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$
  • $\begingroup$ Try Total@ before your output list. $\endgroup$ – David G. Stork Apr 30 '15 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$ – Doug Kimzey Apr 30 '15 at 19:11
  • $\begingroup$ you should provide a working example.. $\endgroup$ – george2079 Apr 30 '15 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$ – rhomboidRhipper Apr 30 '15 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$ – Doug Kimzey Apr 30 '15 at 19:54
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, privacy policy and cookie policy

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