# Dynare 4.5.7 → 6.3 Migration Notes

Based on updating and debugging `BCGmodelcomp_nash_c1dpd_c2dpd`.

---

## 1. `_steadystate.m` files

### Function signature
```matlab
% Dynare 4
function [ys,check] = MODELNAME_steadystate(junk,ys)

% Dynare 6
function [ys,params,check] = MODELNAME_steadystate(ys,exo,M_,options_)
```

### Remove global declarations
```matlab
% Remove entirely:
global M_
global M_ params paramlist param_switch sensitivity_switch paramfile_name
```

### Return parameters via output argument (not M_.params)
```matlab
% Dynare 4
nparams = size(M_.param_names,1);
for icount = 1:nparams
    eval(['M_.params(icount) = ',M_.param_names(icount,:),';'])
end

% Dynare 6
nparams = size(M_.param_names,1);
params = nan(nparams,1);
for icount = 1:nparams
    eval(['params(icount) = ',M_.param_names{icount},';'])
end
```

### Return steady-state values (curly-brace indexing)
```matlab
% Dynare 4
for i_indx = 1:nvars
    eval(['ys(i_indx)=',M_.endo_names(i_indx,:),';'])
end

% Dynare 6
for i_indx = 1:nvars
    eval(['ys(i_indx)=',M_.endo_names{i_indx},';'])
end
```

### Nash/Ramsey files: static call and guess call

```matlab
% Dynare 4
[ys] = guess_MODELNAME_steadystate('');
optys = fsolve(@(ys) MODELNAME_static(ys,exog,M_.params), ys, options);

% Dynare 6
[ys,~,~] = guess_MODELNAME_steadystate(ys,exo,M_,options_);
ys = fsolve(@(ys) MODELNAME.static(ys,exog,params), ys, options);
```

The Dynare 6 package `+MODELNAME/static.m` has the same `(y,x,params)` interface as
the old `MODELNAME_static.m`, so switching to dot notation is sufficient.
Pass the local `params` variable (not `M_.params`, which is no longer populated).

### `guess_` helper files
Same signature/indexing updates as above. Unused inputs (`ys` input, `exo`, `options_`)
should be replaced with `~` to suppress lint warnings:
```matlab
function [ys,params,check] = guess_MODELNAME_steadystate(~,~,M_,~)
```

---

## 2. `_ss_defs.m` files

### `M_.endo_names` indexing in loops

Dynare 6 stores `M_.endo_names` as a **cell array of strings**, not a 2-D char array.
Any loop that builds `_ss` variables must use curly-brace indexing:

```matlab
% Dynare 4
varstring = deblank(M_.endo_names(i_indx,:));
if isempty(strfind(varstring,'mult')) & ...
    eval([varstring,'_ss = ',deblank(varstring),';']);

% Dynare 6
varstring = M_.endo_names{i_indx};
if isempty(strfind(varstring,'mult')) && ...
    eval([varstring,'_ss = ',varstring,';']);
```

Using `(i_indx,:)` in Dynare 6 returns a 1×1 cell; `strfind` on a cell returns a cell;
`isempty` on a non-empty cell is always `false` — so **no `_ss` variables get created**,
causing downstream "Unrecognized variable" errors.

---

## 3. `.mod` files — parameter seeding for preprocessor normalization

### The problem
Dynare 6's preprocessing step "Normalizing the static model" evaluates the static
model Jacobian numerically. For this it needs parameter values. Any parameter not
assigned in the `.mod` file defaults to **1** in the preprocessor's evaluation.

With default value 1, certain expressions become singular:
- `log(exp(c1c) - 1*exp(c1clag)) = log(0)` → **ERROR: log(0) not defined!**
- Coefficients like `c1beta - 1 = 0` make Jacobian entries zero, which the
  scoring algorithm hits with `log(0)` internally.

This error appears even if the MATLAB steadystate function sets the correct values,
because normalization runs **before** the steadystate function is called (but after
`.mod` file parameter assignments are applied, which is why the seed block works).

### The fix
Add explicit parameter assignments in the `.mod` file, after all `var`/`varexo`/
`parameters` declaration blocks and **immediately before** `model;`:

