magnetps.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "ui_magnetpsform.h"
15 #include "ui_magnetpsconfigform.h"
16 #include "magnetps.h"
17 #include "interface.h"
18 #include "analyzer.h"
19 #include "xnodeconnector.h"
20 #include <QStatusBar>
21 
22 XMagnetPS::XMagnetPS(const char *name, bool runtime,
23  Transaction &tr_meas, const shared_ptr<XMeasure> &meas) :
24  XPrimaryDriverWithThread(name, runtime, ref(tr_meas), meas),
25  m_field(create<XScalarEntry>("Field", false,
26  dynamic_pointer_cast<XDriver>(shared_from_this()), "%.8g")),
27  m_current(create<XScalarEntry>("Current", false,
28  dynamic_pointer_cast<XDriver>(shared_from_this()), "%.8g")),
29  m_entries(meas->scalarEntries()),
30  m_targetField(create<XDoubleNode>("TargetField", true)),
31  m_sweepRate(create<XDoubleNode>("SweepRate", true)),
32  m_allowPersistent(create<XBoolNode>("AllowPersistent", true)),
33  m_approach(create<XComboNode>("Approach", false, true)),
34  m_stabilized(create<XDoubleNode>("Stabilized", true)),
35  m_magnetField(create<XDoubleNode>("MagnetField", true)),
36  m_outputField(create<XDoubleNode>("OutpuField", true)),
37  m_outputCurrent(create<XDoubleNode>("OutputCurrent", true)),
38  m_outputVolt(create<XDoubleNode>("OutputVolt", true)),
39  m_pcsHeater(create<XBoolNode>("PCSHeater", true)),
40  m_persistent(create<XBoolNode>("Persistent", true)),
41  m_aborting(create<XBoolNode>("Aborting", true)),
42  m_configShow(create<XTouchableNode>("ConfigShow", true)),
43  m_rateLimit1(create<XDoubleNode>("RateLimit1", false)),
44  m_rateLimit1UBound(create<XDoubleNode>("RateLimit1UBound", false)),
45  m_rateLimit2(create<XDoubleNode>("RateLimit2", false)),
46  m_rateLimit2UBound(create<XDoubleNode>("RateLimit2UBound", false)),
47  m_rateLimit3(create<XDoubleNode>("RateLimit3", false)),
48  m_rateLimit3UBound(create<XDoubleNode>("RateLimit3UBound", false)),
49  m_rateLimit4(create<XDoubleNode>("RateLimit4", false)),
50  m_rateLimit4UBound(create<XDoubleNode>("RateLimit4UBound", false)),
51  m_rateLimit5(create<XDoubleNode>("RateLimit5", false)),
52  m_rateLimit5UBound(create<XDoubleNode>("RateLimit5UBound", false)),
53  m_secondaryPSMultiplier(create<XDoubleNode>("SecondaryPSMultiplier", false)),
54  m_secondaryPS(create<XItemNode<XDriverList, XMagnetPS> >("SecondaryPS", false, ref(tr_meas), meas->drivers())),
55  m_safeCond1Entry(create<XItemNode<XScalarEntryList, XScalarEntry> >("SafeCond1Entry", false, ref(tr_meas), meas->scalarEntries())),
56  m_safeCond1Min(create<XDoubleNode>("SafeCond1Min", false)),
57  m_safeCond1Max(create<XDoubleNode>("SafeCond1Max", false)),
58  m_safeCond2Entry(create<XItemNode<XScalarEntryList, XScalarEntry> >("SafeCond2Entry", false, ref(tr_meas), meas->scalarEntries())),
59  m_safeCond2Min(create<XDoubleNode>("SafeCond2Min", false)),
60  m_safeCond2Max(create<XDoubleNode>("SafeCond2Max", false)),
61  m_safeCond3Entry(create<XItemNode<XScalarEntryList, XScalarEntry> >("SafeCond3Entry", false, ref(tr_meas), meas->scalarEntries())),
62  m_safeCond3Min(create<XDoubleNode>("SafeCond3Min", false)),
63  m_safeCond3Max(create<XDoubleNode>("SafeCond3Max", false)),
64  m_persistentCondEntry(create<XItemNode<XScalarEntryList, XScalarEntry> >("PersistentCondEntry", false, ref(tr_meas), meas->scalarEntries())),
65  m_persistentCondMax(create<XDoubleNode>("PersistentCondMax", false)),
66  m_nonPersistentCondEntry(create<XItemNode<XScalarEntryList, XScalarEntry> >("NonPersistentCondEntry", false, ref(tr_meas), meas->scalarEntries())),
67  m_nonPersistentCondMin(create<XDoubleNode>("NonPersistentCondMin", false)),
68  m_pcshWait(create<XDoubleNode>("PCSHWait", false)),
69  m_form(new FrmMagnetPS(g_pFrmMain)),
70  m_formConfig(new FrmMagnetPSConfig(g_pFrmMain)),
71  m_statusPrinter(XStatusPrinter::create(m_form.get())) {
72  meas->scalarEntries()->insert(tr_meas, m_field);
73  meas->scalarEntries()->insert(tr_meas, m_current);
74  m_form->statusBar()->hide();
75  m_form->setWindowTitle(XString("Magnet Power Supply - " + getLabel() ));
76  m_formConfig->statusBar()->hide();
77  m_formConfig->setWindowTitle(XString("Magnet PS Detail Configuration - " + getLabel() ));
78 
79  m_conConfigShow = xqcon_create<XQButtonConnector>(
80  m_configShow, m_form->m_btnConfig);
81 
82  m_form->m_btnConfig->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogOpenButton));
83 
84  m_conAllowPersistent = xqcon_create<XQToggleButtonConnector>(
85  allowPersistent(), m_form->m_ckbAllowPersistent);
86  m_conTargetField = xqcon_create<XQLineEditConnector>(
87  targetField(), m_form->m_edTargetField);
88  m_conSweepRate = xqcon_create<XQLineEditConnector>(
89  sweepRate(), m_form->m_edSweepRate);
90  m_conMagnetField = xqcon_create<XQLCDNumberConnector>(
91  magnetField(), m_form->m_lcdMagnetField);
92  m_conOutputField = xqcon_create<XQLCDNumberConnector>(
93  outputField(), m_form->m_lcdOutputField);
94  m_conOutputCurrent= xqcon_create<XQLCDNumberConnector>(
95  outputCurrent(), m_form->m_lcdCurrent);
96  m_conOutputVolt = xqcon_create<XQLCDNumberConnector>(
97  outputVolt(), m_form->m_lcdVoltage);
98  m_conPCSH = xqcon_create<XQLedConnector>(
99  pcsHeater(), m_form->m_ledSwitchHeater);
100  m_conPersist = xqcon_create<XQLedConnector>(
101  persistent(), m_form->m_ledPersistent);
102  m_conAborting = xqcon_create<XQLedConnector>(
103  m_aborting, m_form->m_ledAborting);
104  m_conApproach = xqcon_create<XQComboBoxConnector>(
105  m_approach, m_form->m_cmbApproach, Snapshot( *m_approach));
106  m_conRateLimit1 = xqcon_create<XQLineEditConnector>(
107  m_rateLimit1, m_formConfig->m_edRateLimit1);
108  m_conRateLimit2 = xqcon_create<XQLineEditConnector>(
109  m_rateLimit2, m_formConfig->m_edRateLimit2);
110  m_conRateLimit3 = xqcon_create<XQLineEditConnector>(
111  m_rateLimit3, m_formConfig->m_edRateLimit3);
112  m_conRateLimit4 = xqcon_create<XQLineEditConnector>(
113  m_rateLimit4, m_formConfig->m_edRateLimit4);
114  m_conRateLimit5 = xqcon_create<XQLineEditConnector>(
115  m_rateLimit5, m_formConfig->m_edRateLimit5);
116  m_conRateLimit1UBound = xqcon_create<XQLineEditConnector>(
117  m_rateLimit1UBound, m_formConfig->m_edRateLimit1Bound);
118  m_conRateLimit2UBound = xqcon_create<XQLineEditConnector>(
119  m_rateLimit2UBound, m_formConfig->m_edRateLimit2Bound);
120  m_conRateLimit3UBound = xqcon_create<XQLineEditConnector>(
121  m_rateLimit3UBound, m_formConfig->m_edRateLimit3Bound);
122  m_conRateLimit4UBound = xqcon_create<XQLineEditConnector>(
123  m_rateLimit4UBound, m_formConfig->m_edRateLimit4Bound);
124  m_conRateLimit5UBound = xqcon_create<XQLineEditConnector>(
125  m_rateLimit5UBound, m_formConfig->m_edRateLimit5Bound);
126  m_conSecondaryPS = xqcon_create<XQComboBoxConnector>(
127  m_secondaryPS, m_formConfig->m_cmbSecondaryPS, ref(tr_meas));
128  m_conSecondaryPSMultiplier = xqcon_create<XQLineEditConnector>(
129  m_secondaryPSMultiplier, m_formConfig->m_edSecondaryPSMultiplier);
130  m_conSafeCond1Entry = xqcon_create<XQComboBoxConnector>(
131  m_safeCond1Entry, m_formConfig->m_cmbSafeCond1Entry, ref(tr_meas));
132  m_conSafeCond1Min = xqcon_create<XQLineEditConnector>(
133  m_safeCond1Min, m_formConfig->m_edSafeCond1Min);
134  m_conSafeCond1Max = xqcon_create<XQLineEditConnector>(
135  m_safeCond1Max, m_formConfig->m_edSafeCond1Max);
136  m_conSafeCond2Entry = xqcon_create<XQComboBoxConnector>(
137  m_safeCond2Entry, m_formConfig->m_cmbSafeCond2Entry, ref(tr_meas));
138  m_conSafeCond2Min = xqcon_create<XQLineEditConnector>(
139  m_safeCond2Min, m_formConfig->m_edSafeCond2Min);
140  m_conSafeCond2Max = xqcon_create<XQLineEditConnector>(
141  m_safeCond2Max, m_formConfig->m_edSafeCond2Max);
142  m_conSafeCond3Entry = xqcon_create<XQComboBoxConnector>(
143  m_safeCond3Entry, m_formConfig->m_cmbSafeCond3Entry, ref(tr_meas));
144  m_conSafeCond3Min = xqcon_create<XQLineEditConnector>(
145  m_safeCond3Min, m_formConfig->m_edSafeCond3Min);
146  m_conSafeCond3Max = xqcon_create<XQLineEditConnector>(
147  m_safeCond3Max, m_formConfig->m_edSafeCond3Max);
148  m_conPersistentCondEntry = xqcon_create<XQComboBoxConnector>(
149  m_persistentCondEntry, m_formConfig->m_cmbPersistentCondEntry, ref(tr_meas));
150  m_conPersistentCondMax = xqcon_create<XQLineEditConnector>(
151  m_persistentCondMax, m_formConfig->m_edPersistentCondMax);
152  m_conNonPersistentCondEntry = xqcon_create<XQComboBoxConnector>(
153  m_nonPersistentCondEntry, m_formConfig->m_cmbNonPersistentCondEntry, ref(tr_meas));
154  m_conNonPersistentCondMin = xqcon_create<XQLineEditConnector>(
155  m_nonPersistentCondMin, m_formConfig->m_edNonPersistentCondMin);
156  m_conPCSHWait = xqcon_create<XQLineEditConnector>(
157  m_pcshWait, m_formConfig->m_edPCSHWait);
158 
159  iterate_commit([=](Transaction &tr){
160  tr[ *allowPersistent()] = false;
161  tr[ *approach()].add({"Linear", "Oscillating"});
162  tr[ *m_pcshWait] = 40.0; //sec
163  tr[ *m_safeCond1Max] = 100.0;
164  tr[ *m_safeCond2Max] = 100.0;
165  tr[ *m_safeCond3Max] = 100.0;
166  tr[ *targetField()].setUIEnabled(false);
167  tr[ *sweepRate()].setUIEnabled(false);
168  tr[ *targetField()].setUIEnabled(false);
169  tr[ *sweepRate()].setUIEnabled(false);
170  tr[ *allowPersistent()].setUIEnabled(false);
171  m_lsnConfigShow = tr[ *m_configShow].onTouch().connectWeakly(
172  shared_from_this(), &XMagnetPS::onConfigShow,
173  XListener::FLAG_MAIN_THREAD_CALL | XListener::FLAG_AVOID_DUP);
174  });
175 }
176 void
178  m_form->showNormal();
179  m_form->raise();
180 }
181 void
182 XMagnetPS::onConfigShow(const Snapshot &shot, XTouchableNode *) {
183  m_formConfig->showNormal();
184  m_formConfig->raise();
185 }
186 void
188  tr[ *this].m_magnetField = reader.pop<float>();
189  tr[ *this].m_outputCurrent = reader.pop<float>();
190  m_field->value(tr, tr[ *this].m_magnetField);
191  m_current->value(tr, tr[*this].m_outputCurrent);
192 }
193 void
195 }
196 
197 void
198 XMagnetPS::onRateChanged(const Snapshot &shot, XValueNodeBase *) {
199  try {
200  setRate(shot[ *sweepRate()]);
201  }
202  catch (XKameError &e) {
203  e.print(getLabel() + "; ");
204  }
205 }
206 bool
207 XMagnetPS::isSafeConditionSatisfied(const Snapshot &shot, const Snapshot &shot_entries) {
208  if(shared_ptr<XScalarEntry> entry = shot[ *m_safeCond1Entry]) {
209  try {
210  double x = shot_entries[ *entry->value()];
211  if((x >= shot[ *m_safeCond1Max]) || (x <= shot[ *m_safeCond1Min]))
212  return false;
213  }
214  catch(NodeNotFoundError &) {
215  }
216  }
217  if(shared_ptr<XScalarEntry> entry = shot[ *m_safeCond2Entry]) {
218  try {
219  double x = shot_entries[ *entry->value()];
220  if((x >= shot[ *m_safeCond2Max]) || (x <= shot[ *m_safeCond2Min]))
221  return false;
222  }
223  catch(NodeNotFoundError &) {
224  }
225  }
226  if(shared_ptr<XScalarEntry> entry = shot[ *m_safeCond3Entry]) {
227  try {
228  double x = shot_entries[ *entry->value()];
229  if((x >= shot[ *m_safeCond3Max]) || (x <= shot[ *m_safeCond3Min]))
230  return false;
231  }
232  catch(NodeNotFoundError &) {
233  }
234  }
235  return true;
236 }
237 bool
238 XMagnetPS::isPersistentStabilized(const Snapshot &shot, const Snapshot &shot_entries, const XTime &pcsh_off_time) {
239  if(shared_ptr<XScalarEntry> entry = shot[ *m_persistentCondEntry]) {
240  try {
241  double x = shot_entries[ *entry->value()];
242  if(x >= shot[ *m_persistentCondMax])
243  return false;
244  }
245  catch(NodeNotFoundError &) {
246  }
247  }
248  if(XTime::now() - pcsh_off_time < std::max(10.0, (double)shot[ *m_pcshWait]))
249  return false;
250  return true;
251 }
252 bool
253 XMagnetPS::isNonPersistentStabilized(const Snapshot &shot, const Snapshot &shot_entries, const XTime &pcsh_on_time) {
254  if(shared_ptr<XScalarEntry> entry = shot[ *m_nonPersistentCondEntry]) {
255  try {
256  double x = shot_entries[ *entry->value()];
257  if(x <= shot[ *m_nonPersistentCondMin])
258  return false;
259  }
260  catch(NodeNotFoundError &) {
261  }
262  }
263  if(XTime::now() - pcsh_on_time < std::max(10.0, (double)shot[ *m_pcshWait]))
264  return false;
265  return true;
266 }
267 double
268 XMagnetPS::limitSweepRate(double field, double rate, const Snapshot &shot) {
269  if((shot[ *m_rateLimit1UBound] > 0.0) && (fabs(field) < shot[ *m_rateLimit1UBound])) {
270  return std::min( rate, (double)shot[ *m_rateLimit1]);
271  }
272  if((shot[ *m_rateLimit2UBound] > 0.0) && (fabs(field) < shot[ *m_rateLimit2UBound])) {
273  return std::min( rate, (double)shot[ *m_rateLimit2]);
274  }
275  if((shot[ *m_rateLimit3UBound] > 0.0) && (fabs(field) < shot[ *m_rateLimit3UBound])) {
276  return std::min( rate, (double)shot[ *m_rateLimit3]);
277  }
278  if((shot[ *m_rateLimit4UBound] > 0.0) && (fabs(field) < shot[ *m_rateLimit4UBound])) {
279  return std::min( rate, (double)shot[ *m_rateLimit4]);
280  }
281  if((shot[ *m_rateLimit5UBound] > 0.0) && (fabs(field) < shot[ *m_rateLimit5UBound])) {
282  return std::min( rate, (double)shot[ *m_rateLimit5]);
283  }
284  return rate;
285 }
286 double
287 XMagnetPS::limitTargetField(double field, const Snapshot &shot) {
288  double max_h = std::max((double)shot[ *m_rateLimit1UBound], (double)shot[ *m_rateLimit2UBound]);
289  max_h = std::max(max_h, (double)shot[ *m_rateLimit3UBound]);
290  max_h = std::max(max_h, (double)shot[ *m_rateLimit4UBound]);
291  max_h = std::max(max_h, (double)shot[ *m_rateLimit5UBound]);
292  if((max_h > 0.0) && (fabs(field) > max_h)) return max_h * field / fabs(field);
293  return field;
294 }
295 
296 void *
297 XMagnetPS::execute(const atomic<bool> &terminated) {
298  double havg = 0.0;
299  XTime lasttime = XTime::now();
300  XTime last_unstab_time = XTime::now();
301  XTime pcsh_time = XTime::now();
302  pcsh_time -= Snapshot( *this)[ *m_pcshWait];
303  double field_resolution;
304  bool is_pcs_fitted;
305  bool last_pcsh;
306  trans( *m_aborting) = false;
307 
308  field_resolution = fieldResolution();
309  is_pcs_fitted = isPCSFitted();
310  trans( *sweepRate()) = getSweepRate();
311  trans( *targetField()) = getTargetField();
312  last_pcsh = isPCSHeaterOn();
313 
314  targetField()->setUIEnabled(true);
315  sweepRate()->setUIEnabled(true);
316 
317  double target_field_old = Snapshot( *this)[ *targetField()];
318  double target_corr = 0.0;
319 
320  if(is_pcs_fitted) allowPersistent()->setUIEnabled(true);
321  iterate_commit([=](Transaction &tr){
322  m_lsnRate = tr[ *sweepRate()].onValueChanged().connectWeakly(
323  shared_from_this(), &XMagnetPS::onRateChanged);
324  });
325 
326  while( !terminated) {
327  msecsleep(100);
328  double magnet_field;
329  double output_field;
330  double output_current;
331  double output_volt;
332  double target_field_ps;
333  bool pcs_heater = true;
334 
335  Snapshot shot_entries( *m_entries);
336 
337  try {
338  // Reading magnet status.
339  output_field = getOutputField();
340  output_current = getOutputCurrent();
341  output_volt = getOutputVolt();
342  target_field_ps = getTargetField();
343  if(is_pcs_fitted) {
344  pcs_heater = isPCSHeaterOn();
345  if(pcs_heater != last_pcsh)
346  pcsh_time = XTime::now();
347  last_pcsh = pcs_heater;
348  }
349  if( !is_pcs_fitted || pcs_heater) {
350  magnet_field = output_field;
351  }
352  else {
353  magnet_field = getPersistentField();
354  }
355  }
356  catch (XKameError &e) {
357  e.print(getLabel() + "; ");
358  continue;
359  }
360  auto writer = std::make_shared<RawData>();
361  writer->push((float)magnet_field);
362  writer->push((float)output_current);
363 
364  finishWritingRaw(writer, XTime::now(), XTime::now());
365 
366  XTime newtime = XTime::now();
367  double havg_next;
368  Snapshot shot = iterate_commit([=, &havg_next](Transaction &tr){
369  Snapshot &shot(tr);
370  tr[ *magnetField()] = magnet_field;
371  tr[ *outputField()] = output_field;
372  tr[ *outputCurrent()] = output_current;
373  tr[ *outputVolt()] = output_volt;
374  tr[ *pcsHeater()] = pcs_heater && is_pcs_fitted;
375 
376  tr[ *persistent()] = !pcs_heater && is_pcs_fitted && isPersistentStabilized(shot, shot_entries, pcsh_time);
377 
378  if(shot[ *m_aborting]) {
379  //Aborting.
380  tr[ *targetField()].setUIEnabled(false);
381  tr[ *targetField()] = 0;
382  tr[ *sweepRate()] = limitSweepRate(magnet_field, 1.0, shot) / 10.0; //-0.1T/min or less.
383  }
384  //Limits sweep rate and field by software.
385  double sweep_rate = limitSweepRate(magnet_field, shot[ *sweepRate()], shot);
386  if(sweep_rate != shot[ *sweepRate()]) {
387  m_statusPrinter->printMessage(getLabel() + " " +
388  i18n("Limits sweep rate."));
389  tr[ *sweepRate()] = sweep_rate;
390  }
391 
392  double dt = fabs(newtime - lasttime);
393  //Estimates field deviation.
394  havg_next = (havg - magnet_field) * exp( -0.1 * dt) + magnet_field; //LPF by 10sec.
395  tr[ *stabilized()] = std::max(fabs(magnet_field - target_field_ps), fabs(havg_next - target_field_ps));
396  });
397  havg = havg_next;
398  double field_resolution_for_stab = field_resolution * 1.3;
399  if(shot[ *stabilized()] > field_resolution_for_stab)
400  last_unstab_time = XTime::now();
401  lasttime = newtime;
402 
403  //Checks abort condition.
404  if( !shot[ *m_aborting] && !isSafeConditionSatisfied(shot, shot_entries)) {
405  m_statusPrinter->printMessage(getLabel() + " " +
406  i18n("Aborting."));
407  trans( *m_aborting) = true;
408  break;
409  }
410  if( shot[ *m_aborting] && isSafeConditionSatisfied(shot, shot_entries)) {
411  m_statusPrinter->printMessage(getLabel() + " " +
412  i18n("Safe conditions are satisfied."));
413  trans( *m_aborting) = false;
414  trans( *targetField()).setUIEnabled(true);
415  break;
416  }
417 
418  try {
419  shared_ptr<XMagnetPS> secondaryps = shot[ *m_secondaryPS];
420  if(secondaryps.get() == this)
421  secondaryps.reset();
422 
423  if(pcs_heater || !is_pcs_fitted) {
424  //pcs heater is on or not fitted.
425  if((target_field_old != shot[ *targetField()]) ||
426  ((fabs(target_field_ps - target_field_old - target_corr) > field_resolution) &&
427  (fabs(target_field_ps - magnet_field) < field_resolution))) {
428  //Target has changed, or field has reached the temporary target.
429  if( !is_pcs_fitted || isNonPersistentStabilized(shot, shot_entries, pcsh_time)) {
430  //Sweeping starts.
431  double next_target_ps = shot[ *targetField()];
432  if(target_field_old != shot[ *targetField()])
433  target_corr = 0.0;
434  target_field_old = shot[ *targetField()];
435  if(shot[ *approach()] == APPROACH_OSC) {
436  next_target_ps += 0.2 * (next_target_ps - magnet_field) + target_corr;
437  }
438  target_corr = 0.0;
439  if((next_target_ps * magnet_field < 0) && (fabs(magnet_field) > field_resolution) &&
440  !canChangePolarityDuringSweep()) {
441  target_corr = next_target_ps - shot[ *targetField()];
442  next_target_ps = 0.0; //First go to zero before setting target with different polarity.
443  }
444  //Limits target.
445  double x = limitTargetField(next_target_ps, shot);
446  if(x != next_target_ps) {
447  m_statusPrinter->printMessage(getLabel() + " " +
448  i18n("Limits field."));
449  next_target_ps = x;
450  }
451  setPoint(next_target_ps);
452  toSetPoint();
453  if(secondaryps) {
454  double mul = shot[ *m_secondaryPSMultiplier];
455  if(fabs(mul) > 0.4) {
456  m_statusPrinter->printMessage(getLabel() + " " +
457  i18n("Multiplier too large."));
458  }
459  else {
460  double sweep_rate = getSweepRate();
461  secondaryps->iterate_commit([=](Transaction &tr){
462  tr[ *secondaryps->sweepRate()] = sweep_rate * mul;
463  tr[ *secondaryps->targetField()] = next_target_ps * mul;
464  tr[ *secondaryps->approach()] = (int)shot[ *approach()];
465  });
466  }
467  }
468  }
469  }
470  else {
471  if(is_pcs_fitted &&
472  (fabs(magnet_field - shot[ *targetField()]) < field_resolution) && shot[ *allowPersistent()]) {
473  if(XTime::now() - last_unstab_time >
474  std::max(30.0, (double)shot[ *m_pcshWait]) + field_resolution_for_stab * 1.05 / shot[ *sweepRate()] * 60.0) {
475  //field is not sweeping, and persistent mode is allowed
476  m_statusPrinter->printMessage(getLabel() + " " +
477  i18n("Turning on Perisistent mode."));
478  pcsh_time = XTime::now();
479  toPersistent();
480  }
481  }
482  }
483  }
484  else {
485  //pcs heater is off
486  if(fabs(magnet_field - shot[ *targetField()]) >= field_resolution) {
487  if((fabs(magnet_field - output_field) < field_resolution) &&
488  (fabs(target_field_ps - magnet_field) < field_resolution)) {
489  //ready to go non-persistent.
490  m_statusPrinter->printMessage(getLabel() + " " +
491  i18n("Non-Perisistent mode."));
492  double h = getPersistentField();
493  if(fabs(h - output_field) > field_resolution)
495  i18n("Huh? Magnet field confusing."), __FILE__, __LINE__);
496  pcsh_time = XTime::now();
497  toNonPersistent();
498  }
499  else {
500  //set output to persistent field.
501  if(shot[ *m_persistent]) {
502  setPoint(magnet_field);
503  toSetPoint();
504  }
505  }
506  }
507  else {
508  if(shot[ *m_persistent] && (fabs(output_field) > field_resolution)) {
509  toZero();
510  }
511  }
512  }
513  }
514  catch (XKameError &e) {
515  e.print(getLabel());
516  }
517 
518  }
519 
520  targetField()->setUIEnabled(false);
521  sweepRate()->setUIEnabled(false);
522  allowPersistent()->setUIEnabled(false);
523 
524  m_lsnRate.reset();
525  return NULL;
526 }

Generated for KAME4 by  doxygen 1.8.3