3

I am doing a time-intensive calculation and I would like to have the option to stop the calculation but obtain the current (last) result. Generally, I do some groundwork as what can be done before asking a question but this time I don't even know where to start. I wrote the "toy" version of my problem.

Here is the user interface that I would like to insert the "ABORT" button. and the "time-dependent" package.

BeginPackage["AbortCal`"];

  MainAbortCal::usage=" ";

Begin["`Private`"];

  MainAbortCal[tfinal_]:=Module[{a}
  , a=ConstantArray[1, {50, 50}]
  ; Do[a=a+1; Pause[2];,{i,tfinal}]
  ; plta=ListPlot3D[a,ImageSize->Full]
  ; {plta, a}
  ]


End[];
EndPackage[];


Panel[
  Framed[
    DynamicModule[
      {tfinal = 100}
    , Column[{
        Style["Compute","Subsection"],
        Row[{Style["Final Time ",12,Blue], InputField[Dynamic[tfinal]]},Spacer[5]],
        Button[Style["Compute",Green,Bold]
        , Res=AbortCal`MainAbortCal[tfinal]
        ; Plt=Res[[1]]
        ; a=Res[[2]]
        , Method->"Queued"
        ],
        Row[{Button["Stop",Interrupt[];Print[Dynamic[a]]]}],
        Row[{Style["Plot  ",12,Red],InputField[Dynamic[Plt],FieldSize->{50,15},Enabled->False,BaseStyle->{12}]},Spacer[15]]
      }]
    ]
  , Background->Lighter[Gray,.6]
  ]
]

I have the Pause[2] command there just to give me a time. I am not sure if there is a way to do what I want to do. Thank you for the help.

Kuba
  • 136,707
  • 13
  • 279
  • 740
Erdem
  • 869
  • 4
  • 11

1 Answers1

2

Here is what I'd do:

  • decouple calculations from presenting results (Plot3D) , it gives you more control and is a very good habit for gui construction

  • how to capture, and if it is possible at all, calculations state after an abort is a case dependent problem. here we can pass a variable that will be updated live so once abort happens we can always use it

  • we can abort using FrontEndToken["EvaluatorAbort"] which is more reliable

Minor changes:

  • finished variable tracks whether the calculation is ongoing in order to display a progress indicator or something. users need to know :)

  • Internal`WithLocalSettings is used to make sure finished is set True despite aborting. If you want to use more documented method check CheckAbort and friends.

See closely related solution in: Button action monitored with progress bar

BeginPackage["AbortCal`"];

MainCalculation;
PlotMainCalculationResults;

Begin["`Private`"];

MainCalculation//Attributes = {HoldFirst};
MainCalculation[a_, tfinal_]:=Module[{}
, a=ConstantArray[1, {50, 50}]
; Do[a=a+1; Pause[2];,{i,tfinal}]
; a

]

PlotMainCalculationResults[a_]:=ListPlot3D[a, ImageSize->300]

End[];
EndPackage[];


    Panel @ DynamicModule[
      {tfinal = 100, a, finished = True, compute, display}
    , Grid[{
        {Style["Compute","Subsection"], SpanFromLeft},
        {"Final Time", InputField[Dynamic[tfinal]]},
        {"", Button["Compute", compute[], Method->"Queued"      ]},
        {"", Button["Stop", FrontEndExecute[FrontEndToken["EvaluatorAbort"]]]},
        {"Plot  ", Dynamic[display[]]}
      }]
    , Initialization:>(
        compute[]:= Internal`WithLocalSettings[
          finished = False,
          MainCalculation[a,tfinal],
          finished = True
        ];
        display[]:=Which[
          Not @ finished, Dynamic @ ProgressIndicator[Appearance->"Indeterminate"]
        , ArrayQ[a], PlotMainCalculationResults[a]
        , True, "compute first"]



      )
    ]

enter image description here

Kuba
  • 136,707
  • 13
  • 279
  • 740
  • I think I can build on this one. I even started by adding "b" matrix. MainCalculation[a_,b_, tfinal_] and inside the code b=a; Do[a=a+1; b=b-50;Pause[2];,{i,tfinal}] and b everywhere that see a, except ArrayQ[a] . I plot c = a + b; ListPlot3D[c, ImageSize -> 300]] It is working but in the original version I can stop the calculation and push compute it starts over. My version gives an error.Cannot assign to raw object and gives minus values which is c matrix that I am creating. It does that even I do only ListPlot3D[a+b, ImageSize -> 300]]. Do you know why? – Erdem Apr 17 '18 at 17:33
  • @erdem now you need HoldAll not HoldFirst. – Kuba Apr 17 '18 at 17:35
  • Awesome...works like a charm. Now time for me to build on that :) – Erdem Apr 17 '18 at 17:40