```dynare
// Seed parameter values for Dynare 6 preprocessor normalization.
// The steadystate function overwrites these at runtime.
c1kappa = 0.5;
c1beta  = 0.995024875621891;
// ... all other parameters ...

model;
```

**Important placement rule:** the assignment block must come after ALL declaration
blocks (`var`, `varexo`, `parameters`). Placing it between two `var` blocks causes
the preprocessor to ignore it.

### Practical approach
Use MATLAB to compute the values from the existing paramfile and print them
in Dynare assignment format:
```matlab
BCGmodelcomp_nash_c1dpd_c2dpd_paramfile;
fprintf('%s = %.15g;\n', 'c1kappa', c1kappa);
% ... etc.
```
Then paste the output into the `.mod` file. The steadystate function will
overwrite these values with identical ones at runtime, so there is no
risk of inconsistency as long as the paramfile is not changed without
also updating the `.mod` seed block.

---

## 4. Ramsey models — additional `initval` block for Lagrange multipliers

### The problem

Parameter seeding (section 3) fixes log(0) errors caused by bad parameter defaults.
But Ramsey models have a second, independent source of log(0): **structural zeros in
the static Jacobian caused by Lagrange multipliers defaulting to zero.**

Ramsey FOC equations (one per private-sector variable, say `c1c`) take the form:

```
lmult_j * ∂(constraint_j)/∂c1c  +  lmult_k * ∂(constraint_k)/∂c1c  +  ... = 0
```

Every term is proportional to a multiplier. When all `lmult = 0` (the default at
normalization time), the equation evaluates to zero **and** its Jacobian w.r.t.
`c1c` is also zero (`Σ lmult_j * ∂²constraint_j/∂c1c²` = 0). The normalization
scoring algorithm takes `log(|0|)` and fails.

### Why Nash models don't have this problem

Nash FOC equations are the policymakers' optimality conditions w.r.t. their
*instruments* (interest rate, price target, etc.). The instrument appears with a
non-zero coefficient regardless of multiplier values, so the Jacobian of the FOC
w.r.t. that instrument is non-zero at `lmult = 0`. The normalization algorithm
always finds a valid assignment without hitting log(0).

In short: Ramsey FOCs are second-order conditions (multipliers × first derivatives
of constraints) that vanish structurally when multipliers are zero. Nash FOCs are
first-order conditions w.r.t. specific instruments that retain non-zero Jacobian
entries regardless.

### The fix

Add an `initval` block after the `shocks` block (and before `steady;`) that sets
all Lagrange multipliers to a small non-zero value:

```dynare
initval;
lmult1 = 1e-4;
lmult2 = 1e-4;
// ... all lmult variables ...
lmult76 = 1e-4;
end;

steady;
```

The `initval` block is applied before normalization runs, making all Jacobian entries
non-zero. The external `_steadystate.m` file then overwrites these values when
computing the actual steady state — there is no conflict.

### What does not work

- **`model(block);`**: Block decomposition uses a different (graph-based) matching
  algorithm and avoids numerical Jacobian evaluation in principle, but in practice
  it did **not** resolve the log(0) error for `BCGmodelcomp_ramsey_c1dpd_c2dpd`.
  Both the parameter seed block and the `initval` block are required.

---

## Summary of files changed per model (BCGmodelcomp_nash_c1dpd_c2dpd example)

| File | Changes |
|------|---------|
| `MODELNAME_steadystate.m` | New signature, remove globals, `params` output, `{}` indexing, updated guess/static calls |
| `guess_MODELNAME_steadystate.m` | Same signature/indexing updates, unused inputs → `~` |
| `MODELNAME_ss_defs.m` | `M_.endo_names{i_indx}` instead of `deblank(M_.endo_names(i_indx,:))` |
| `MODELNAME.mod` | Add full parameter seed block before `model;` |

### Additional changes for Ramsey models (`BCGmodelcomp_ramsey_*`)

| File | Changes |
|------|---------|
| `MODELNAME.mod` | Parameter seed block before `model;` **plus** `initval` block with all `lmult` variables set to `1e-4` before `steady;` |
