# Find root of a function defined as a Module

I have a simple module like

BCdet[x_, y_] := Module[
{AuxMat},
AuxMat = Mat /. {f -> x, A -> y};
Det[AuxMat]
]


where Mat is a normal matrix 12x12 with parameters f and A. The above defined module returns a complex number and it works without any problems.

Then I would like to find root of its real part for given A=trailA and for a complex f

FindRoot[
Re[BCdet[f, trialA]],
{f, 2.5 + 0. I},
StepMonitor :> Print["Step to f = ", f]
]


Unfortunately, this does not work at all. I cannot get any result. I use StepMonitor to check it, however, it does not give any output. Any idea where might be the problem?

• But as I understood, this evaluates function only when its argument is a number. I think this must be obeyed in the example with FindRoot, isn't it? Jul 31 '13 at 9:17

You may consider making Mat a function of f and A. Or if you wish to work with your code, make sure f and A do not have values. FindRoot temporarily gives f a value in your example. Therefore in your code the replacement rule for f will be broken. However, this is usually not a problem as f will be given its value simply by evaluation. But it does show the risk of making a function like this. If you give A a value, then it does not make a difference what you set trialA to, as the rule for A will be broken.

Fortunately we have

x /. {3.3 -> 5}


x

but it would be terrible if 3.3 would appear on the LHS of /., as you would then get an undesired replacement . This is not what makes your code fail to work however. Consider these definitions

Mat2[A_, f_] := {{A + I, f}, {A + f, A + f + 3 I}}

BCdet[x_, y_] := Module[
{AuxMat},
AuxMat = Mat2[y,x];
Det[AuxMat]
]


Now, for me it works if we simply do

FindRoot[BCdet[x, trialA], {x, 5}]


-> {x -> 3.01955 + 7.45469 I}

And we have

Abs[BCdet[3.019546672440941 + 7.454686341385149 I, trialA]]


2.99373*10^-14

Which is pretty close to 0. However, you code does not work

FindRoot[Re[BCdet[x, trialA]], {x, 5}]


--messages--> The line search decreased the step size to within tolerance...

I suppose you can leave out the Re as without the Re FindRoot will find a solution with a small real part anyway. But that is a bit ugly.

Remarks

If you wish to do still use replacement rules, at least use HoldPattern. But first another suggestion. If you don't want to do

BCdet[f_, A_] :=  Det[{{A + I, f}, {A + f, A + f + 3 I}}]


Because Mat is so big, or because you want to reuse/change Mat, you can do something like

Clear[A, f]

Mat = {{A + I, f}, {A + f, A + f + 3 I}};

With[
{Mat = Mat}
,
BCdet[f_, A_] :=  Det[Mat]
]


I suggest you work with regular functions so I don't have to explain everything below :P. This would make your code work but it is really inconvenient:

Clear[A,f]
With[
{Mat = {{A + I, f}, {A + f, A + f + 3 I}}}
,
BCdet[x_, y_] :=
Module[{AuxMat},
AuxMat = Unevaluated[Mat] /. {HoldPattern[f] -> x, HoldPattern[A] -> y};
Det[AuxMat]]
]

• Thanks, I always use Clear[f,A]. Finally, it seems that adding BCdet[x_?NumericQ, y_?NumericQ] to the definition helped. Unfortunately, I do not understand why. I guess, the arguments always must be numbers. Jul 31 '13 at 10:00
• @LLapsus note that there is still a risk because f is given a value by FindRoot. You might get undesired replacements still, but it is very unlikely. Jul 31 '13 at 10:02