FullMatrix
The FullMatrix class is part of the Sofa Linear Algebra module and provides an implementation for a full matrix container. This component is designed to store and manipulate dense matrices, which are matrices where most elements have non-zero values.
- abstract
- The FullMatrix class provides dense matrix storage and manipulation for numerical computations in physics-based simulations.
- sheet
- # FullMatrix **Overview**: The FullMatrix class is part of the Sofa Linear Algebra module, providing an implementation for a full (dense) matrix container. It supports efficient storage and manipulation of matrices with non-zero elements. ## Mathematical Model The FullMatrix represents dense matrices using a one-dimensional array `data` in row-major order. Given dimensions `nRow` (number of rows) and `nCol` (number of columns), the element at position \\( (i, j) \\) can be accessed as: egin{equation} A_{ij} = data[i \cdot pitch + j] \end{equation} where `pitch` is typically set to `nCol`. The class supports basic matrix operations such as multiplication with vectors and matrices, addition of values, and clearing elements. ## Parameters and Data The FullMatrix does not expose any significant data fields. Its functionality relies on methods for accessing and manipulating the matrix elements. Key methods include: - `operator[](Index i)`: Returns a pointer to the start of row \\(i\\). - `element(Index i, Index j)`: Returns the value at position \\( (i, j) \\). - `set(Index i, Index j, double v)`: Sets the element at position \\( (i, j) \\) to value \\(v\\). - `add(Index i, Index j, double v)`: Adds value \\(v\\) to the element at position \\( (i, j) \\). - `clear(Index i, Index j)`: Clears the element at position \\( (i, j) \\). These methods enable efficient manipulation of dense matrices for numerical computations in physics-based simulations.
- name
- Sofa.LinearAlgebra.FullMatrix
- title
- Full Matrix Component in Sofa Linear Algebra Module
- category
- Linear Algebra
- description
- The FullMatrix class is part of the Sofa Linear Algebra module and provides an implementation for a full matrix container. This component is designed to store and manipulate dense matrices, which are matrices where most elements have non-zero values.
- parameters
-
- {'name': 'nbRow', 'type': 'int', 'description': 'The number of rows in the matrix.', 'required': True}
- {'name': 'nbCol', 'type': 'int', 'description': 'The number of columns in the matrix.', 'required': True}
- methods
-
- {'name': 'resize(nbRow, nbCol)', 'description': "Resize the matrix to have 'nbRow' rows and 'nbCol' columns."}
- {'name': 'rowSize()', 'returnType': 'int', 'description': 'Returns the number of rows in the matrix.'}
- {'name': 'colSize()', 'returnType': 'int', 'description': 'Returns the number of columns in the matrix.'}
- {'name': 'element(i, j)', 'returnType': 'Real', 'description': 'Accesses and returns the element at position (i,j) in the matrix.', 'parameters': [{'name': 'i', 'type': 'int', 'description': 'The row index of the element to access'}, {'name': 'j', 'type': 'int', 'description': 'The column index of the element to access'}]}
- {'name': 'set(i, j, v)', 'returnType': '', 'description': "Sets the value 'v' at position (i,j) in the matrix.", 'parameters': [{'name': 'i', 'type': 'int', 'description': 'The row index of the element to set'}, {'name': 'j', 'type': 'int', 'description': 'The column index of the element to set'}, {'name': 'v', 'type': 'double', 'description': 'The value to be assigned at position (i,j)'}]}
- {'name': 'add(i, j, v)', 'returnType': '', 'description': "Adds 'v' to the element at position (i,j) in the matrix.", 'parameters': [{'name': 'i', 'type': 'int', 'description': 'The row index of the element'}, {'name': 'j', 'type': 'int', 'description': 'The column index of the element'}, {'name': 'v', 'type': 'double', 'description': 'The value to be added at position (i,j)'}]}
- {'name': 'clear(i, j)', 'returnType': '', 'description': 'Clears or sets to zero the element at position (i,j) in the matrix.', 'parameters': [{'name': 'i', 'type': 'int', 'description': 'The row index of the element'}, {'name': 'j', 'type': 'int', 'description': 'The column index of the element'}]}
- {'name': 'clearRow(i)', 'returnType': '', 'description': "Clears or sets to zero all elements in row 'i'.", 'parameters': [{'name': 'i', 'type': 'int', 'description': 'The index of the row to clear'}]}
- {'name': 'clearCol(j)', 'returnType': '', 'description': "Clears or sets to zero all elements in column 'j'.", 'parameters': [{'name': 'j', 'type': 'int', 'description': 'The index of the column to clear'}]}
- {'name': 'clearRowCol(i)', 'returnType': '', 'description': "Clears or sets to zero all elements in both row 'i' and column 'i'.", 'parameters': [{'name': 'i', 'type': 'int', 'description': 'The index of the row and column to clear'}]}
- {'name': 'clear()', 'returnType': '', 'description': 'Clears or sets to zero all elements in the matrix.'}
- {'name': 'operator*(v)', 'returnType': 'FullVector<Real>', 'description': 'Performs a matrix-vector multiplication, returning a new vector as a result.', 'parameters': [{'name': 'v', 'type': 'FullVector<Real>', 'description': 'The input vector to multiply with the matrix'}]}
- {'name': 'mul(res, b)', 'returnType': '', 'description': "Performs in-place matrix-vector multiplication and stores result in 'res'.", 'parameters': [{'name': 'res', 'type': 'FullVector<Real>', 'description': 'The output vector to store the result'}, {'name': 'b', 'type': 'FullVector<Real>', 'description': 'The input vector'}]}
- {'name': 'mulT(res, b)', 'returnType': '', 'description': "Performs in-place matrix-vector multiplication with the transpose of this matrix and stores result in 'res'.", 'parameters': [{'name': 'res', 'type': 'FullVector<Real>', 'description': 'The output vector to store the result'}, {'name': 'b', 'type': 'FullVector<Real>', 'description': 'The input vector'}]}
- {'name': 'operator*(m)', 'returnType': 'FullMatrix<Real>', 'description': 'Performs matrix-matrix multiplication, returning a new matrix as a result.', 'parameters': [{'name': 'm', 'type': 'FullMatrix<Real>', 'description': 'The input matrix to multiply with the current matrix'}]}
- {'name': 'mul(res, m)', 'returnType': '', 'description': "Performs in-place matrix-matrix multiplication and stores result in 'res'.", 'parameters': [{'name': 'res', 'type': 'FullMatrix<Real>', 'description': 'The output matrix to store the result'}, {'name': 'm', 'type': 'FullMatrix<Real>', 'description': 'The input matrix'}]}
- {'name': 'mulT(res, m)', 'returnType': '', 'description': "Performs in-place matrix-matrix multiplication with the transpose of this matrix and stores result in 'res'.", 'parameters': [{'name': 'res', 'type': 'FullMatrix<Real>', 'description': 'The output matrix to store the result'}, {'name': 'm', 'type': 'FullMatrix<Real>', 'description': 'The input matrix'}]}
- example
- The FullMatrix class is useful when working with dense matrices that don't benefit from sparse representations. It can be used for various operations such as matrix-vector multiplication, matrix-matrix multiplication, and modifying the values within a matrix. Example usage: ```cpp FullMatrix<double> mat(3, 3); // Create a 3x3 full matrix mat.set(0, 1, 2.5); // Set value at position (0, 1) double val = mat.element(0, 1); // Get the value at position (0, 1) - should return 2.5 FullVector<double> vec(3); // Create a vector of size 3 mat.mul(res, vec); // Perform matrix-vector multiplication and store result in 'res' ``` This example shows basic operations such as setting values within the matrix and performing matrix-vector multiplication.
- limitations
- The FullMatrix class is designed for dense matrices. If working with sparse data (where most elements are zero), using a full matrix may be inefficient both in terms of memory usage and computational performance. In such cases, other specialized sparse matrix representations would be more suitable.
- maths
- The FullMatrix class in the Sofa Linear Algebra module provides an implementation for a dense matrix container, which is essential for numerical computations in physics-based simulations. A dense matrix is one where most elements are non-zero, and it is represented using a two-dimensional array structure. This class allows efficient storage and manipulation of these matrices, which can be critical for solving systems of linear equations that arise in various physical models such as those used to simulate deformable objects or rigid body dynamics. **Mathematical Description:** - **Matrix Representation**: The FullMatrix is represented by a one-dimensional array `data` where the elements are stored in row-major order. The dimensions of the matrix are given by `nRow` (number of rows) and `nCol` (number of columns). Additionally, there is a `pitch`, which is typically set to `nCol` unless otherwise specified. - **Accessing Elements**: Access to elements within the matrix is provided through various methods. The method `operator[](Index i)` returns a pointer to the start of row `i`. Element access can be performed using `element(Index i, Index j)`, which returns the value at row `i` and column `j`. Methods like `set(Index i, Index j, double v)` allow setting an element's value. - **Operations**: The FullMatrix supports basic matrix operations such as multiplication with vectors (`mul`) and other matrices (`operator*`). It also includes methods for adding values to specific elements (`add`), clearing individual elements (`clear`), and entire rows or columns. **Physical Description: In Physics-based Simulations:** - **Deformable Objects**: FullMatrix is often used in simulations of deformable objects where the finite element method (FEM) is applied. The stiffness matrix, a dense matrix representing the linear elasticity properties of the object, can be modeled using FullMatrix. - **Rigid Body Dynamics**: In rigid body dynamics, when solving for forces and constraints, the Jacobian matrix might be represented as a FullMatrix. This allows efficient computation of the system's state during each simulation step. - **Efficiency Considerations**: While full matrices are straightforward to use due to their dense structure, they can become computationally expensive for large-scale problems. The Sofa Linear Algebra module provides other sparse matrix implementations (like Compressed Sparse Row Format) that might be more efficient depending on the problem's sparsity.
{
"name": "FullMatrix",
"main": {
"name": "FullMatrix",
"namespace": "sofa::linearalgebra",
"module": "Sofa.framework.LinearAlgebra",
"include": "sofa/linearalgebra/FullMatrix.h",
"doc": "Simple full matrix container",
"inherits": [
"BaseMatrix"
],
"templates": [
"double",
"float"
],
"data_fields": [],
"links": [],
"methods": [
{
"name": "ptr",
"return_type": "Real *",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "begin",
"return_type": "LineIterator",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "end",
"return_type": "LineIterator",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "operator[]",
"return_type": "Real *",
"params": [
{
"name": "i",
"type": "Index"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "resize",
"return_type": "void",
"params": [
{
"name": "nbRow",
"type": "Index"
},
{
"name": "nbCol",
"type": "Index"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "rowSize",
"return_type": "Index",
"params": [],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "colSize",
"return_type": "Index",
"params": [],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "element",
"return_type": "SReal",
"params": [
{
"name": "i",
"type": "Index"
},
{
"name": "j",
"type": "Index"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "set",
"return_type": "void",
"params": [
{
"name": "i",
"type": "Index"
},
{
"name": "j",
"type": "Index"
},
{
"name": "v",
"type": "double"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "add",
"return_type": "void",
"params": [
{
"name": "i",
"type": "Index"
},
{
"name": "j",
"type": "Index"
},
{
"name": "v",
"type": "double"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "clear",
"return_type": "void",
"params": [
{
"name": "i",
"type": "Index"
},
{
"name": "j",
"type": "Index"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "clearRow",
"return_type": "void",
"params": [
{
"name": "i",
"type": "Index"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "clearCol",
"return_type": "void",
"params": [
{
"name": "j",
"type": "Index"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "clearRowCol",
"return_type": "void",
"params": [
{
"name": "i",
"type": "Index"
}
],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "clear",
"return_type": "void",
"params": [],
"is_virtual": true,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "operator*",
"return_type": "FullVector<Real>",
"params": [
{
"name": "v",
"type": "const FullVector<Real> &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "mul",
"return_type": "void",
"params": [
{
"name": "res",
"type": "FullVector<Real> &"
},
{
"name": "b",
"type": "const FullVector<Real> &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "mulT",
"return_type": "void",
"params": [
{
"name": "res",
"type": "FullVector<Real> &"
},
{
"name": "b",
"type": "const FullVector<Real> &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "operator*",
"return_type": "FullMatrix<Real>",
"params": [
{
"name": "m",
"type": "const FullMatrix<Real> &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "mul",
"return_type": "void",
"params": [
{
"name": "res",
"type": "FullMatrix<Real> &"
},
{
"name": "m",
"type": "const FullMatrix<Real> &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "mulT",
"return_type": "void",
"params": [
{
"name": "res",
"type": "FullMatrix<Real> &"
},
{
"name": "m",
"type": "const FullMatrix<Real> &"
}
],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": false,
"access": "public"
},
{
"name": "Name",
"return_type": "const char *",
"params": [],
"is_virtual": false,
"is_pure_virtual": false,
"is_static": true,
"access": "public"
}
]
},
"desc": {
"name": "Sofa.LinearAlgebra.FullMatrix",
"title": "Full Matrix Component in Sofa Linear Algebra Module",
"category": "Linear Algebra",
"description": "The FullMatrix class is part of the Sofa Linear Algebra module and provides an implementation for a full matrix container. This component is designed to store and manipulate dense matrices, which are matrices where most elements have non-zero values.",
"parameters": [
{
"name": "nbRow",
"type": "int",
"description": "The number of rows in the matrix.",
"required": true
},
{
"name": "nbCol",
"type": "int",
"description": "The number of columns in the matrix.",
"required": true
}
],
"methods": [
{
"name": "resize(nbRow, nbCol)",
"description": "Resize the matrix to have 'nbRow' rows and 'nbCol' columns."
},
{
"name": "rowSize()",
"returnType": "int",
"description": "Returns the number of rows in the matrix."
},
{
"name": "colSize()",
"returnType": "int",
"description": "Returns the number of columns in the matrix."
},
{
"name": "element(i, j)",
"returnType": "Real",
"description": "Accesses and returns the element at position (i,j) in the matrix.",
"parameters": [
{
"name": "i",
"type": "int",
"description": "The row index of the element to access"
},
{
"name": "j",
"type": "int",
"description": "The column index of the element to access"
}
]
},
{
"name": "set(i, j, v)",
"returnType": "",
"description": "Sets the value 'v' at position (i,j) in the matrix.",
"parameters": [
{
"name": "i",
"type": "int",
"description": "The row index of the element to set"
},
{
"name": "j",
"type": "int",
"description": "The column index of the element to set"
},
{
"name": "v",
"type": "double",
"description": "The value to be assigned at position (i,j)"
}
]
},
{
"name": "add(i, j, v)",
"returnType": "",
"description": "Adds 'v' to the element at position (i,j) in the matrix.",
"parameters": [
{
"name": "i",
"type": "int",
"description": "The row index of the element"
},
{
"name": "j",
"type": "int",
"description": "The column index of the element"
},
{
"name": "v",
"type": "double",
"description": "The value to be added at position (i,j)"
}
]
},
{
"name": "clear(i, j)",
"returnType": "",
"description": "Clears or sets to zero the element at position (i,j) in the matrix.",
"parameters": [
{
"name": "i",
"type": "int",
"description": "The row index of the element"
},
{
"name": "j",
"type": "int",
"description": "The column index of the element"
}
]
},
{
"name": "clearRow(i)",
"returnType": "",
"description": "Clears or sets to zero all elements in row 'i'.",
"parameters": [
{
"name": "i",
"type": "int",
"description": "The index of the row to clear"
}
]
},
{
"name": "clearCol(j)",
"returnType": "",
"description": "Clears or sets to zero all elements in column 'j'.",
"parameters": [
{
"name": "j",
"type": "int",
"description": "The index of the column to clear"
}
]
},
{
"name": "clearRowCol(i)",
"returnType": "",
"description": "Clears or sets to zero all elements in both row 'i' and column 'i'.",
"parameters": [
{
"name": "i",
"type": "int",
"description": "The index of the row and column to clear"
}
]
},
{
"name": "clear()",
"returnType": "",
"description": "Clears or sets to zero all elements in the matrix."
},
{
"name": "operator*(v)",
"returnType": "FullVector<Real>",
"description": "Performs a matrix-vector multiplication, returning a new vector as a result.",
"parameters": [
{
"name": "v",
"type": "FullVector<Real>",
"description": "The input vector to multiply with the matrix"
}
]
},
{
"name": "mul(res, b)",
"returnType": "",
"description": "Performs in-place matrix-vector multiplication and stores result in 'res'.",
"parameters": [
{
"name": "res",
"type": "FullVector<Real>",
"description": "The output vector to store the result"
},
{
"name": "b",
"type": "FullVector<Real>",
"description": "The input vector"
}
]
},
{
"name": "mulT(res, b)",
"returnType": "",
"description": "Performs in-place matrix-vector multiplication with the transpose of this matrix and stores result in 'res'.",
"parameters": [
{
"name": "res",
"type": "FullVector<Real>",
"description": "The output vector to store the result"
},
{
"name": "b",
"type": "FullVector<Real>",
"description": "The input vector"
}
]
},
{
"name": "operator*(m)",
"returnType": "FullMatrix<Real>",
"description": "Performs matrix-matrix multiplication, returning a new matrix as a result.",
"parameters": [
{
"name": "m",
"type": "FullMatrix<Real>",
"description": "The input matrix to multiply with the current matrix"
}
]
},
{
"name": "mul(res, m)",
"returnType": "",
"description": "Performs in-place matrix-matrix multiplication and stores result in 'res'.",
"parameters": [
{
"name": "res",
"type": "FullMatrix<Real>",
"description": "The output matrix to store the result"
},
{
"name": "m",
"type": "FullMatrix<Real>",
"description": "The input matrix"
}
]
},
{
"name": "mulT(res, m)",
"returnType": "",
"description": "Performs in-place matrix-matrix multiplication with the transpose of this matrix and stores result in 'res'.",
"parameters": [
{
"name": "res",
"type": "FullMatrix<Real>",
"description": "The output matrix to store the result"
},
{
"name": "m",
"type": "FullMatrix<Real>",
"description": "The input matrix"
}
]
}
],
"example": "The FullMatrix class is useful when working with dense matrices that don't benefit from sparse representations. It can be used for various operations such as matrix-vector multiplication, matrix-matrix multiplication, and modifying the values within a matrix.\n\nExample usage:\n```cpp\nFullMatrix<double> mat(3, 3); // Create a 3x3 full matrix\nmat.set(0, 1, 2.5); // Set value at position (0, 1)\ndouble val = mat.element(0, 1); // Get the value at position (0, 1) - should return 2.5\nFullVector<double> vec(3); // Create a vector of size 3\nmat.mul(res, vec); // Perform matrix-vector multiplication and store result in 'res'\n```\nThis example shows basic operations such as setting values within the matrix and performing matrix-vector multiplication.",
"limitations": "The FullMatrix class is designed for dense matrices. If working with sparse data (where most elements are zero), using a full matrix may be inefficient both in terms of memory usage and computational performance. In such cases, other specialized sparse matrix representations would be more suitable."
},
"maths": {
"maths": "The FullMatrix class in the Sofa Linear Algebra module provides an implementation for a dense matrix container, which is essential for numerical computations in physics-based simulations. A dense matrix is one where most elements are non-zero, and it is represented using a two-dimensional array structure. This class allows efficient storage and manipulation of these matrices, which can be critical for solving systems of linear equations that arise in various physical models such as those used to simulate deformable objects or rigid body dynamics.\n\n**Mathematical Description:**\n- **Matrix Representation**: The FullMatrix is represented by a one-dimensional array `data` where the elements are stored in row-major order. The dimensions of the matrix are given by `nRow` (number of rows) and `nCol` (number of columns). Additionally, there is a `pitch`, which is typically set to `nCol` unless otherwise specified.\n\n- **Accessing Elements**: Access to elements within the matrix is provided through various methods. The method `operator[](Index i)` returns a pointer to the start of row `i`. Element access can be performed using `element(Index i, Index j)`, which returns the value at row `i` and column `j`. Methods like `set(Index i, Index j, double v)` allow setting an element's value.\n\n- **Operations**: The FullMatrix supports basic matrix operations such as multiplication with vectors (`mul`) and other matrices (`operator*`). It also includes methods for adding values to specific elements (`add`), clearing individual elements (`clear`), and entire rows or columns. \n\n**Physical Description: In Physics-based Simulations:**\n- **Deformable Objects**: FullMatrix is often used in simulations of deformable objects where the finite element method (FEM) is applied. The stiffness matrix, a dense matrix representing the linear elasticity properties of the object, can be modeled using FullMatrix.\n\n- **Rigid Body Dynamics**: In rigid body dynamics, when solving for forces and constraints, the Jacobian matrix might be represented as a FullMatrix. This allows efficient computation of the system's state during each simulation step.\n\n- **Efficiency Considerations**: While full matrices are straightforward to use due to their dense structure, they can become computationally expensive for large-scale problems. The Sofa Linear Algebra module provides other sparse matrix implementations (like Compressed Sparse Row Format) that might be more efficient depending on the problem's sparsity.\n"
},
"summary": {
"abstract": "The FullMatrix class provides dense matrix storage and manipulation for numerical computations in physics-based simulations.",
"sheet": "# FullMatrix\n\n**Overview**: The FullMatrix class is part of the Sofa Linear Algebra module, providing an implementation for a full (dense) matrix container. It supports efficient storage and manipulation of matrices with non-zero elements.\n\n## Mathematical Model\nThe FullMatrix represents dense matrices using a one-dimensional array `data` in row-major order. Given dimensions `nRow` (number of rows) and `nCol` (number of columns), the element at position \\\\( (i, j) \\\\) can be accessed as:\n\n\begin{equation}\n A_{ij} = data[i \\cdot pitch + j]\n\\end{equation}\nwhere `pitch` is typically set to `nCol`. The class supports basic matrix operations such as multiplication with vectors and matrices, addition of values, and clearing elements.\n\n## Parameters and Data\nThe FullMatrix does not expose any significant data fields. Its functionality relies on methods for accessing and manipulating the matrix elements. Key methods include:\n- `operator[](Index i)`: Returns a pointer to the start of row \\\\(i\\\\).\n- `element(Index i, Index j)`: Returns the value at position \\\\( (i, j) \\\\).\n- `set(Index i, Index j, double v)`: Sets the element at position \\\\( (i, j) \\\\) to value \\\\(v\\\\).\n- `add(Index i, Index j, double v)`: Adds value \\\\(v\\\\) to the element at position \\\\( (i, j) \\\\).\n- `clear(Index i, Index j)`: Clears the element at position \\\\( (i, j) \\\\).\n\nThese methods enable efficient manipulation of dense matrices for numerical computations in physics-based simulations."
}
}