1
$\begingroup$

Perhaps this question has a simple answer, I'm sorry but I unable to get my head around it. Here's a minimal description of my issue.

I have a an equation of the form eq = expr == 0, where expr is a very complicated function of the symbols x and y.

I wish to find the roots of the equation for various values of y. Thus I defined the function:

f = Function[z, {z, x /. FindRoot[eq /. y -> z, {x, 0}]}]

I then define a grid:

 grid = Range[ymin, ymax]

and map over it:

res = Map[f, grid]

Apparently my equation is quite hard to solve as I get:

error message

After playing with it changes to the options of FindRoot such as: adding more iterations, change of method, changing working precision, etc., doesn't help me.

Thus what I would like is to be able to figure out how bad am I doing. My issues are:

  1. I don't know how many times did the execution occur as after a certain amount of times it suppresses the alerts
  2. I don't know if the issues are within a certain domain, in which case I'll know I have a domain where I can't solve my equation. On the other hand maybe the points where I have my issues are sparse in which case maybe I may just ignore them?

In short I would like to add to my code (or have a separate code running over the same grid) some sort of error handler which would do one of two things:

  1. Count exceptions and give me a tally. Preferably it should also defer between different exceptions as FindRoot can throw other exceptions as well.
  2. An even better option is to return a array of exceptions and grid values, in the form: {{excep1, GridVal1},{excep2, GridVal2},{excep3, GridVal3},{excep4,GridVal4}}

I didn't post any attempt as I don't even know how to start. Complete solutions, as weak as general directions will be most welcome.

Update

I still haven't solved my issue. However I gained some intuition regarding my problem. The solution my equation is discontinuous. In a region around the discontinuity I have big oscillations. I could in principle be satisfied with with a solution only within a bounded domain. However, my actual problem involves several equations with several variables, so I'll need this sort of error handler to define the feasible domain.

$\endgroup$
  • $\begingroup$ eq = expr == 0 gives eq a boolean value, i.e. True or False. Mathematica can't find a root of that. Replace eq with expr inside your FindRoot and that may solve the issue. $\endgroup$ – Myridium Mar 2 '17 at 13:22
  • $\begingroup$ of course it can, and to works perfectly except in the region where the solution isn't continuous $\endgroup$ – Yair M Mar 2 '17 at 14:04
  • $\begingroup$ Okay yes, if expr==0 remains unevaluated. $\endgroup$ – Myridium Mar 2 '17 at 14:25
2
$\begingroup$

One way to do it is to use Check, so that when there's a message generated, an appropriate alternative result is returned. I chose Nothing so those results would be simply omitted, with a silly strawman version of f:

f = Function[z, {z, x /. FindRoot[Abs[Sin[x]] == z, {x, 0}]}];

Quiet[Map[Check[f[#], Nothing] &, Range[-0.5, 1.5, 0.1]]]

(* {{0., 0.}, {0.1, 0.100167}, {0.2, 0.201358}, {0.3, 0.304693}, 
    {0.4, 0.411517}, {0.5, 0.523599}, {0.6, 0.643501}, {0.7, 0.775397}, 
    {0.8, 0.927295}, {0.9, 1.11977}, {1., 1.5708}} *)

I wrapped the whole thing in Quiet do avoid a bunch of annoying error messages I knew I was going to get anyway.

EDIT: I don't know a completely reliable way to capture the generated messages (this is a mild annoyance I've encountered repeatedly over the years), but you can hack something together using $MessageList, like this:

Map[Quiet@Check[f[#], $MessageList] &, 
 Range[-0.5, 1.5, 0.1]]
(* {{FindRoot::lstol},{FindRoot::lstol},{FindRoot::lstol},{FindRoot::lstol}, 
    {FindRoot::lstol},{0.,0.},{0.1,0.100167},{0.2,0.201358},{0.3,0.304693},  
    {0.4,0.411517},{0.5,0.523599},{0.6,0.643501},{0.7,0.775397},
    {0.8,0.927295},{0.9,1.11977},{1.,1.5708},{FindRoot::lstol},
    {FindRoot::lstol},{FindRoot::lstol},{FindRoot::lstol},
    {FindRoot::lstol}} *)

As you see, this gets the name of the message, but not the full body. It's more common to use a sentinel value like $Failed or something with head Failure, though. The Quiet is kind of obligatory here or otherwise you'll get the list of all messages generated during the whole computation, and the General::stop message may come up spoiling everything.

$\endgroup$
  • $\begingroup$ Thanks, this is great. I there way for me the change alternate behaviour (which you set to Nothing in your example), to the body of the warning? $\endgroup$ – Yair M Mar 3 '17 at 8:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.