3
$\begingroup$

Overview

I want to apply a specified Chop function to every step in an function call in Mathematica (in my case LegendreP), especially when encountering a machine underflow error. The resulting function should be applicable to a dataframe.

The Setup

I am trying to calculate a function including an associated Legendre function with complex indices

function[t_] = 1/Sin[t] * LegendreP[-1/2 + V * I, l+1, Cos[t]]

where t is between 0 and Pi, V is of order of magnitude 10 and l is between 10 and 100. Beside the function I need its logarithmic derivative function'/function.

Ideally I want to do this by applying the function to a dataframe and appending the result in a separate column.

Append[#, "function" -> function[#timeframe]]

where timeframe is a column with all the t values.

The Problem

When I run this code for any l bigger than 12 and very small t~1e-5 values, the LegendreP Algorithm throws a machine underflow error General::munfl because it cannot execute a multiplication of extremly small complex numbers.

While for a single call or a plot, it seems to do some chopping or return Indeterminate, when I write it to a dataframe with

Append[#, "function" -> function[#timeframe]]

it just returns Failure and does not write anything to the dataframe.

What I have tried so far

I have tried to use Chop and Threshold, but this does not seem to apply to the single steps of the algorithm but only the final result.

The way I "solve" the problem at the moment is to catch the error and return 0 instead of my function. This is not ideal since the real or imaginary part of the step in question and the result might not be negligible while the other one is, or it might diverge instead of converge to 0.

Since the multiplication that raises the error lists numbers ~1e-300 or so, I doubt that the problem is solvable by increasing the precision.

My Goal

Ideally I'd like to call Chop, whenever Mathematica encounters a machine underflow. The behavior of Chop on complex numbers is exactly what I need. This way I should be able to preserve the real or imaginary part that does not vanish.

Is the error handling different, when applied to a dataframe as it relates to this question (for plots or even single evaluation points I don't have the same issue) or can an indeterminate/NaN be written to a dataframe?

Is there a way to set a "global chop rule"?

Grateful for any hint :D

Edit 1:

"Minimal" Example:

potentialValue = 77.5;
l = 25;

data = Dataset[{
   <|"timeframe" -> 0.000001|>,
   <|"timeframe" -> 0.000002|>,
   <|"timeframe" -> 0.000003|>
   }]


vacuumFluctuation[t_] = 
  1/Sin[t] LegendreP[-(1/2) + I Sqrt[potentialValue], l + 1, Cos[t]];

firstDerivative[t_] = D[vacuumFluctuation[x], x] /. x -> t;

logarithmicDerivative[t_] = firstDerivative[t]/vacuumFluctuation[t];

data = data[All, 
   Append[#, 
     "vacuum_fluctuation_logarithmic_derivative_mathematica" -> 
      logarithmicDerivative[#timeframe]] &];

data
```
$\endgroup$
6
  • $\begingroup$ What’s a dataframe? Can you add the complete executable code for your operation, perhaps on a small toy example that reproduces the behavior? $\endgroup$
    – MarcoB
    Jan 15 at 14:13
  • $\begingroup$ munfl means the number was replaced by zero, so neither Threshold nor Chop should be of any use internally at such steps. $\endgroup$
    – Michael E2
    Jan 15 at 23:08
  • $\begingroup$ @MarcoB Sorry, in Mathematica it's called a Dataset. See Edit. Thanks for the comment $\endgroup$
    – Phteven
    Jan 16 at 11:04
  • $\begingroup$ @MichaelE2 How can it still crash with "too small to represent" instead of producing 0, then? $\endgroup$
    – Phteven
    Jan 16 at 11:05
  • $\begingroup$ I interpreted “chopping or return Indeterminate” as doing something like 10.^-310 or 10.^-310/10.^-310. I don’t see how to use Threshold to prevent getting 0. or Indeterminate in these two cases. (You will get the munfl message, but that’s just a warning that it’s chopping the result to zero. I wouldn’t call is a “crash.”) $\endgroup$
    – Michael E2
    Jan 16 at 14:40
4
$\begingroup$

The message General::munfl only occurs for machine numbers. So, you can fix the issue by using arbitrary precision numbers internally, and then converting to a machine number:

function[t_, V_, l_] := N @ ReleaseHold[
    SetPrecision[Hold[1/Sin[t]*LegendreP[-1/2+V*I,l+1,Cos[t]]], 30]
]

Then:

function[.00001, 10, 50]

1.34228*10^-189 + 0. I

$\endgroup$
1
  • $\begingroup$ Thank you! Do you mind explaining what the logic is behind the function/ decorator sequence? $\endgroup$
    – Phteven
    Jan 16 at 11:41

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.