---
title: "Migrating from dust 1.x.x"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Migrating from dust 1.x.x}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

This vignette discusses key differences with dust version 1.  Version 2 of dust is a full rewrite, and some features have moved out of the package, some have moved in from `mcstate` and others have not yet been implemented.

If you have not used previous versions of `dust` and `mcstate` (e.g., via `odin.dust`), you do not need to read this vignette.

```{r}
library(dust2)
```

# Dude, where's my feature?

Features now found elsewhere:

* The random number generation support is now found in [`monty`](https://mrc-ide.github.io/monty); this affects very few users.

Features now included:

* The particle filter is now fully implemented in dust, and no longer part of `mcstate` (now `monty`)

Not yet implemented:

* GPU compilation (a rewrite is planned for 2025)
* "Restart" a particle filter
* Multi-phase systems (not believed used except [`sircovid`](https://mrc-ide.github.io/sircovid))

# Change in meaning of time in discrete-time models

Previously, discrete time models used `step` to count steps forward as unsigned integers, usually from zero. Many systems added a parameter (or constant) `dt` representing the timestep and then a variable `time` which represented the time as a real-valued number. For example you might have `dt` of 0.25 and then your system stops at times `[0, 0.25, 0.5, 0.75, 1]` for steps `[0, 1, 2, 3, 4]`.  This created a point of difference with continuous time models, which were (and still are) based on real-valued time, and was particularly confusing for "mixed time" systems with a mix of both discrete-time and continuous-time components.

In `dust2`, time in all systems is real valued, and starts at 0 by default, though this can be set on initialisation.  For discrete time models, the default `dt` is 1 (though this default can be changed in the system generator, see `vignette("writing")`), which means that if you never thought about `dt` before you can use `dust2` without thinking any more about this.

# New interface

The new interface is completely different, following feedback about the discoverability and documentation of features within the package.  We've also generally tried to make the functions more self-contained, less magic, and easier to understand.  Some lesser-used functions have been removed entirely.  We apologise for the inconvenience that this will cause in migrating old code, but unfortunately this cannot be done automatically.

Previously, dust generators were "[R6 classes](https://r6.r-lib.org/)", which were created using `$new()` and then interacted with using methods (e.g., `sys$run()`.  In contrast, `dust2` uses free functions to create systems and to interact with these systems once created.

In this table, consider the dust system `sir`, which is available via `dust_example()` in both versions of the package.  In dust 1.0.0 we could allocate a system with 10 particles, set the initial conditions, run it forward for 20 time units and return the state matrix by writing:

```r
sir <- dust_example("sir")
sys <- sir$new(pars = list(dt = 1), time = 0, n_particles = 10)
sys$run(10)
```

And in dust2 we could write

```{r}
sir <- dust_example("sir")
sys <- dust_system_create(sir, pars = list(), time = 0, n_particles = 10)
dust_system_set_state_initial(sys)
dust_system_run_to_time(sys, 10)
dust_system_state(sys)
```

There are more lines here in version 2, but each is more predictable and it is easier to find documentation.

First the core methods that represent most usage:

Action        | dust 1.x.x         | dust2
--------------+--------------------+---------------------------------
Allocate      | `$new()`           | `dust_system_create()` (1)
Run to time   | `$run()`           | `dust_system_create()` (2)
Simulate      | `$simulate()`      | `dust_system_simulate()`
Update state  | `$update_state()`  | `dust_system_set_state()` (3)
              |                    | `dust_system_set_state_initial()`
              |                    | `dust_system_set_time()`
              |                    | `dust_system_set_pars()`
Get state     | `$state()`         | `dust_system_state()`
Get time      | `$time()`          | `dust_system_time()`
Reorder       | `$reorder()`       | `dust_system_reorder()`
Get RNG state | `$rng_state()`     | `dust_system_rng_state()`
Set RNG state | `$set_rng_state()` | `dust_system_set_rng_state()`
Get last pars | `$pars()`          | (not yet implemented)

1. No longer set initial conditions into the model
2. No longer returns state at the end
3. The `$update_state()` method was always too complex

Access to some read-only properties has changed slightly, typically just dropping the function call.

Action              | dust 1.x.x            | dust2
--------------------+-----------------------+---------------------------------
Get name            | `$name()`             | `$name`
State size          | `$n_state()`          | `$n_state`
Number of particles | `$n_particles()`      | `$n_particles` (1)
                    | `$n_particles_each()` |
Number of groups    | `$n_pars()`           | `$n_groups`
Number of threads   | `$n_threads()`        | `$n_threads`
Supports compare    | `$has_compare()`      | `$properties$has_compare`
Supports OpenMP     | `$has_openmp()`       | (not yet implemented)

1. Previously, the number of particles was much less well defined (running multiple groups was always implemented after support for running a single group).  `n_particles` now represents the number of particles *per group*.

Some less used methods were removed entirely:

* `$shape()`: previously returned the dimension structure among groups.  We do not currently support this concept and we do not believe anyone used it.
* `$run_adjoint()`: this was to support proof-of-concept calculation of derivatives, which has moved into `dust_likelihood_last_gradient()`
* `$set_index()`, `$index()`: the concept of an "index" was to support efficient running of the particle filter when that was implemented in R in the `mcstate` package.  We had two "indexes" to consider - one for saving trajectories and the other for the comparison to data.  With the particle filter now entirely written in C++ this is no longer needed.
* `$set_stochastic_schedule()`: we had the concept of a "stochastic schedule" to support mixed time models.  This schedule is now set via `dt` on construction.
* `$resample()`: this existed to debug the particle filter and is no longer needed.
* `$info()`: was mostly used to return information about packing of variables within model state.  This is now done with "packers"; see `dust_unpack_state()` and `dust_unpack_index()`
* `$has_gpu_support()`, `$uses_gpu()`, `$get_gpu_info()`: we no longer support any GPU models
* `$real_size()`: we no longer encourage running in single precision (this was needed for running on GPUs)
* `$rng_algorithm()`: while you can change the random number generation algorithm, typically no-one did
* `$set_data()`, `$filter()`: these methods existed to support the previous version of the particle filter.  Data is no longer set into a system and one would now use `dust_filter_create()` or `dust_unfilter_create()`

# See also

* The [`odin2` migration guide](https://mrc-ide.github.io/odin2/articles/migrating.html)
