0
$\begingroup$

I am fairly new to functional programming and would like to replace a For[] loop that sums the results over a Dataset.

This may be a bit different since the function being called takes a mix of parameters and Dataset columns.

activeSegments = segmentMap[Select[#State == 1 &]];
eFieldMag375 = 
  Parallelize[Table[{x, y, segmentMapEFieldIntensity[x, y, 0.375, 37, 10^-8]}, 
    {x,-6,6,0.25},{y,-6,6,0.25}]]

segmentMap = 
  Dataset[{
    <|"id"->1,  "alignType"->0, "x1"->-3.0, "x2"->3.0, "y1"->3.0, "y2"->3.0, "z1"->0.0, "z2"->0.0,   "State"->0|>,
    <|"id"->2, "alignType"->1,  "x1"->0.0, "x2"->0.0, "y1"->-3.0, "y2"->3.0, "z1"->0.0, "z2"->0.0,   "State"->0|>,  
    <|"id"->3, "alignType"->0,  "x1"->-3.0, "x2"->3.0, "y1"->-3.0, "y2"->-3.0, "z1"->0.0, "z2"->0.0, "State"->0|>,
    <|"id"->4, "alignType"->2,  "x1"->0.0,  "x2"->0.0, "y1"->0.0, "y2"->0.0, "z1"->0.0, "z2"->1.5, "State"->0|>,
    <|"id"->5, "alignType"->0, "x1"->-3.0, "x2"->3.0, "y1"->3.0, "y2"->3.0, "z1"->1.5, "z2"->1.5,   "State"->0|>,
    <|"id"->6, "alignType"->1, "x1"->-3.0, "x2"->-3.0, "y1"->-3.0, "y2"->3.0, "z1"->1.5, "z2"->1.5, "State"->0|>,
    <|"id"->7, "alignType"->1, "x1"->3.0, "x2"->3.0, "y1"->-3.0, "y2"->3.0, "z1"->1.5, "z2"->1.5, "State"->0|>,
    <|"id"->8, "alignType"->0, "x1"->-3.0, "x2"->3.0, "y1"->-3.0, "y2"->-3.0, "z1"->1.5, "z2"->1.5,   "State"->0|>,
    <|"id"->9, "alignType"->2, "x1"->-3.0, "x2"->-3.0, "y1"->3.0, "y2"->3.0, "z1"->0.0, "z2"->1.5, "State"->1|>,
    <|"id"->10, "alignType"->2, "x1"->-3.0, "x2"->-3.0, "y1"->-3.0, "y2"->-3.0, "z1"->0.0, "z2"->1.5, "State"->1|>,
    <|"id"->11, "alignType"->2, "x1"->3.0, "x2"->3.0, "y1"->3.0, "y2"->3.0, "z1"->0.0, "z2"->1.5, "State"->1|>,
    <|"id"->12, "alignType"->2, "x1"->3.0, "x2"->3.0, "y1"->-3.0, "y2"->-3.0, "z1"->0.0, "z2"->1.5, "State"->1|>}];

segmentMapEFieldx[testPtx_, testPty_, testPtz_, εr_, ρℓ_]:= 
  Module[{segmentIndex, segmentCount, exMag},
    exMag = 0.0;
    segmentCount = Length[activeSegments];
    For[segmentIndex = 1, segmentIndex <= segmentCount, segmentIndex += 1,
      exMag += Apply[EFieldxComponent,
       {activeSegments[segmentIndex]["alignType"], εr, testPtx, testPty, testPtz, 
        activeSegments[segmentIndex]["x1"], activeSegments[segmentIndex]["x2"],  
        activeSegments[segmentIndex]["y1"], activeSegments[segmentIndex]["y2"],
        activeSegments[segmentIndex]["z1"], activeSegments[segmentIndex]["z2"],
        ρℓ}];]      
    Return[exMag]]

EFieldxComponent[segType_, εr_, x_, y_, z_, xp1_, xp2_, yp1_, yp2_, zp1_, zp2_, ρℓ_]:=
  Switch[segType,
    0, Exx[x, y, z, xp1, xp2, yp1, zp1, εr, ρℓ],
    1, Eyx[x, y, z, xp1, yp1, yp2, zp1, εr, ρℓ],
    2, Ezx[x, y, z, xp1, yp1, zp1, zp2, εr, ρℓ]];

The Apply is fairly straight-forward. I am wondering if it would be possible to replace the For loop with a Map and sum the values returned by EFieldxComponent.

$\endgroup$
6
  • $\begingroup$ Try Total@ before your output list. $\endgroup$ Apr 30, 2015 at 18:52
  • $\begingroup$ Thanks David - I will try that. (Still trying to figure out how to wrap a Map around the Apply so that it iterates over activeSegments). $\endgroup$ Apr 30, 2015 at 19:11
  • $\begingroup$ you should provide a working example.. $\endgroup$
    – george2079
    Apr 30, 2015 at 19:39
  • $\begingroup$ So activeSegments is a list? Of what dimension? Are you not passing it in with the other arguments to the function? And EFieldxComponents is a function? $\endgroup$ Apr 30, 2015 at 19:42
  • $\begingroup$ I have fleshed out the code snippet to show activeSegments and EFieldxComponents and the call I am using to create a Table. $\endgroup$ Apr 30, 2015 at 19:54

2 Answers 2

1
$\begingroup$

There may be better approaches, but this is what I found to work. I replaced:

segmentMapEFieldx[testPtx_, testPty_, testPtz_, \[CurlyEpsilon]r_, \[Rho]\[ScriptL]_]:=     
Module[
    {segmentIndex, segmentCount, exMag},

    exMag = 0.0;
    segmentCount = Length[activeSegments];

    For[segmentIndex = 1, segmentIndex<=segmentCount,segmentIndex+=1,
        exMag += Apply[ EFieldxComponent, {activeSegments[segmentIndex]["alignType"],
                                  \[CurlyEpsilon]r, testPtx,testPty,testPtz, 
                                  activeSegments[segmentIndex]["x1"], activeSegments[segmentIndex]["x2"],  
                                  activeSegments[segmentIndex]["y1"], activeSegments[segmentIndex]["y2"],
                                  activeSegments[segmentIndex]["z1"], activeSegments[segmentIndex]["z2"],
                                 \[Rho]\[ScriptL]}];

    ];

    Return[exMag]
]

With:

segmentMapEFieldx[testPtx_, testPty_, testPtz_, \[CurlyEpsilon]r_, \[Rho]\[ScriptL]_]:=
    Total@Map[(Apply[EFieldxComponent[#2,\[CurlyEpsilon]r, testPtx,testPty,testPtz,#3,#4,#5,#6,#7,#8,\[Rho]\[ScriptL]]&,#])&,activeSegments]

This dropped AbsoluteTiming for 44.54 seconds to 29.07

$\endgroup$
0
$\begingroup$

This is similar, but perhaps a bit more readable than yours:

exMag=Total@Map[
   EFieldxComponent[#["alignType"], \[CurlyEpsilon]r, testPtx, testPty,
        testPtz, #["x1"], #["x2"], #["y1"], #["y2"], #["z1"],
                 #["z2"], \[Rho]\[ScriptL]] &, activeSegments]

alternately you might use the Dataset built in map functionality:

 Total@activeSegments[All, 
    EFieldxComponent[#["alignType"], \[CurlyEpsilon]r, testPtx, testPty,
    testPtz,#["x1"], #["x2"], #["y1"], #["y2"], #["z1"], #["z2"],
      \[Rho]\[ScriptL]] & ]

Can't test due to missing info though.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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