From 13709f6853b2fe72dc91297b87dd1f618d1fc9cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= <sebastien@dynare.org>
Date: Fri, 22 Jul 2022 14:34:02 +0200
Subject: [PATCH] =?UTF-8?q?Add=20=E2=80=9Cfsolve=5Foptions=E2=80=9D=20opti?=
 =?UTF-8?q?on=20to=20=E2=80=9Csteady=E2=80=9D=20command?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Closes: #1856
---
 doc/manual/source/the-model-file.rst      | 13 ++++++++++
 matlab/default_option_values.m            |  7 ++++--
 matlab/dynare_solve.m                     |  9 +++++++
 preprocessor                              |  2 +-
 tests/Makefile.am                         |  1 +
 tests/steady_state/ramst_solve_algo_0.mod | 30 +++++++++++++++++++++++
 6 files changed, 59 insertions(+), 3 deletions(-)
 create mode 100644 tests/steady_state/ramst_solve_algo_0.mod

diff --git a/doc/manual/source/the-model-file.rst b/doc/manual/source/the-model-file.rst
index 63ddf0f212..056e9c9028 100644
--- a/doc/manual/source/the-model-file.rst
+++ b/doc/manual/source/the-model-file.rst
@@ -3107,6 +3107,19 @@ Finding the steady state with Dynare nonlinear solver
        accurate solution (low ``markowitz`` values) and the one that preserves 
        maximum sparsity (high ``markowitz`` values). Default: 0.5.
 
+    .. option:: fsolve_options = (NAME, VALUE, ...)
+
+       A list of NAME and VALUE pairs. Can be used to set options for the
+       ``fsolve`` routine, which is selected when ``solve_algo = 0`` (this
+       option has no effect for other values of ``solve_algo``). For the list
+       of available name/value pairs, see the documentation of ``fsolve`` in
+       the MATLAB or Octave manual. Note that Dynare already uses the values of
+       the ``maxit``, ``tolf`` and ``tolx`` options of the ``steady`` command
+       for initializing the corresponding options passed to ``fsolve``, so you
+       should not need to override those. Also note that you should not try to
+       override the value of the ``Jacobian`` or ``SpecifyObjectiveGradient``
+       option.
+
     *Example*
 
     See :ref:`init-term-cond`.
diff --git a/matlab/default_option_values.m b/matlab/default_option_values.m
index aab17a3829..8a1437447c 100644
--- a/matlab/default_option_values.m
+++ b/matlab/default_option_values.m
@@ -107,10 +107,13 @@ options_.bvar_prior_flat = false;
 options_.bvar_prior_train = 0;
 options_.bvar.conf_sig = 0.6;
 
-% Initialize the field that will contain the optimization algorigthm's options declared in the
-% estimation command (if anny).
+% Initialize the field that will contain the optimization algorithm's options declared in the
+% estimation command (if any).
 options_.optim_opt = [];
 
+% Same for options to fsolve
+options_.fsolve_options = [];
+
 % Optimization algorithm [6] gmhmaxlik
 gmhmaxlik.iterations = 3;
 gmhmaxlik.number = 20000;
diff --git a/matlab/dynare_solve.m b/matlab/dynare_solve.m
index ee1c0e35e9..06e2b266dc 100644
--- a/matlab/dynare_solve.m
+++ b/matlab/dynare_solve.m
@@ -189,6 +189,15 @@ if options.solve_algo == 0
     else
         options4fsolve.Display = 'off';
     end
+    %% This one comes last, so that the user can override Dynare
+    if ~isempty(options.fsolve_options)
+        if isoctave
+            eval(['options4fsolve = optimset(options4fsolve,' options.fsolve_options ');']);
+        else
+            eval(['options4fsolve = optimoptions(options4fsolve,' options.fsolve_options ');']);
+        end
+    end
+
     if ~isoctave
         [x, fvec, errorcode, ~, fjac] = fsolve(f, x, options4fsolve, args{:});
     else
diff --git a/preprocessor b/preprocessor
index ad40f1365c..21cecee599 160000
--- a/preprocessor
+++ b/preprocessor
@@ -1 +1 @@
-Subproject commit ad40f1365c8fe791546464e968bb4d86daaddbdd
+Subproject commit 21cecee5990e1541d0721c2a7a554da15b5e8011
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ff3c3a2c7d..22e21be833 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -182,6 +182,7 @@ MODFILES = \
 	steady_state/example1_trust_region.mod \
 	steady_state/example1_block_trust_region.mod \
 	steady_state/Gali_2015_chapter_6_4.mod \
+	steady_state/ramst_solve_algo_0.mod \
 	steady_state_operator/standard.mod \
 	steady_state_operator/use_dll.mod \
 	steady_state_operator/block.mod \
diff --git a/tests/steady_state/ramst_solve_algo_0.mod b/tests/steady_state/ramst_solve_algo_0.mod
new file mode 100644
index 0000000000..93e04819e2
--- /dev/null
+++ b/tests/steady_state/ramst_solve_algo_0.mod
@@ -0,0 +1,30 @@
+% Test solve_algo=0 (fsolve), and its companion “fsolve_options” option
+
+var c k;
+varexo x;
+
+parameters alph gam delt bet aa;
+alph=0.5;
+gam=0.5;
+delt=0.02;
+bet=0.05;
+aa=0.5;
+
+
+model;
+c + k - aa*x*k(-1)^alph - (1-delt)*k(-1);
+c^(-gam) - (1+bet)^(-1)*(aa*alph*x(+1)*k^(alph-1) + 1 - delt)*c(+1)^(-gam);
+end;
+
+initval;
+x = 1;
+k = 1;
+c = 0.1;
+end;
+
+if isoctave
+steady(solve_algo=0, fsolve_options = ('AutoScaling', 'on'));
+elseif user_has_matlab_license('optimization_toolbox')
+%% NB: The Display option is accepted but not honoured under Octave (as of version 7)
+steady(solve_algo=0, fsolve_options = ('Display', 'iter'));
+end
-- 
GitLab