Skip to content

Commit eb353ea

Browse files
committed
Version 2.2.0
1 parent 18c4821 commit eb353ea

File tree

6 files changed

+88
-12
lines changed

6 files changed

+88
-12
lines changed

docs/CHANGELOG.md

+20-2
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,37 @@ nav_order: 11
88

99
All notable user-facing changes to the `dae-cpp` project are documented in this page.
1010

11-
## v2.1.1
11+
## v2.2.0
1212

1313
New
1414
{: .label .label-green }
1515

16-
Version 2.1.x allows the user to define the shape (structure) of the Jacobian matrix. I.e., instead of providing analytic Jacobian (or not providing it at all, which is slow if the system is large enough), the user can specify the positions of non-zero elements in the Jacobian. The solver will use automatic differentiation for the specified elements only. This works nearly as fast as analytic Jacobian without requiring the user to differentiate the vector function manually.
16+
In version 2.2.x, the solver can reduce the time step size and redo the current time step until a certain condition is met.
17+
This is useful if the solver needs to stop when, for example, one of the variables should reach the given value, and the solver should not "overshoot".
18+
This version also includes several important updates, such as bug fixes and corrections for compiler warnings.
19+
20+
- Added `solver_command::command` enum with [Solution Manager](solution-manager.html) functor return values. Used to send "commands" to the solver from the user-defined Solution Manager
21+
- The user can request the solver to decrease the time step size
22+
- The user can request the solver to decrease the time step size and then redo the current time step
23+
- Fix parentheses warning in `autodiff`
24+
- Fix `-Wall` and `-Wextra` warnings (e.g., "reorder" and "unused variable" warnings)
25+
- Switch from `uint32_t` to `int32_t` for `int_type`
26+
- Switch from `uint64_t` to `int64_t` for `int_type` if `DAECPP_LONG` is defined
27+
- Fix the relative error check
28+
- Fix situation when the solver can decrease and then immediately increase the time step
29+
- Fix tolerances for single precision
30+
31+
## v2.1.1
1732

1833
- Fixed bug when the solver could not recover from divergence and could not redo the last time step correctly
1934
- Type `dual_type` deprecated but supported, added `state_value` instead as it is clearer
2035
- Added `recover_from_linsolver_failure` solver option (`true` by default). Now the solver will try to recover from the linear solver failure (e.g., on the matrix decomposition step) by rolling back and decreasing the time step.
2136

2237
## v2.1.0
2338

