A grab-bag of things to be aware of when writing code that will get used in TMB.

Arrays are one dimensional under the hood

A tmbutils::Array, whilst based on an Eigen array, manages dimensions itself. As a result if you call any inherited Eigen methods, dimensions can disappear.

From https://kaskr.github.io/adcomp/structtmbutils_1_1array.html:

Methods that are not documented here are inherited from the Eigen library and applied on the underlying n-by-1 array. In general this will yield surprising results for 2D specific array methods.

Has to be some kind of return value

The return value in a g3 model, ``nll’’, can’t just be a hard coded value, has to be e.g. a parameter There has to be at least 1 parameter, otherwise there will be an Eigen error on return.

Obviously not a huge practical problem, but easily crops up in unit tests.

Autofilling vectors

Can’t do vector = single_value, have to use vector.setConstant(single_value).

g3 will mostly handle this automatically, but seems like something that could be fixed in TMB.

VECTORIZE1_t macros

(documented in https://github.com/kaskr/adcomp/pull/329 )

The “R-like” functions TMB provides, such as lgamma() are defined using the VECTORIZE macros. These macros expect a single symbol, and will produce mysterious errors if an expression is used.

Instead of lgamma(alpha + beta), do something like:

lgamma_arg = alpha + beta; val_vec = val_vec + lgamma(lgamma_arg);

No vector to vector conversion

Can’t do stock__num.col(...) = (integer vector), since this needs an explicit cast. This is problematic for e.g:

g3a_initialconditions(prey_a, ~10 * prey_a__minlen)

This case is a somewhat artifical construct, and not a problem for midlen (which isn’t integer), a more likely scenario.

No easy solutions, since gadget3 doesn’t have enough type information and Eigen needs explicit casts.

TMB::gdbsource(interactive = TRUE) eats stderr

(documented in https://github.com/kaskr/adcomp/issues/341)

Any error messages in gdb are lost, which makes for a frustrating console experience. Instead run the new R session yourself, with:

R -d gdb
(gdb) run --vanilla < /tmp/RtmpysTVvW/file3da4a6f13a80c.R

Subsetting is by-reference

Subsetting will be by reference, unlike R. i.e the following will report 0:

DATA_ARRAY(x);
auto y = x.col(0);
x.col(0).setZero();
REPORT(y)

This is particuarly problematic with g3_with, that currently uses auto to save deriving types properly.

A workaround is to force a copy to a vector, either by filling a vector<Type> variable or adding .vec(). See stock__premigrate in R/action_migrate.R.