Skip to content

Commit 2d1c171

Browse files
committed
Minor corrections and changes
1 parent ac37aae commit 2d1c171

10 files changed

+29
-27
lines changed

Diff for: docs/examples.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,13 @@ Simple DAE source file example: [simple_dae.cpp](https://github.com/dae-cpp/dae-
2222
{: .fs-5 .fw-400 }
2323

2424
Here we solve another simple system of DAEs.
25-
This example introduces [Solution Manager](solution-manager.html), that will work as solution observer.
25+
This example introduces [Solution Manager](solution-manager.html), that will work as a solution observer.
2626

2727
## Perovskite model
2828

2929
Perovskite model source file example: [perovskite.cpp](https://github.com/dae-cpp/dae-cpp/blob/master/examples/perovskite_model/perovskite.cpp)
3030
{: .fs-5 .fw-400 }
3131

32-
A more sophisticated example, where we solve a big DAE system that describes potential distribution and ion concentration in a perovskite solar cell.
32+
A more sophisticated example, where we solve a big DAE system that describes the potential distribution and ion concentration in a perovskite solar cell.
3333
We show how to add parameters to the user-defined mass matrix, vector function, and Jacobian.
3434
This example also demonstrates a custom [Solution Manager](solution-manager.html) implementation that can work as an observer and event function.

Diff for: docs/index.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ to be solved in the interval $$t \in [0, t_\mathrm{end}]$$ with the given initia
2323

2424
### How does it work
2525

26-
The DAE solver uses implicit Backward Differentiation Formulae (BDF) of orders I-IV with adaptive time stepping. Every time step, the BDF integrator reduces the original DAE system to a system of nonlinear equations, which is solved using iterative [Quasi-Newton](https://en.wikipedia.org/wiki/Quasi-Newton_method) root-finding algorithm. The Quasi-Newton method reduces the problem further down to a system of linear equations, which is solved using [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page), a versatile and fast C++ template library for linear algebra.
26+
The DAE solver uses implicit Backward Differentiation Formulae (BDF) of orders I-IV with adaptive time stepping. Every time step, the BDF integrator converts the original DAE system to a system of nonlinear equations, which is solved using iterative [Quasi-Newton](https://en.wikipedia.org/wiki/Quasi-Newton_method) root-finding algorithm. The Quasi-Newton method reduces the problem further down to a system of linear equations, which is solved using [Eigen](https://eigen.tuxfamily.org/index.php?title=Main_Page), a versatile and fast C++ template library for linear algebra.
2727
Eigen's sparse solver performs two steps: factorization (decomposition) of the Jacobian matrix and the linear system solving itself. This gives us the numerical solution of the entire DAE system at the current time step. Finally, depending on the convergence rate of the Quasi-Newton method, variability of the solution, and user-defined accuracy, the DAE solver adjusts the time step size and initiates a new iteration in time.
2828

2929
### The main features of the solver
3030

3131
- Header only, no pre-compilation required.
32-
- Uses automatic (algorithmic, exact) differentiation ([autodiff](https://autodiff.github.io/)) to compute the Jacobian matrix, if it is not provided by the user.
32+
- Uses [automatic](https://en.wikipedia.org/wiki/Automatic_differentiation) (algorithmic, exact) differentiation (using [autodiff](https://autodiff.github.io/)) to compute the Jacobian matrix, if it is not provided by the user.
3333
- Fourth-order implicit BDF time integrator that preserves accuracy even when the time step rapidly changes.
3434
- A very flexible and customizable variable time stepping algorithm based on the solution stability and variability.
3535
- Mass matrix can be non-static (can depend on time) and it can be singular.

Diff for: docs/jacobian-matrix.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ nav_order: 5
77

88
# Jacobian Matrix class
99

10-
The Jacobian matrix class defines the Jacobian matrix $$\mathbf{J}(\mathbf{x}, t)$$ of the DAE system.
10+
The Jacobian Matrix class defines the Jacobian matrix $$\mathbf{J}(\mathbf{x}, t)$$ of the DAE system.
1111
This matrix can be obtained by differentiating the vector function (the RHS) $$\mathbf{f}(\mathbf{x}, t)$$ of the DAE system
1212

1313
$$\mathbf{M}(t) \frac{\mathrm{d}\mathbf{x}}{\mathrm{d}t} = \mathbf{f}(\mathbf{x}, t)$$
@@ -112,7 +112,7 @@ For more information about defining the matrix in sparse format, refer to the [S
112112
The solver provides a helper class `daecpp::JacobianAutomatic` to compute the Jacobian matrix for the given vector function $$\mathbf{f}(\mathbf{x}, t)$$ algorithmically using [`autodiff`](https://autodiff.github.io/) package.
113113
For relatively small systems, the user does not even need to define the Jacobian, not even automatic one. This will be handled by the solver itself. Behind the scenes, the solver will create an automatic Jacobian matrix object for the user, if analytic Jacobian is not provided.
114114
115-
However, in some cases, it can be difficult to derive the Jacobian matrix analytically. Or if the user has provided the Jacobian matrix, but the solution diverges, which means there might be a bug in the Jacobian matrix definition. In these cases, the user can try to feed the automatic Jacobian matrix to the solver explicitly, or print out (or save to a file) both user-defined and automatic Jacobians for comparison to find possible errors in the matrix definition.
115+
For big systems, it is highly recommended to provide analytic (user-defined) Jacobian. However, in some cases, it can be difficult to derive the Jacobian matrix analytically. Or the user has provided the Jacobian matrix, but the solution diverges, which means there might be a bug in the Jacobian matrix definition. In these cases, the user can try to feed the automatic Jacobian matrix to the solver explicitly, or print out (or save to a file) both user-defined and automatic Jacobians for comparison to find possible errors in the matrix definition.
116116
117117
In order to construct an automatic Jacobian matrix object, the user needs to provide the vector function object `rhs` (see [Vector Function class](vector-function.html) section):
118118

Diff for: docs/mass-matrix.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ nav_order: 3
77

88
# Mass Matrix class
99

10-
The Mass matrix class defines the mass matrix $$\mathbf{M}(t)$$ of the DAE system written in the matrix-vector form:
10+
The Mass Matrix class defines the mass matrix $$\mathbf{M}(t)$$ of the DAE system written in the matrix-vector form:
1111

1212
$$\mathbf{M}(t) \frac{\mathrm{d}\mathbf{x}}{\mathrm{d}t} = \mathbf{f}(\mathbf{x}, t).$$
1313

@@ -91,7 +91,7 @@ In the example above, we created an object `identityMatrix` which holds an ident
9191

9292
## Zero mass matrix
9393

94-
Similar ot the example above, a helper class `daecpp::MassMatrixZero` can be used to construct a zero matrix (a matrix filled by zeros only). This matrix can be useful to solve pure algebraic systems without time derivatives.
94+
Similar ot the example above, a helper class `daecpp::MassMatrixZero` can be used to construct a zero matrix (a matrix filled with zeros only). This matrix can be useful to solve pure algebraic systems without time derivatives.
9595

9696
```cpp
9797
daecpp::MassMatrixZero zeroMatrix; // Creates empty mass matrix for algebraic system

Diff for: docs/quick-start.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ or simply
124124
my_system.solve({0, 1}, 1.0);
125125
```
126126
127-
Solution vector of vectors `x` and the corresponding vector of times `t` will be stored in `my_system.sol.x` and `my_system.sol.t`, respectively.
127+
Vector of solution vectors `x` and the corresponding vector of times `t` will be stored in `my_system.sol.x` and `my_system.sol.t`, respectively.
128128
129129
The entire C++ code is provided in the [Quick Start example](https://github.com/dae-cpp/dae-cpp/blob/master/examples/quick_start/quick_start.cpp).
130130
@@ -156,21 +156,23 @@ struct MyJacobian
156156
};
157157
```
158158

159-
Then add the user-defined Jacobian to the DAE system definition:
159+
Then add the user-defined Jacobian to the `solve()` method:
160160

161161
```cpp
162-
System my_system(mass, rhs, MyJacobian()); // Defines the DAE system with Jacobian
162+
my_system.solve(x0, t, MyJacobian()); // Starts the computation with Jacobian
163163
```
164164

165+
Defining the analytic Jacobian matrix can significantly speed up the computation (especially for big systems).
166+
165167
For more information about defining the Jacobian matrix, see [Jacobian Matrix class](jacobian-matrix.html) description.
166168

167169
### (Optional) Step 6. Tweak the solver options
168170

169171
For example, restrict the maximum time step:
170172

171173
```cpp
172-
my_system.opt.dt_max = 0.1; // Update `dt_max`
173-
my_system.solve({0, 1}, 1.0); // Restart the computation
174+
my_system.opt.dt_max = 0.1; // Update `dt_max`
175+
my_system.solve(x0, t, MyJacobian()); // Restart the computation
174176
```
175177

176178
See [Solver Options class](solver-options.html) description for more information.

Diff for: docs/solution-manager.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public:
7878
{: .warning }
7979
Vectors `x_sol` and `t_sol` should be defined before calling the `UserDefinedSolutionManager` constructor and must live until the end of the computation. They shouldn't be passed to the constructor as temporary objects and must **not** go out of scope before finishing the system solving (otherwise, this will lead to dangling references `&m_x_sol` and `&m_t_sol` in the class definition above).
8080

81-
Similar to the mass matrix, vector function, Jacobian matrix definitions, inhereting the `daecpp::SolutionManager` class is a good practice (it serves as a blueprint), but it is not necessary. The user is allowed to define custom Solution Managers without inhereting `daecpp::SolutionManager`.
81+
Similar to the mass matrix, vector function and Jacobian matrix definitions, inhereting the `daecpp::SolutionManager` class is a good practice (it serves as a blueprint), but it is not necessary. The user is allowed to define custom Solution Managers without inhereting `daecpp::SolutionManager`.
8282

8383
----
8484

@@ -128,7 +128,7 @@ sol.print({0, 1, 42});
128128
129129
# Solution class
130130
131-
Solution class `daecpp::Solution` is derived from `daecpp::SolutionManager` and serves as a basic solution *observer* that writes solution vectors `x` and the corresponding times `t` every time step or every specific time from `t_output` vector (that can be optionally provided in the constructor) into `daecpp::SolutionHolder` class object. The Solution class is also used in the [`daecpp::System`](solve.html) class as a default Solution Manager.
131+
Solution class `daecpp::Solution` is derived from `daecpp::SolutionManager` and serves as a basic solution *observer* that writes solution vectors `x` and the corresponding times `t` every time step or every specific time from `t_output` vector (that can be optionally provided in the constructor) into `daecpp::SolutionHolder` class object. The Solution class is also used in the [`daecpp::System`](solve.html#system-class) class as a default Solution Manager.
132132
133133
## Solution class constructor
134134

Diff for: docs/solve.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ In this section, we consider both approaches to start the computation.
1818

1919
# System class
2020

21-
The `System` class serves as a wrapper for lower level [`daecpp::solve(...)`](#daecppsolve-function) function calls. Contains the [Solver Options](solver-options.html) and [Solution Holder](solution-manager.html#solution-holder-class) objects.
21+
The `System` class serves as a wrapper for lower level [`daecpp::solve(...)`](#daecppsolve-function) function calls. The class allows the user to easily set up the DAE system, solve it, and get the result. The class already contains the [Solver Options](solver-options.html) and [Solution Holder](solution-manager.html#solution-holder-class) objects.
2222

2323
## System class public members
2424

@@ -51,8 +51,8 @@ Here is the summary of the `solve(...)` method:
5151
| Parameter | Type(s) | Description |
5252
| --------- | ------- | ----------- |
5353
| `x0` | `const daecpp::state_vector &` | The initial condition (initial state vector) |
54-
| `t` | `const double` **or** `const std::vector<double> &` | Integration interval `[0, t]` **or** a vector of integration times (useful if the user need the output at particular times `t`) |
55-
| `jacobian` | User-defined [Jacobian Matrix](jacobian-matrix.html) | **(Optional)** Jacobian matrix (matrix of the RHS derivatives) |
54+
| `t` | `const double` **or** `const std::vector<double> &` | Integration interval `[0, t]` **or** a vector of integration times (useful if the user needs the output at particular times `t`) |
55+
| `jacobian` | User-defined [Jacobian Matrix](jacobian-matrix.html) | **(Optional)** User-defined Jacobian matrix (matrix of the RHS derivatives) |
5656
5757
## Examples
5858
@@ -82,7 +82,7 @@ int status = my_system.solve({0, 1}, 1.0, MyJacobian()); // Solves the system wi
8282

8383
if(!status)
8484
{
85-
my_system.sol.print(); // Prints solution on screen
85+
my_system.sol.print(); // Prints solution on screen if solution is successfull
8686
}
8787
```
8888
@@ -110,9 +110,9 @@ Here is the summary of the `solve(...)` function:
110110
| `rhs` | User-defined [Vector Function](vector-function.html) | Vector function (the RHS) of the DAE system |
111111
| `jac` | User-defined [Jacobian Matrix](jacobian-matrix.html) | **(Optional)** Jacobian matrix (matrix of the RHS derivatives) |
112112
| `x0` | `const daecpp::state_vector &` | The initial condition (initial state vector) |
113-
| `t` | `const double` **or** `const std::vector<double> &` | Integration interval `[0, t]` **or** a vector of integration times (useful if the user need the output at particular times `t`) |
113+
| `t` | `const double` **or** `const std::vector<double> &` | Integration interval `[0, t]` **or** a vector of integration times (useful if the user needs the output at particular times `t`) |
114114
| `sol_mgr` | User-defined [Solution Manager](solution-manager.html) | Solution manager (solution observer and/or event function) |
115-
| `opt` | `const daecpp::SolverOptions &` | **(Optional)** Solver options |
115+
| `opt` | `const daecpp::SolverOptions &` | **(Optional)** [Solver options](solver-options.html) |
116116
117117
## Exit codes
118118

Diff for: docs/solver-options.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ nav_order: 7
66

77
# Solver Options class
88

9-
The Solver Options class, `daecpp::SolverOptions`, allows the user to redefine and fine-tune the DAE solver options. To do so, the user should create an object of the Solver Options class, update parameters of interest by accessing public variables (see [example](#example) below), and then provide the updated object to the solver function `solve`.
9+
The Solver Options class, `daecpp::SolverOptions`, allows the user to redefine and fine-tune the DAE solver options. To do so, the user should create an object of the Solver Options class, update parameters of interest by accessing public variables (see [example](#example) below), and then provide the updated object to the solver function [`solve`](solve.html).
1010

1111
The table below contains a complete list of all options accessible via the Solver Options class.
1212

@@ -25,7 +25,7 @@ The table below contains a complete list of all options accessible via the Solve
2525
| `Newton_scheme` | `unsigned` | `1` | Non-linear solver algorithm: <br> `0` - Classic Newton method (usually the most stable but the slowest), <br> `1` (default) - Quasi-Newton method I (balanced with focus on stability, updates Jacobian and performs factorization every 2nd iteration), <br> `2` - Quasi-Newton method II (balanced with focus on speed, updates Jacobian and performs factorization every 3rd iteration), <br> `3` - Quasi-Newton method III (can be the fastest but less stable, may require tweaking the time step increase/decrease thresholds, updates Jacobian and performs factorization every 4th iteration). |
2626
| `is_mass_matrix_static` | `bool` | `false` | If `true`, the mass matrix will be updated only once (at the beginning of computation). Setting this option as `true` slightly speeds up the computation, but the mass matrix must be static (i.e., it must be independent on time). |
2727
| `max_Jacobian_updates` | `int` | `8` | Maximum number of the Jacobian matrix updates and factorizations per time step. If the algorithm fails to converge after `max_Jacobian_updates` Jacobian matrix updates and factorizations per time step, the Newton iterations will be considered as diverged. The solver will try to roll back and decrease the time step. |
28-
| `max_Newton_failed_attempts` | `unsigned` | `3` | If the Newton method fails to converge 'max_Newton_failed_attempts' times in a row, the solver will try to update Jacobian matrix every single iteration next time step (for Quasi-Newton methods). |
28+
| `max_Newton_failed_attempts` | `unsigned` | `3` | If the Newton method fails to converge `max_Newton_failed_attempts` times in a row, the solver will try to update Jacobian matrix every single iteration next time step (for Quasi-Newton methods). |
2929
| `dt_increase_threshold_delta` | `int` | `0` | Time step amplification threshold delta. Can be negative or positive integer number. The solver increases the time step if the number of successful Newton iterations per time step is less than the threshold. <br> **Example:** If the solver increases the time step too often, decrease the time step amplification threshold by setting `dt_increase_threshold_delta` to `-1`. |
3030
| `dt_decrease_threshold_delta` | `int` | `0` | Time step reduction threshold delta. Can be negative or positive integer number. The solver decreases the time step if the number of successful Newton iterations per time step is greater than the threshold. <br> **Example:** If the solver struggles to converge but keeps doing many Newton iterations without reducing the time step, decrease the time step reduction threshold by setting `dt_decrease_threshold_delta` to `-1` (or `-2` and less). |
3131
| `solution_variability_control` | `bool` | `true` | Turns ON/OFF solution variability control. Solution variability control tightens up the adaptive time stepping algorithm, and it is ON by default. Switching it OFF can lead to a significant speed boost for big systems, but it can also lead to instability. |

Diff for: docs/sparse-matrix.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ std::cout << M.dense(3) << '\n'; // Prints matrix M on screen assuming it's a 3x
2424
The three-array format defines a sparse matrix using two (unsigned) integer vectors of indices `i` and `j` and one floating-point vector `A` of the corresponding non-zero elements of the matrix. Only non-zero elements of the sparse matrix should be defined and stored. Theoretically, all three arrays can be empty. This will define a zero matrix where all elements are zeros.
2525

2626
{: .note }
27-
All three arrays `i`, `j`, and `A` should be the same size. This can be (and will be) checked by calling the `void check()` method of the class `daecpp::sparse_matrix`.
27+
All three arrays `i`, `j`, and `A` should be the same size. This can be (and will be) checked by calling the [`void check()`](#void-check-const) method of the class `daecpp::sparse_matrix`.
2828

2929
Here is an example of a sparse matrix:
3030

@@ -64,7 +64,7 @@ The row and column numeration starts from `0`.
6464
For `float_type` and `int_type` definition, refer to the [Prerequisites](prerequisites.html#dae-cpp-types) section.
6565

6666
{: .note }
67-
All three vectors are initially empty an NOT preallocated
67+
All three vectors are initially empty and **not** preallocated.
6868

6969
## Sparse Matrix class methods
7070

@@ -189,4 +189,4 @@ Converts matrix from `dae-cpp` three-array format to `Eigen::SparseMatrix` forma
189189
## `std::size_t N_elements() const`
190190
191191
<br>
192-
Returns the number of non-zero elements in the matrix.
192+
Returns the number of non-zero elements in the matrix (including duplicates, if any).

Diff for: docs/vector-function.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ nav_order: 4
77

88
# Vector Function class
99

10-
The Vector function class defines the (nonlinear) vector function (the RHS) $$\mathbf{f}(\mathbf{x}, t)$$ of the DAE system written in the matrix-vector form:
10+
The Vector Function class defines the (nonlinear) vector function (the RHS) $$\mathbf{f}(\mathbf{x}, t)$$ of the DAE system written in the matrix-vector form:
1111

1212
$$\mathbf{M}(t) \frac{\mathrm{d}\mathbf{x}}{\mathrm{d}t} = \mathbf{f}(\mathbf{x}, t).$$
1313

0 commit comments

Comments
 (0)