39+
Version 2.1.x allows the user to define the shape (structure) of the Jacobian matrix. I.e., instead of providing analytic Jacobian (or not providing it at all, which is slow if the system is large enough),
40+
the user can specify the positions of non-zero elements in the Jacobian. The solver will use automatic differentiation for the specified elements only. This works nearly as fast as analytic Jacobian without requiring the user to differentiate the vector function manually.
41+
2442
- Added [`daecpp::JacobianMatrixShape`](jacobian-matrix.html#jacobian-matrix-shape) and [`daecpp::VectorFunctionElements`](vector-function.html#element-by-element-vector-function-to-define-the-jacobian-shape) helper classes to define the Jacobian matrix shape and the vector function
2543
- Added [`daecpp::JacobianCompare`](jacobian-matrix.html#jacobian-matrix-check) class that helps the user to compare the user-defined Jacobian (either defined explicitly or using Jacobian shape) with the one computed automatically from the system RHS
2644
- Added [Jacobian shape](https://github.com/dae-cpp/dae-cpp/blob/master/examples/jacobian_shape/jacobian_shape.cpp) and [Jacobian compare](https://github.com/dae-cpp/dae-cpp/blob/master/examples/jacobian_compare/jacobian_compare.cpp) examples

docs/examples.md

-3
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ layout: default
44
nav_order: 10
55
---
66

7-
Work in progress
8-
{: .label .label-red }
9-
107
# Examples
118

129
## Quick Start

docs/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ layout: home
44
nav_order: 1
55
---
66

7-
![version](https://img.shields.io/badge/version-2.1.1-blue)
7+
![version](https://img.shields.io/badge/version-2.2.0-blue)
88

99
<p align="center">
1010
<img src="../assets/images/logo.png" alt="dae-cpp logo" width="250"/>

docs/prerequisites.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ using namespace daecpp;
2626

2727
| Type | Equivalent to | Note |
2828
| ---- | ------------- | ---- |
29-
| `daecpp::int_type` | `uint32_t` (default), <br> `uint64_t` if `DAECPP_LONG` is defined | Unsigned integer type, used for sparse matrix indices |
29+
| `daecpp::int_type` | `int32_t` (default), <br> `int64_t` if `DAECPP_LONG` is defined | Integer type, used for sparse matrix indices |
3030
| `daecpp::float_type` | `double` (default), <br> `float` if `DAECPP_SINGLE` is defined | Floating point scalar, used for sparse matrix coefficients |
3131
| `daecpp::state_vector` | `std::vector<float_type>` | State vector, used, for example, to define the initial condition |
3232
| `daecpp::state_type` | `autodiff::VectorXreal` | State vector, used for the [vector function](vector-function.html) definition so that it can be automatically (algorithmically) differentiated using [`autodiff`](https://autodiff.github.io/) package |

docs/solution-manager.md

+65-4
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ nav_order: 6
66

77
# Solution Manager class
88

9-
The Solution Manager class can serve as a solution observer and/or as an event function that stops computation when a certain event occurs. Solution Manager functor will be called every time step, providing the time `t` and the corresponding solution vector `x` for the user for further post-processing. If the functor returns an integer which is not equal to `0` (i.e., `true`), the computation will immediately stop.
9+
The Solution Manager class can serve as a solution observer and/or as an event function that stops computation (or reduces the time step) when a certain event occurs. Solution Manager functor will be called every time step, providing the time `t` and the corresponding solution vector `x` for the user for further post-processing. If the functor returns an integer which is not equal to `0` (or `daecpp::solver_command::continue_integration`), the solver behaviour will depend on the return value of the functor:
10+
11+
- If the functor returns `daecpp::solver_command::stop_intergration` (or any other integer except defined below), the computation will immediately stop.
12+
- `daecpp::solver_command::decrease_time_step`: the solver will continue integration but the next time step will be reduced by a factor of `dt_decrease_factor` from the `SolverOptions` class.
13+
- `daecpp::solver_command::decrease_time_step_and_redo`: the solver will abort the current time step and will redo it with the decreased (by a factor of `dt_decrease_factor`) time step.
14+
15+
The solver commands can be useful in the situations when the solver needs to stop once one of the variables reaches the given value, and the solver should not "overshoot".
16+
An example of the Solution Manager class that "tells" the solver to decrease the time step and stop when the variable reaches the given value with the given tolerance is provided [below](#example-2).
1017

1118
The solver provides a derived from the Solution Manager class called [`daecpp::Solution`](#solution-class), which writes the solution vector `x` and time `t` every time step or every specific times defined by the user into the [Solution Holder](#solution-holder) object. The user can access this object for further post-processing, printing the solution on the screen or writing it to a file.
1219

@@ -26,19 +33,19 @@ public:
2633
{
2734
// Solution Manager definition
2835

29-
return 0; // Returns 0 by default or an integer != 0 to stop the computation
36+
return 0; // Returns 0 by default (or `daecpp::solver_command::continue_integration`)
3037
}
3138
};
3239
```
3340

3441
The operator `()` will be called every time step, providing the user with the current state `x` and the corresponding time `t`.
35-
If the functor returns non-zero integer, the computation will stop.
42+
If the functor returns `daecpp::solver_command::stop_intergration`, the computation will stop.
3643
The user is free to define the solution container and save the solution within the Solution Manager class. The solver provides [`SolutionHolder`](#solution-holder) helper class that stores solution vectors `x` and the corresponding times `t`.
3744

3845
{: .note }
3946
The type of vector `x` in the class definition above is `daecpp::state_vector`, which is an alias of `std::vector<float_type>` type. See [`dae-cpp` types](https://dae-cpp.github.io/prerequisites.html#dae-cpp-types) section for more information.
4047

41-
## Example
48+
## Example 1
4249

4350
In the following example, we define a custom Solution Manager that performs the following 3 tasks:
4451

@@ -80,6 +87,60 @@ Vectors `x_sol` and `t_sol` should be defined before calling the `UserDefinedSol
8087

8188
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`.
8289

90+
## Example 2
91+
92+
In the example below, consider the analytic solution is `x[0] = 2 - t`, so `x[0] = 1` at time `t = 1`.
93+
Imagine we need to stop integration when `x[0] = 1` exactly (with the given tolerance).
94+
Here is an example of the Solution Manager class that can be used to achieve that:
95+
96+
```cpp
97+
constexpr double tol{1e-6}; // Tolerance
98+
99+
class UserDefinedSolutionManager
100+
{
101+
daecpp::SolutionHolder &m_sol;
102+
103+
bool m_keep_reducing_time_step{false};
104+
105+
void m_save_solution(const daecpp::state_vector &x, const double t)
106+
{
107+
m_sol.x.emplace_back(x);
108+
m_sol.t.emplace_back(t);
109+
}
110+
111+
public:
112+
UserDefinedSolutionManager(daecpp::SolutionHolder &sol) : m_sol(sol) {}
113+
114+
int operator()(const daecpp::state_vector &x, const double t)
115+
{
116+
// Stop once x[0] == 1.0 (with the given tolerance)
117+
if (std::abs(x[0] - 1.0) < tol)
118+
{
119+
m_save_solution(x, t);
120+
return daecpp::solver_command::stop_intergration;
121+
}
122+
123+
// In case the solver "overshoots" and x[0] is below 1.0
124+
if (x[0] < 1.0)
125+
{
126+
m_keep_reducing_time_step = true;
127+
return daecpp::solver_command::decrease_time_step_and_redo;
128+
}
129+
130+
m_save_solution(x, t);
131+
132+
// The x[0] value is getting close to 1.0 but we need to reduce the time step
133+
// to avoid "overshooting"
134+
if (m_keep_reducing_time_step)
135+
{
136+
return daecpp::solver_command::decrease_time_step;
137+
}
138+
139+
return daecpp::solver_command::continue_integration;
140+
}
141+
};
142+
```
143+
83144
----
84145
85146
# Solution Holder class

docs/utilities.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ daecpp::version_patch
3232
The timer measures time spent by the program in the given scope and saves it in **milliseconds** in a variable of type `double`:
3333

3434
```cpp
35-
double time{0.0}; // Stores time (in ms)
35+
double time{}; // Stores time (in ms)
3636
{
3737
daecpp::Timer timer(&time); // Starts the timer
3838

0 commit comments

Comments
 (0)