Solving an equation matrix with NDSolve

Imagine I want to solve the following matrix system of equations $$\begin{pmatrix} \dot{x}_{11} & \dot{x}_{12} & \dot{x}_{13}\\ \dot{x}_{21} & \dot{x}_{22} & \dot{x}_{23}\\ \dot{x}_{31} & \dot{x}_{32} & \dot{x}_{33} \end{pmatrix}= \begin{pmatrix} a_{11}x_{11} & a_{12}x_{12} & a_{13}x_{13}\\ a_{21}x_{21} & a_{22}x_{22} & a_{23}x_{23}\\ a_{31}x_{31} & a_{32}x_{32} & a_{33}x_{33} \end{pmatrix}$$ where $$x_{ij}\equiv x_{ij}(t)$$ and $$\{a_{ij}\}$$ are some real coefficients. When $$\{a_{ij}\}=1$$, we can solve this with NDSolveValue as follows

ini = RandomReal[1, {3, 3}];
sol = NDSolveValue[{
x'[t] == x[t],
x[0] == ini
}, x, {t, 0, 1}]


for some random initial conditions ini (also a matrix). Now, how can I include custom coefficients? Specifically, what if the coefficient matrix is such that the diagonal is zero and all the other entries are 1? That is,

$$\begin{pmatrix} \dot{x}_{11} & \dot{x}_{12} & \dot{x}_{13}\\ \dot{x}_{21} & \dot{x}_{22} & \dot{x}_{23}\\ \dot{x}_{31} & \dot{x}_{32} & \dot{x}_{33} \end{pmatrix}= \begin{pmatrix} 0 & x_{12} & x_{13}\\ x_{21} & 0 & x_{23}\\ x_{31} & x_{32} & 0 \end{pmatrix}$$

I tried setting

coeff = ConstantArray[1, {3, 3}] - IdentityMatrix[3]


followed simply by

ini = RandomReal[1, {3, 3}];
sol = NDSolveValue[{
x'[t] == coeff * x[t],
x[0] == ini
}, x, {t, 0, 1}]


However this doesn't seem to work and I get the error message

which seems to be related with how NDSolveValue is interpreting coeff

I've noticed that, although x[t] within the NDSolve environment can be tretaed as a list or a list of lists, it fails its interpretation in some cases. Any ideas?

• why not work with the vector {x11, x12, x13, x21, x22, x23, x31, x32, x33} instead? Then you can use a matrix-vector dot product on the rhs. If you really need to use a matrix formulation, you can define a function foo[x_List] := coeff x and use that on the rhs. Jun 29 at 18:33
• I really need to use the matrix formulation. How exactly would I do that with the foo function? Jun 29 at 18:34
• use x'[t] == foo[x[t]] Jun 29 at 18:35
• Evaluate x'[t] == coeff x[t]. Since x[t] is not a matrix yet, it is treated as a scalar and x[t] is threaded into the matrix. Using foo prevents this early multiplication. Jun 29 at 18:43
• It is because all of these functions expect their arguments to be Lists. So if you give foo or Dot or Transpose the argument x[t], it won't evaluate and everything will work like you want. Jun 30 at 19:19

As mentioned in the comments, the issue is premature evaluation of the product between coeff and x[t]. Before NDSolve evaluates x[t] with the initial condition, it performs

coeff*x[t] = {{0,x[t],x[t]}, {x[t],0,x[t]},{x[t],x[t],0}}


Then when it substitutes in the initial condition, each of those x[t]s becomes a matrix and you end up with a mess. The idea is to stop the scalar * matrix product happening until x[t] is evaluated to be a matrix. This can be accomplished by using any function which expects a List as an argument and remains unevaluated if the argument is not a list. @CarolWoll suggests in the comments using foo[x_List]:=coeff*x. We can see that

mat={{1,2,3},{4,5,6},{7,8,9}};
coeff*x[t] = {{0,x[t],x[t]},{x[t],0,x[t]},{x[t],x[t],0}}
coeff*x[t] = {{0,x[t],x[t]},{x[t],0,x[t]},{x[t],x[t],0}}/.x[t]->mat =
{{0,{{1,2,3},{4,5,6},{7,8,9}},{{1,2,3},{4,5,6},{7,8,9}}},{{{1,2,3},
{4,5,6},{7,8,9}},0,{{1,2,3},{4,5,6},{7,8,9}}},{{{1,2,3},{4,5,6},{7,8,9}},
{{1,2,3},{4,5,6},{7,8,9}},0}} (* huge mess *)
foo[x[t]]=foo[x[t]]
foo[mat]={{0,2,3},{4,0,6},{7,8,0}} (* as desired *)