autolctuner.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 //---------------------------------------------------------------------------
15 #include "analyzer.h"
16 #include "autolctuner.h"
17 #include "ui_autolctunerform.h"
18 
19 REGISTER_TYPE(XDriverList, AutoLCTuner, "NMR LC autotuner");
20 
21 static const double TUNE_DROT_APPROACH = 5.0,
22  TUNE_DROT_FINETUNE = 2.0, TUNE_DROT_ABORT = 180.0; //[deg.]
23 static const double TUNE_TRUST_APPROACH = 720.0, TUNE_TRUST_FINETUNE = 360.0; //[deg.]
24 static const double TUNE_FINETUNE_START = 0.7; //-3dB@f0
25 static const double TUNE_DROT_REQUIRED_N_SIGMA_FINETUNE = 1.0;
26 static const double TUNE_DROT_REQUIRED_N_SIGMA_APPROACH = 2.0;
27 static const double SOR_FACTOR_MAX = 0.9;
28 static const double SOR_FACTOR_MIN = 0.3;
29 static const double TUNE_DROT_MUL_FINETUNE = 2.5;
30 static const double TUNE_DROT_MUL_APPROACH = 3.5;
31 
32 //---------------------------------------------------------------------------
33 XAutoLCTuner::XAutoLCTuner(const char *name, bool runtime,
34  Transaction &tr_meas, const shared_ptr<XMeasure> &meas) :
35  XSecondaryDriver(name, runtime, ref(tr_meas), meas),
36  m_stm1(create<XItemNode<XDriverList, XMotorDriver> >("STM1", false, ref(tr_meas), meas->drivers(), true)),
37  m_stm2(create<XItemNode<XDriverList, XMotorDriver> >("STM2", false, ref(tr_meas), meas->drivers(), false)),
38  m_netana(create<XItemNode<XDriverList, XNetworkAnalyzer> >("NetworkAnalyzer", false, ref(tr_meas), meas->drivers(), true)),
39  m_tuning(create<XBoolNode>("Tuning", true)),
40  m_succeeded(create<XBoolNode>("Succeeded", true)),
41  m_target(create<XDoubleNode>("Target", true)),
42  m_reflectionTargeted(create<XDoubleNode>("ReflectionTargeted", false)),
43  m_reflectionRequired(create<XDoubleNode>("ReflectionRequired", false)),
44  m_useSTM1(create<XBoolNode>("UseSTM1", false)),
45  m_useSTM2(create<XBoolNode>("UseSTM2", false)),
46  m_abortTuning(create<XTouchableNode>("AbortTuning", true)),
47  m_form(new FrmAutoLCTuner(g_pFrmMain)) {
48  connect(stm1());
49  connect(stm2());
50  connect(netana());
51 
52  m_form->setWindowTitle(i18n("NMR LC autotuner - ") + getLabel() );
53 
54  m_conUIs = {
55  xqcon_create<XQComboBoxConnector>(stm1(), m_form->m_cmbSTM1, ref(tr_meas)),
56  xqcon_create<XQComboBoxConnector>(stm2(), m_form->m_cmbSTM2, ref(tr_meas)),
57  xqcon_create<XQComboBoxConnector>(netana(), m_form->m_cmbNetAna, ref(tr_meas)),
58  xqcon_create<XQLineEditConnector>(target(), m_form->m_edTarget),
59  xqcon_create<XQLineEditConnector>(reflectionTargeted(), m_form->m_edReflectionTargeted),
60  xqcon_create<XQLineEditConnector>(reflectionRequired(), m_form->m_edReflectionRequired),
61  xqcon_create<XQButtonConnector>(m_abortTuning, m_form->m_btnAbortTuning),
62  xqcon_create<XQLedConnector>(m_tuning, m_form->m_ledTuning),
63  xqcon_create<XQLedConnector>(m_succeeded, m_form->m_ledSucceeded),
64  xqcon_create<XQToggleButtonConnector>(m_useSTM1, m_form->m_ckbUseSTM1),
65  xqcon_create<XQToggleButtonConnector>(m_useSTM2, m_form->m_ckbUseSTM2)
66  };
67 
68  iterate_commit([=](Transaction &tr){
69  tr[ *m_tuning] = false;
70  tr[ *m_succeeded] = false;
71  tr[ *m_reflectionTargeted] = -15.0;
72  tr[ *m_reflectionRequired] = -7.0;
73  tr[ *m_useSTM1] = true;
74  tr[ *m_useSTM2] = true;
75  m_lsnOnTargetChanged = tr[ *m_target].onValueChanged().connectWeakly(
76  shared_from_this(), &XAutoLCTuner::onTargetChanged);
77  m_lsnOnAbortTouched = tr[ *m_abortTuning].onTouch().connectWeakly(
78  shared_from_this(), &XAutoLCTuner::onAbortTuningTouched);
79  });
80 }
81 XAutoLCTuner::~XAutoLCTuner() {
82 }
84  m_form->showNormal();
85  m_form->raise();
86 }
87 void XAutoLCTuner::onTargetChanged(const Snapshot &shot, XValueNodeBase *node) {
88  Snapshot shot_this( *this);
89  shared_ptr<XMotorDriver> stm1__ = shot_this[ *stm1()];
90  shared_ptr<XMotorDriver> stm2__ = shot_this[ *stm2()];
91  const unsigned int tunebits = 0xffu;
92  if(stm1__) {
93  stm1__->iterate_commit([=](Transaction &tr){
94  tr[ *stm1__->active()] = true; // Activate motor.
95  tr[ *stm1__->auxBits()] = tunebits; //For external RF relays.
96  });
97  }
98  if(stm2__) {
99  stm2__->iterate_commit([=](Transaction &tr){
100  tr[ *stm2__->active()] = true; // Activate motor.
101  tr[ *stm2__->auxBits()] = tunebits; //For external RF relays.
102  });
103  }
104  iterate_commit([=](Transaction &tr){
105  tr[ *m_tuning] = true;
106  tr[ *succeeded()] = false;
107  tr[ *this].iteration_count = 0;
108  tr[ *this].ref_f0_best = 1e10;
109  tr[ *this].isSTMChanged = true;
110  tr[ *this].sor_factor = SOR_FACTOR_MAX;
111  tr[ *this].stage = Payload::STAGE_FIRST;
112  tr[ *this].trace.clear();
113  tr[ *this].dCa = 0.0;
114  tr[ *this].dCb = 0.0;
115  tr[ *this].started = XTime::now();
116  tr[ *this].isTargetAbondoned = false;
117  });
118 }
119 void XAutoLCTuner::onAbortTuningTouched(const Snapshot &shot, XTouchableNode *) {
120  iterate_commit_while([=](Transaction &tr)->bool{
121  if( !tr[ *m_tuning])
122  return false;
123  tr[ *m_tuning] = false;
124  tr[ *this].isSTMChanged = false;
125  return true;
126  });
127 }
128 void
129 XAutoLCTuner::determineNextC(double &deltaC1, double &deltaC2,
130  double x, double x_err,
131  double y, double y_err,
132  double dxdC1, double dxdC2,
133  double dydC1, double dydC2) {
134  double det = dxdC1 * dydC2 - dxdC2 *dydC1;
135  double slimit = 1e-60;
136  x -= ((x > 0) ? 1 : -1) * std::min(x_err, fabs(x)); //reduces as large as err.
137  y -= ((y > 0) ? 1 : -1) * std::min(y_err, fabs(y));
138  if(det > slimit) {
139  deltaC1 = -(dydC2 * x - dxdC2 * y) / det;
140  deltaC2 = -( -dydC1 * x + dxdC1 * y) / det;
141  }
142  else {
143  if(fabs(x) > x_err) {
144  //superior to y
145  if(fabs(dxdC2) > slimit) {
146  deltaC2 = -x / dxdC2;
147  }
148  if(fabs(dxdC1) > slimit) {
149  deltaC1 = -x / dxdC1;
150  }
151  }
152  else {
153  if(fabs(dydC2) > slimit) {
154  deltaC2 = -y / dydC2;
155  }
156  if(fabs(dydC1) > slimit) {
157  deltaC1 = -y / dydC1;
158  }
159  }
160  }
161 }
163  const Snapshot &shot_emitter, const Snapshot &shot_others,
164  XDriver *emitter) const {
165  const shared_ptr<XMotorDriver> stm1__ = shot_this[ *stm1()];
166  const shared_ptr<XMotorDriver> stm2__ = shot_this[ *stm2()];
167  const shared_ptr<XNetworkAnalyzer> na__ = shot_this[ *netana()];
168  if( !na__)
169  return false;
170  if(stm1__ == stm2__)
171  return false;
172  if(emitter != na__.get())
173  return false;
174 
175  return true;
176 }
177 void
178 XAutoLCTuner::rollBack(Transaction &tr) {
179  fprintf(stderr, "LCtuner: Rolls back.\n");
180  //rolls back to good positions.
181  tr[ *this].isSTMChanged = true;
182  tr[ *this].dCa = 0.0;
183  tr[ *this].dCb = 0.0;
184  tr[ *this].stm1 = tr[ *this].stm1_best;
185  tr[ *this].stm2 = tr[ *this].stm2_best;
186  tr[ *this].ref_f0_best = 1e10; //resets the best pos.
187  throw XSkippedRecordError(__FILE__, __LINE__);
188 }
189 void
190 XAutoLCTuner::abortTuningFromAnalyze(Transaction &tr, std::complex<double> reff0) {
191  double tune_approach_goal2 = pow(10.0, 0.05 * tr[ *reflectionRequired()]);
192  if(tune_approach_goal2 > std::abs(tr[ *this].ref_f0_best)) {
193  fprintf(stderr, "LCtuner: Softens target value.\n");
194  tr[ *this].iteration_count = 0;
195  tr[ *this].ref_f0_best = 1e10;
196  tr[ *this].isSTMChanged = true;
197  tr[ *this].sor_factor = SOR_FACTOR_MAX;
198  tr[ *this].stage = Payload::STAGE_FIRST;
199  tr[ *this].trace.clear();
200  tr[ *this].started = XTime::now();
201  tr[ *this].isTargetAbondoned = true;
202  rollBack(tr); //rolls back and skps.
203  }
204  tr[ *m_tuning] = false;
205  if(std::abs(reff0) > std::abs(tr[ *this].ref_f0_best)) {
206  tr[ *this].isSTMChanged = true;
207  tr[ *this].stm1 = tr[ *this].stm1_best;
208  tr[ *this].stm2 = tr[ *this].stm2_best;
209  throw XRecordError(i18n("Aborting. Out of tune, or capacitors have sticked. Back to better positions."), __FILE__, __LINE__);
210  }
211  throw XRecordError(i18n("Aborting. Out of tune, or capacitors have sticked."), __FILE__, __LINE__);
212 }
213 void
214 XAutoLCTuner::analyze(Transaction &tr, const Snapshot &shot_emitter,
215  const Snapshot &shot_others,
216  XDriver *emitter) throw (XRecordError&) {
217  const Snapshot &shot_this(tr);
218  const Snapshot &shot_na(shot_emitter);
219 
220  shared_ptr<XMotorDriver> stm1__ = shot_this[ *stm1()];
221  shared_ptr<XMotorDriver> stm2__ = shot_this[ *stm2()];
222  //remembers original position.
223  if(stm1__)
224  tr[ *this].stm1 = shot_others[ *stm1__->position()->value()];
225  if(stm2__)
226  tr[ *this].stm2 = shot_others[ *stm2__->position()->value()];
227  if( !shot_this[ *useSTM1()]) stm1__.reset();
228  if( !shot_this[ *useSTM2()]) stm2__.reset();
229 
230  if( (stm1__ && !shot_others[ *stm1__->ready()]) ||
231  ( stm2__ && !shot_others[ *stm2__->ready()]))
232  throw XSkippedRecordError(__FILE__, __LINE__); //STM is moving. skip.
233  if( shot_this[ *this].isSTMChanged) {
234  tr[ *this].isSTMChanged = false;
235  throw XSkippedRecordError(__FILE__, __LINE__); //the present data may involve one before STM was moved. reload.
236  }
237  if( !shot_this[ *tuning()]) {
238  throw XSkippedRecordError(__FILE__, __LINE__);
239  }
240 
241  if( !stm1__ && !stm2__) {
242  tr[ *m_tuning] = false;
243  throw XSkippedRecordError(__FILE__, __LINE__);
244  }
245 
246  const shared_ptr<XNetworkAnalyzer> na__ = shot_this[ *netana()];
247 
248  int trace_len = shot_na[ *na__].length();
249  double ref_sigma = 0.0;
250  {
251  const std::complex<double> *trace = shot_na[ *na__].trace();
252  if(shot_this[ *this].trace.size() != trace_len) {
253  //copies trace.
254  tr[ *this].trace.resize(trace_len);
255  for(int i = 0; i < trace_len; ++i) {
256  tr[ *this].trace[i] = trace[i];
257  }
258  //re-acquires the same situation.
259  throw XSkippedRecordError(__FILE__, __LINE__);
260  }
261 
262  //estimates errors.
263  for(int i = 0; i < trace_len; ++i) {
264  ref_sigma += std::norm(trace[i] - shot_this[ *this].trace[i]);
265  tr[ *this].trace[i] = (shot_this[ *this].trace[i] + trace[i]) / 2.0; //takes averages.
266  }
267  ref_sigma = sqrt(ref_sigma / trace_len);
268  if(ref_sigma > 0.1) {
269  tr[ *this].trace.clear();
270  throw XSkippedRecordError(i18n("Too large errors in the trace."), __FILE__, __LINE__);
271  }
272  }
273  double trace_dfreq = shot_na[ *na__].freqInterval();
274  double trace_start = shot_na[ *na__].startFreq();
275  double fmin_err;
276  double fmin;
277  std::complex<double> reffmin(0.0);
278  double f0 = shot_this[ *target()];
279  std::complex<double> reff0(0.0);
280  double reffmin_sigma, reff0_sigma;
281  //analyzes trace.
282  {
283  const std::complex<double> *trace = &shot_this[ *this].trace[0];
284 
285  std::complex<double> reffmin_peak(1e10);
286  //searches for minimum in reflection.
287  double fmin_peak = 0;
288  for(int i = 0; i < trace_len; ++i) {
289  double z = std::abs(trace[i]);
290  if(std::abs(reffmin_peak) > z) {
291  reffmin_peak = trace[i];
292  fmin_peak = trace_start + i * trace_dfreq;
293  }
294  }
295 
296  //Takes averages around the minimum.
297  reffmin = reffmin_peak;
298  double ref_sigma_sq = ref_sigma * ref_sigma;
299  for(int cnt = 0; cnt < 2; ++cnt) {
300  double wsum = 0.0;
301  double wsqsum = 0.0;
302  std::complex<double> refsum = 0.0;
303  double fsum = 0.0;
304  double fsqsum = 0.0;
305  for(int i = 0; i < trace_len; ++i) {
306  double f = trace_start + i * trace_dfreq;
307  double zsq = std::norm(trace[i] - reffmin);
308  if(zsq < ref_sigma_sq * 10) {
309  double w = exp( -zsq / (2.0 * ref_sigma_sq));
310  wsum += w;
311  wsqsum += w * w;
312  refsum += w * trace[i];
313  fsum += w * f;
314  fsqsum += w * w * (f - fmin) * (f - fmin);
315  }
316  }
317  fmin = fsum / wsum;
318  fmin_err = sqrt(fsqsum / wsum / wsum + trace_dfreq * trace_dfreq);
319  reffmin = refsum / wsum;
320  reffmin_sigma = ref_sigma * sqrt(wsqsum) / wsum;
321  }
322  //Takes averages around the target frequency.
323  double wsum = 0.0;
324  double wsqsum = 0.0;
325  std::complex<double> refsum = 0.0;
326  double f0_err = std::min(trace_dfreq * 5, fmin_err);
327  for(int i = 0; i < trace_len; ++i) {
328  double f = trace_start + i * trace_dfreq;
329  if(fabs(f - f0) < f0_err * 10) {
330  double w = exp( -(f - f0) * (f - f0) / (2.0 * f0_err * f0_err));
331  wsum += w;
332  wsqsum += w * w;
333  refsum += w * trace[i];
334  }
335  }
336  reff0 = refsum / wsum;
337  reff0_sigma = ref_sigma * sqrt(wsqsum / wsum * wsum);
338  fprintf(stderr, "LCtuner: fmin=%.4f+-%.4f, reffmin=%.3f+-%.3f, reff0=%.3f+-%.3f\n",
339  fmin, fmin_err, std::abs(reffmin), reffmin_sigma, std::abs(reff0), reff0_sigma);
340 
341  tr[ *this].trace.clear();
342  }
343 
344  if(std::abs(reff0) < reff0_sigma * 2) {
345  tr[ *succeeded()] = true;
346  fprintf(stderr, "LCtuner: tuning done within errors.\n");
347  return;
348  }
349 
350  if(( !stm1__ || !stm2__) && (std::abs(fmin - f0) < fmin_err)) {
351  tr[ *succeeded()] = true;
352  fprintf(stderr, "LCtuner: tuning done within errors.\n");
353  return;
354  }
355 
356 
357  double tune_approach_goal = pow(10.0, 0.05 * shot_this[ *reflectionTargeted()]);
358  if(shot_this[ *this].isTargetAbondoned)
359  tune_approach_goal = pow(10.0, 0.05 * shot_this[ *reflectionRequired()]);
360  if(std::abs(reff0) < tune_approach_goal) {
361  fprintf(stderr, "LCtuner: tuning done satisfactorily.\n");
362  tr[ *succeeded()] = true;
363  return;
364  }
365 
366  tr[ *this].iteration_count++;
367  if(std::abs(shot_this[ *this].ref_f0_best) > std::abs(reff0)) {
368  tr[ *this].iteration_count = 0;
369  //remembers good positions.
370  tr[ *this].stm1_best = tr[ *this].stm1;
371  tr[ *this].stm2_best = tr[ *this].stm2;
372  tr[ *this].fmin_best = fmin;
373  tr[ *this].ref_f0_best = std::abs(reff0) + reff0_sigma;
374  tr[ *this].sor_factor = (tr[ *this].sor_factor + SOR_FACTOR_MAX) / 2;
375  }
376 // else
377 // tr[ *this].sor_factor = std::min(tr[ *this].sor_factor, (SOR_FACTOR_MAX + SOR_FACTOR_MIN) / 2);
378 
379  bool timeout = (XTime::now() - shot_this[ *this].started > 360); //6min.
380  if(timeout) {
381  fprintf(stderr, "LCtuner: Time out.\n");
382  abortTuningFromAnalyze(tr, reff0);//Aborts.
383  return;
384  }
385 
386  Payload::STAGE stage = shot_this[ *this].stage;
387 
388  if(stage == Payload::STAGE_FIRST) {
389  if((std::abs(shot_this[ *this].ref_f0_best) + reff0_sigma < std::abs(reff0)) &&
390  ((shot_this[ *this].iteration_count > 10) ||
391  ((shot_this[ *this].iteration_count > 4) && (std::abs(shot_this[ *this].ref_f0_best) * 1.5 < std::abs(reff0) - reff0_sigma)))) {
392  tr[ *this].iteration_count = 0;
393  tr[ *this].sor_factor = (tr[ *this].sor_factor + SOR_FACTOR_MIN) / 2;
394  if(shot_this[ *this].sor_factor < (SOR_FACTOR_MAX - SOR_FACTOR_MIN) * pow(2.0, -6.0) + SOR_FACTOR_MIN) {
395  abortTuningFromAnalyze(tr, reff0);//Aborts.
396  return;
397  }
398  rollBack(tr); //rolls back and skps.
399  }
400  }
401 
402  if(stage == Payload::STAGE_FIRST) {
403  fprintf(stderr, "LCtuner: the first stage\n");
404  //Ref(0, 0)
405  if(std::abs(reff0) < TUNE_FINETUNE_START) {
406  fprintf(stderr, "LCtuner: finetune mode\n");
407  tr[ *this].mode = Payload::TUNE_FINETUNE;
408  }
409  else {
410  fprintf(stderr, "LCtuner: approach mode\n");
411  tr[ *this].mode = Payload::TUNE_APPROACHING;
412  }
413  }
414  //Selects suitable reflection point to be minimized.
415  std::complex<double> ref_targeted;
416  double tune_drot_required_nsigma;
417  double tune_drot_mul;
418  switch(shot_this[ *this].mode) {
419  case Payload::TUNE_FINETUNE:
420  ref_targeted = reff0;
421  ref_sigma = reff0_sigma;
422  tune_drot_required_nsigma = TUNE_DROT_REQUIRED_N_SIGMA_FINETUNE;
423  tune_drot_mul = TUNE_DROT_MUL_FINETUNE;
424  break;
425  case Payload::TUNE_APPROACHING:
426  ref_targeted = reffmin;
427  ref_sigma = reffmin_sigma;
428  tune_drot_required_nsigma = TUNE_DROT_REQUIRED_N_SIGMA_APPROACH;
429  tune_drot_mul = TUNE_DROT_MUL_APPROACH;
430  break;
431  }
432  switch(stage) {
433  default:
434  case Payload::STAGE_FIRST:
435  //Ref(0, 0)
436  tr[ *this].fmin_first = fmin;
437  tr[ *this].ref_first = ref_targeted;
438  double tune_drot;
439  switch(shot_this[ *this].mode) {
440  case Payload::TUNE_APPROACHING:
441  tune_drot = TUNE_DROT_APPROACH;
442  break;
443  case Payload::TUNE_FINETUNE:
444  tune_drot = TUNE_DROT_FINETUNE;
445  break;
446  }
447  tr[ *this].dCa /= tune_drot_mul * tune_drot_mul; //considers the last change.
448  tr[ *this].dCb /= tune_drot_mul * tune_drot_mul;
449  if(fabs(tr[ *this].dCa) < tune_drot)
450  tr[ *this].dCa = tune_drot * ((shot_this[ *this].dfmin_dCa * (fmin - f0) < 0) ? 1.0 : -1.0); //direction to approach.
451  if(fabs(tr[ *this].dCb) < tune_drot)
452  tr[ *this].dCb = tune_drot * ((shot_this[ *this].dfmin_dCb * (fmin - f0) < 0) ? 1.0 : -1.0);
453 
454  tr[ *this].isSTMChanged = true;
455  tr[ *this].stage = Payload::STAGE_DCA;
456  if(stm1__)
457  tr[ *this].stm1 += tr[ *this].dCa;
458  else
459  tr[ *this].stm2 += tr[ *this].dCa;
460  throw XSkippedRecordError(__FILE__, __LINE__); //rotate Ca
461  break;
462  case Payload::STAGE_DCA:
463  {
464  fprintf(stderr, "LCtuner: +dCa\n");
465  //Ref( +dCa, 0), averaged with the previous.
466  tr[ *this].fmin_plus_dCa = fmin;
467  tr[ *this].ref_plus_dCa = ref_targeted;
468 
469  //derivative of freq_min.
470  double dfmin = shot_this[ *this].fmin_plus_dCa - shot_this[ *this].fmin_first;
471  tr[ *this].dfmin_dCa = dfmin / shot_this[ *this].dCa;
472 
473  //derivative of reflection.
474  std::complex<double> dref;
475  dref = shot_this[ *this].ref_plus_dCa - shot_this[ *this].ref_first;
476  tr[ *this].dref_dCa = dref / shot_this[ *this].dCa;
477 
478  if((fabs(dfmin) < fmin_err * tune_drot_required_nsigma) &&
479  (std::abs(dref) < ref_sigma * tune_drot_required_nsigma)) {
480  if(fabs(tr[ *this].dCa) < TUNE_DROT_ABORT) {
481  tr[ *this].dCa *= tune_drot_mul; //increases rotation angle to measure derivative.
482  tr[ *this].fmin_first = fmin; //the present data may be influenced by backlashes.
483  tr[ *this].ref_first = ref_targeted;
484  if(stm1__)
485  tr[ *this].stm1 += tr[ *this].dCa;
486  else
487  tr[ *this].stm2 += tr[ *this].dCa;
488  tr[ *this].isSTMChanged = true;
489  tr[ *this].stage = Payload::STAGE_DCA; //rotate C1 more and try again.
490  fprintf(stderr, "LCtuner: increasing dCa to %f\n", (double)tr[ *this].dCa);
491  throw XSkippedRecordError(__FILE__, __LINE__);
492  }
493  if( !stm1__ || !stm2__) {
494  abortTuningFromAnalyze(tr, reff0);//C1/C2 is useless. Aborts.
495  return;
496  }
497  //Ca is useless, try Cb.
498  }
499  if(stm1__ && stm2__) {
500  tr[ *this].isSTMChanged = true;
501  tr[ *this].stage = Payload::STAGE_DCB; //to next stage.
502  tr[ *this].stm2 += tr[ *this].dCb;
503  throw XSkippedRecordError(__FILE__, __LINE__);
504  }
505  break; //to final.
506  }
507  case Payload::STAGE_DCB:
508  fprintf(stderr, "LCtuner: +dCb\n");
509  //Ref( 0, +dCb)
510  //derivative of freq_min.
511  double dfmin = fmin - shot_this[ *this].fmin_plus_dCa;
512  tr[ *this].dfmin_dCb = dfmin / shot_this[ *this].dCb;
513 
514  //derivative of reflection.
515  std::complex<double> dref;
516  dref = ref_targeted - shot_this[ *this].ref_plus_dCa;
517  tr[ *this].dref_dCb = dref / shot_this[ *this].dCb;
518 
519  if((std::min(fabs(shot_this[ *this].dfmin_dCa * shot_this[ *this].dCa), fabs(dfmin)) < fmin_err * tune_drot_required_nsigma) &&
520  (std::min(std::abs(shot_this[ *this].dref_dCa * shot_this[ *this].dCa), std::abs(dref)) < ref_sigma * tune_drot_required_nsigma)) {
521  if(fabs(tr[ *this].dCb) < TUNE_DROT_ABORT) {
522  tr[ *this].dCb *= tune_drot_mul; //increases rotation angle to measure derivative.
523  tr[ *this].fmin_plus_dCa = fmin; //the present data may be influenced by backlashes.
524  tr[ *this].ref_plus_dCa = ref_targeted;
525  tr[ *this].stm2 += tr[ *this].dCb;
526  tr[ *this].isSTMChanged = true;
527  fprintf(stderr, "LCtuner: increasing dCb to %f\n", (double)tr[ *this].dCb);
528  //rotate Cb more and try again.
529  throw XSkippedRecordError(__FILE__, __LINE__);
530  }
531  if(fabs(tr[ *this].dCa) >= TUNE_DROT_ABORT) {
532  abortTuningFromAnalyze(tr, reff0);//C1/C2 is useless. Aborts.
533  return;
534  }
535  }
536  break;
537  }
538  //Final stage.
539  tr[ *this].stage = Payload::STAGE_FIRST;
540 
541  std::complex<double> dref_dCa = shot_this[ *this].dref_dCa;
542  std::complex<double> dref_dCb = shot_this[ *this].dref_dCb;
543  double gamma;
544  switch(shot_this[ *this].mode) {
545  case Payload::TUNE_FINETUNE:
546 // gamma = 0.5;
547 // break;
548  case Payload::TUNE_APPROACHING:
549  gamma = 1.0;
550  break;
551  }
552  double a = gamma * 2.0 * pow(std::norm(ref_targeted), gamma - 1.0);
553  // d |ref^2|^gamma / dCa,b
554  double drefgamma_dCa = a * (std::real(ref_targeted) * std::real(dref_dCa) + std::imag(ref_targeted) * std::imag(dref_dCa));
555  double drefgamma_dCb = a * (std::real(ref_targeted) * std::real(dref_dCb) + std::imag(ref_targeted) * std::imag(dref_dCb));
556 
557  double dfmin_dCa = shot_this[ *this].dfmin_dCa;
558  double dfmin_dCb = shot_this[ *this].dfmin_dCb;
559  if( !stm1__ || !stm2__) {
560  dref_dCb = 0.0;
561  drefgamma_dCb = 0.0;
562  dfmin_dCb = 0.0;
563  }
564  double dCa_next = 0;
565  double dCb_next = 0;
566 
567  fprintf(stderr, "LCtuner: dref_dCa=%.2g, dref_dCb=%.2g, dfmin_dCa=%.2g, dfmin_dCb=%.2g\n",
568  drefgamma_dCa, drefgamma_dCb, dfmin_dCa, dfmin_dCb);
569 
570  determineNextC( dCa_next, dCb_next,
571  pow(std::norm(ref_targeted), gamma), pow(ref_sigma, gamma * 2.0),
572  (fmin - f0), fmin_err,
573  drefgamma_dCa, drefgamma_dCb,
574  dfmin_dCa, dfmin_dCb);
575 
576  fprintf(stderr, "LCtuner: deltaCa=%f, deltaCb=%f\n", dCa_next, dCb_next);
577 
578  //restricts changes within the trust region.
579  double dc_trust;
580  switch(shot_this[ *this].mode) {
581  case Payload::TUNE_APPROACHING:
582  dc_trust = TUNE_TRUST_APPROACH;
583  break;
584  case Payload::TUNE_FINETUNE:
585  dc_trust = TUNE_TRUST_FINETUNE;
586  break;
587  }
588  double dca_trust = fabs(shot_this[ *this].dCa) * 50;
589  double dcb_trust = fabs(shot_this[ *this].dCb) * 50;
590  //mixes with the best result.
591  double sor = shot_this[ *this].sor_factor;
592  double red_fac = 1.0;
593  if(fabs(tr[ *this].dCa) < fabs(dCa_next)) {
594  if(stm1__)
595  dCa_next = dCa_next * sor + (tr[ *this].stm1_best - tr[ *this].stm1) * (1.0 - sor);
596  else
597  dCa_next = dCa_next * sor + (tr[ *this].stm2_best - tr[ *this].stm2) * (1.0 - sor);
598  red_fac =std::min(red_fac, std::min(dc_trust, dca_trust) / fabs(dCa_next));
599  }
600  if(fabs(tr[ *this].dCb) < fabs(dCb_next)) {
601  if(stm1__ && stm2__)
602  dCb_next = dCb_next * sor + (tr[ *this].stm2_best - tr[ *this].stm2) * (1.0 - sor);
603  red_fac =std::min(red_fac, std::min(dc_trust, dcb_trust) / fabs(dCb_next));
604  }
605  dCa_next *= red_fac;
606  dCb_next *= red_fac;
607  fprintf(stderr, "LCtuner: deltaCa=%f, deltaCb=%f\n", dCa_next, dCb_next);
608 
609  tr[ *this].isSTMChanged = true;
610  if(stm1__)
611  tr[ *this].stm1 += dCa_next;
612  if(stm2__) {
613  if(stm1__)
614  tr[ *this].stm2 += dCb_next;
615  else
616  tr[ *this].stm2 += dCa_next;
617  }
618  tr[ *this].dCa = dCa_next;
619  tr[ *this].dCb = dCb_next;
620  throw XSkippedRecordError(__FILE__, __LINE__);
621 }
622 void
624  const shared_ptr<XMotorDriver> stm1__ = shot_this[ *stm1()];
625  const shared_ptr<XMotorDriver> stm2__ = shot_this[ *stm2()];
626  if(shot_this[ *tuning()]) {
627  if(shot_this[ *succeeded()]){
628  const unsigned int tunebits = 0;
629  if(stm1__) {
630  stm1__->iterate_commit([=](Transaction &tr){
631  tr[ *stm1__->active()] = false; //Deactivates motor.
632  tr[ *stm1__->auxBits()] = tunebits; //For external RF relays.
633  });
634  }
635  if(stm2__) {
636  stm2__->iterate_commit([=](Transaction &tr){
637  tr[ *stm2__->active()] = false; //Deactivates motor.
638  tr[ *stm2__->auxBits()] = tunebits; //For external RF relays.
639  });
640  }
641  msecsleep(50); //waits for relays.
642  trans( *tuning()) = false; //finishes tuning successfully.
643  }
644  }
645  if(shot_this[ *this].isSTMChanged) {
646  if(stm1__) {
647  stm1__->iterate_commit_while([=](Transaction &tr)->bool{
648  if(tr[ *stm1__->position()->value()] == shot_this[ *this].stm1)
649  return false;
650  tr[ *stm1__->target()] = shot_this[ *this].stm1;
651  return true;
652  });
653  }
654  if(stm2__) {
655  stm2__->iterate_commit_while([=](Transaction &tr)->bool{
656  if(tr[ *stm2__->position()->value()] == shot_this[ *this].stm2)
657  return false;
658  tr[ *stm2__->target()] = shot_this[ *this].stm2;
659  return true;
660  });
661  }
662  msecsleep(50); //waits for ready indicators.
663  if( !shot_this[ *tuning()]) {
664  trans( *this).isSTMChanged = false;
665  }
666  }
667 }
668 

Generated for KAME4 by  doxygen 1.8.3