# Goal seeking solver

*This page documents an*

**experimental**feature. Please tell us if you experience any problems.There is a single-variable goal-seeking solver -- similar to the 'goal seek' functionality in spreadsheets -- implemented as an EXTERNAL method call. The solver used is a Brent solver^{[1]}, and it can easily wrap around any other solver that can be invoked from a METHOD declaration (currently this includes QRSlv only). Below is a working example from models/test/brent.a4c, also reproduced below.

The line

EXTERNAL brent(SELF,err,x);

can be interpreted as saying 'solve the variable `err` for a value of 0, by varying the value of `x` between `x.lower_bound` and `x.upper_bound`'. For `brent` to work, you must provide a method named `solve`; the recommended contents of that method is as shown below, using the `senstivity/solve` module. This method is called each `err(x)` needs to be evaluated.

The variable `err` will be considered 'solved' when the absolute value of `err` is less than 1.0e-7 times `err.nominal`. If you want to alter the solving tolerance, the only easy way to do so is to modify `err.nominal`: the value 1.0e-7 is hard-wired into the `brent` routine.

The most common problem when using this routine is that you won't have properly 'bracketed' your solution. At the bounds of `x`, the sign of the variable `err` must be opposite; ie the variable must certainly have a root, if the relationship `err(x)` is continuous.

Note that one could in principle nest several of these brent routines, but only by using submodels, and by carefully choosing what to put in your `solve` method.

REQUIRE "atoms.a4l"; IMPORT "johnpye/brent/brent"; IMPORT "sensitivity/solve"; MODEL brent1; x IS_A solver_var; y IS_A solver_var; z IS_A solver_var; y = -x^2 - 4*x + 4; z = sin(x); err IS_A solver_var; err = y - z; METHODS METHOD on_load; FIX x; x.lower_bound := 0; x.upper_bound := 10; err.nominal := 1; RUN intersect; END on_load; METHOD solve; EXTERNAL do_solve(SELF); END solve; METHOD intersect; EXTERNAL brent(SELF,err,x); END intersect; END brent1;