Search code examples
modulewolfram-mathematicamathematical-optimization

Mathematica Module Not Returning Value


I am new to Mathematica, and using a Module to perform a procedure, then return a value. However, Mathematica seems to be evaluating and returning symbolic values instead of the numerical value I want.

Questions I have are: When don't you use semicolons? And when do you use Return[value] instead of just writing "value"?

DumpVar[x_] := Print[ToString[HoldForm[x]], ":", x];
SetAttributes[DumpVar, {Listable, HoldAll}]

width = 1;
interval = width/2;

panelCoeff = 2;
lightAngle = Pi/3;

(*Panel and light equations*)

panel[x_] = Abs[panelCoeff x];(*panelCoeff ((x)^2);*)

light[x_] = Tan[lightAngle]*x;

getAngleAttack[offset_] := 
  Module[{bounce1x, l1a, lightSlope, panelSlope},
   light[x_] = light'[x] (x - offset) + panel[interval];
   DumpVar[offset];

   lightSlope = N[light'[offset]];
   u1S = light'[offset];
   u1[x_] = (u1S (x - offset)) + panel[interval]; 

   bounce1x = 
    x /. N[NSolve[u1[x] == panel[x] && x < interval && x > -interval, 
       x]];

   u1r[x_] = panel'[bounce1x] (x - bounce1x) + panel[bounce1x];

   If[Length[bounce1x] > 0,
     bounce1x = bounce1x[[1]];,
     bounce1x = offset;
     ]

    If[bounce1x > -interval && bounce1x < interval,

     lightSlope = N[u1'[bounce1x]];

     If[x <= 0,
      panelSlope := N[panelCoeff],
      panelSlope := -N[panelCoeff]];

     DumpVar[lightSlope];
     DumpVar[panelSlope];
     l1a = 
      N[ArcTan[(lightSlope - 
           panelSlope)/(1 + (panelSlope lightSlope))]];

     DumpVar[l1a];

     l1a
      Return[l1a]
     ]

    Return[l1a];
   ];


myint = getAngleAttack[0];
(*myint = N[f[10]];*)
DumpVar[myint];

Plot[{panel[x], light[x]}, {x, -.6, .6}]

myint = getAngleAttack[.5];
DumpVar[myint];

My goal is to be able to graph and integrate this function.


Solution

  • In the middle of your block you have:

    If[Length[bounce1x] > 0,
      bounce1x = bounce1x[[1]];,
      bounce1x = offset;
      ]
    

    The format of If is as follows: If[Condition, ValueIfTrue, ValueIfFalse]

    So If[True, 3, 2] returns 3, and If[False, 3, 2] returns 2. Your semicolons here are unnecessary, but you do need one at the end of the if statement:

    If[Length[bounce1x] > 0,
      bounce1x = bounce1x[[1]],
      bounce1x = offset
      ];
    

    Otherwise, Mathematica will interpret that as multiplication of that statement times whatever the next one to show up will be. In this case, you're returning null from that If statement, and it's being multiplied by the return value of the next If statement that comes up.

    For Module the syntax is: Module[{localvars}, ReturnValue]

    Which means whatever is the last statement that shows up without a semicolon is the ReturnValue. So for example the following module:

    Module[{y},
       y = x * x;
       If[x < 0, -y, +y]
    ]
    

    will return -y when x < 0, and +y otherwise. The one exception this is when Return shows up. Just like in most languages, you can return early from a function by using Return:

    Module[{y},
       y = x * x;
       If[x < 0, 
          Return[-y],
          Return[+y]];
     (* We never reach this point to return null *)
     ];
    

    With respect to your Module, I think this may be what you're trying to accomplish:

    getAngleAttack[offset_] := 
     Module[{bounce1x, l1a, lightSlope, panelSlope}, 
      light[x_] = light'[x] (x - offset) + panel[interval];
      DumpVar[offset];
    
      lightSlope = N[light'[offset]];
      u1S = light'[offset];
      u1[x_] = (u1S (x - offset)) + panel[interval];
    
      bounce1x = 
       x /. N[NSolve[u1[x] == panel[x] && x < interval && x > -interval, 
          x]];
    
      u1r[x_] = panel'[bounce1x] (x - bounce1x) + panel[bounce1x];
    
      If[Length[bounce1x] > 0,
       bounce1x = bounce1x[[1]],
       bounce1x = offset];
    
       If[bounce1x > -interval && bounce1x < interval,
    
       lightSlope = N[u1'[bounce1x]];
    
       If[x <= 0,
        panelSlope := N[panelCoeff],
        panelSlope := -N[panelCoeff]];
    
       DumpVar[lightSlope];
       DumpVar[panelSlope];
    
       l1a = N[
         ArcTan[(lightSlope - panelSlope)/(1 + (panelSlope lightSlope))]];
    
       DumpVar[l1a];
       Return[l1a]
      ];
      l1a]
    

    Another thing you should watch out for is any variables you use inside of a Module. If you run the following piece of code, you'll get 4, -113/5, 32 as the output values:

    d = 4 (* d was 4 *)
    Module[{a, b, c},
       a = 3;
       b = 2;
       c = 5;
       d = 32; (* Uh oh! I just overwrite whatever d was *)
       a^2 + b / c - d]
    d (* d is now 32 *)
    

    To avoid this, define any variables you're using as local variables within the start of the Module: Module[{a, b, c, d}, ...]