Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
experimentdocument2d.cpp
Go to the documentation of this file.
1/**
2 * @file experimentdocument2d.cpp
3 * @brief Implements schema-28 experiment JSON serialization, parsing, validation, and compatibility handling.
4 * @ingroup qpe_experiments
5 *
6 * Source: @c core/experiments/experimentdocument2d.cpp. This file is part of Quantum Phenomena Explorer (QPE),
7 * maintained by Officina Turini. See LICENSE_IT.txt / LICENSE.txt for the
8 * QPE freeware source-available terms and THIRD_PARTY_NOTICES.txt for
9 * third-party components.
10 */
11
13
14#include <QFile>
15#include <QJsonArray>
16#include <QJsonDocument>
17#include <QJsonObject>
18#include <QJsonParseError>
19#include <QSaveFile>
20
21#include <cmath>
22
23namespace qpe {
24namespace {
25
26/**
27 * @brief Performs potential type name.
28 * @param type The type value used by the operation.
29 */
31{
32 switch (type) {
33 case PotentialObjectType2D::Rectangle: return QStringLiteral("rectangle");
34 case PotentialObjectType2D::Circle: return QStringLiteral("circle");
35 case PotentialObjectType2D::Barrier: return QStringLiteral("barrier");
36 case PotentialObjectType2D::SingleSlit: return QStringLiteral("singleSlit");
37 case PotentialObjectType2D::DoubleSlit: return QStringLiteral("doubleSlit");
38 case PotentialObjectType2D::PolygonWedge: return QStringLiteral("polygonWedge");
39 case PotentialObjectType2D::Gaussian: return QStringLiteral("gaussian");
40 case PotentialObjectType2D::Harmonic: return QStringLiteral("harmonic");
41 case PotentialObjectType2D::Linear: return QStringLiteral("linear");
42 case PotentialObjectType2D::SoftenedRadial: return QStringLiteral("softenedRadial");
43 case PotentialObjectType2D::StadiumExterior: return QStringLiteral("stadiumExterior");
44 }
45 return QString();
46}
47
48/**
49 * @brief Performs potential type from name.
50 * @param name The name value used by the operation.
51 * @param type The type value used by the operation.
52 */
53bool potentialTypeFromName(const QString &name, PotentialObjectType2D &type)
54{
55 if (name == QStringLiteral("rectangle")) type = PotentialObjectType2D::Rectangle;
56 else if (name == QStringLiteral("circle")) type = PotentialObjectType2D::Circle;
57 else if (name == QStringLiteral("barrier")) type = PotentialObjectType2D::Barrier;
58 else if (name == QStringLiteral("singleSlit")) type = PotentialObjectType2D::SingleSlit;
59 else if (name == QStringLiteral("doubleSlit")) type = PotentialObjectType2D::DoubleSlit;
60 else if (name == QStringLiteral("polygonWedge")) type = PotentialObjectType2D::PolygonWedge;
61 else if (name == QStringLiteral("gaussian")) type = PotentialObjectType2D::Gaussian;
62 else if (name == QStringLiteral("harmonic")) type = PotentialObjectType2D::Harmonic;
63 else if (name == QStringLiteral("linear")) type = PotentialObjectType2D::Linear;
64 else if (name == QStringLiteral("softenedRadial")) type = PotentialObjectType2D::SoftenedRadial;
65 else if (name == QStringLiteral("stadiumExterior")) type = PotentialObjectType2D::StadiumExterior;
66 else return false;
67 return true;
68}
69
70/**
71 * @brief Performs potential object to json.
72 * @param object The object value used by the operation.
73 */
74QJsonObject potentialObjectToJson(const PotentialObject2D &object)
75{
76 QJsonObject json;
77 json.insert(QStringLiteral("id"), QString::number(static_cast<qulonglong>(object.id)));
78 json.insert(QStringLiteral("type"), potentialTypeName(object.type));
79 json.insert(QStringLiteral("enabled"), object.enabled);
80 json.insert(QStringLiteral("value"), object.value);
81 json.insert(QStringLiteral("centerX"), object.centerX);
82 json.insert(QStringLiteral("centerY"), object.centerY);
83 json.insert(QStringLiteral("width"), object.width);
84 json.insert(QStringLiteral("height"), object.height);
85 json.insert(QStringLiteral("radius"), object.radius);
86 json.insert(QStringLiteral("length"), object.length);
87 json.insert(QStringLiteral("thickness"), object.thickness);
88 json.insert(QStringLiteral("wallWidth"), object.wallWidth);
89 json.insert(QStringLiteral("slitHeight"), object.slitHeight);
90 json.insert(QStringLiteral("slitSeparation"), object.slitSeparation);
91 json.insert(QStringLiteral("sigmaX"), object.sigmaX);
92 json.insert(QStringLiteral("sigmaY"), object.sigmaY);
93 json.insert(QStringLiteral("curvatureX"), object.curvatureX);
94 json.insert(QStringLiteral("curvatureY"), object.curvatureY);
95 json.insert(QStringLiteral("slopeX"), object.slopeX);
96 json.insert(QStringLiteral("slopeY"), object.slopeY);
97 json.insert(QStringLiteral("softening"), object.softening);
98 return json;
99}
100
101/**
102 * @brief Performs finite json number.
103 * @param json The json value used by the operation.
104 * @param name The name value used by the operation.
105 * @param value Value to assign or evaluate.
106 */
107bool finiteJsonNumber(const QJsonObject &json, const char *name, float &value)
108{
109 const QJsonValue item = json.value(QString::fromLatin1(name));
110 if (!item.isDouble()) {
111 return false;
112 }
113 const double number = item.toDouble();
114 if (!std::isfinite(number)) {
115 return false;
116 }
117 value = static_cast<float>(number);
118 return std::isfinite(static_cast<double>(value));
119}
120
121/**
122 * @brief Performs potential object from json.
123 * @param json The json value used by the operation.
124 * @param object The object value used by the operation.
125 * @param errorMessage The error message value used by the operation.
126 * @param index Zero-based index of the selected item.
127 */
128bool potentialObjectFromJson(const QJsonObject &json,
129 PotentialObject2D &object,
130 QString &errorMessage,
131 int index)
132{
133 PotentialObject2D parsed;
134
135 const QString idText = json.value(QStringLiteral("id")).toString();
136 bool idOk = false;
137 const qulonglong id = idText.toULongLong(&idOk);
138 if (!idOk || id == 0) {
139 errorMessage = QStringLiteral("Potential scene object %1 has an invalid id.").arg(index);
140 return false;
141 }
142 parsed.id = static_cast<std::uint64_t>(id);
143
144 if (!potentialTypeFromName(json.value(QStringLiteral("type")).toString(), parsed.type)) {
145 errorMessage = QStringLiteral("Potential scene object %1 has an unknown type.").arg(index);
146 return false;
147 }
148
149 const QJsonValue enabledValue = json.value(QStringLiteral("enabled"));
150 if (!enabledValue.isBool()) {
151 errorMessage = QStringLiteral("Potential scene object %1 has an invalid enabled flag.").arg(index);
152 return false;
153 }
154 parsed.enabled = enabledValue.toBool();
155
156 const char *fields[] = {
157 "value", "centerX", "centerY", "width", "height", "radius",
158 "length", "thickness", "wallWidth", "slitHeight", "slitSeparation"
159 };
160 float *values[] = {
161 &parsed.value, &parsed.centerX, &parsed.centerY, &parsed.width,
162 &parsed.height, &parsed.radius, &parsed.length, &parsed.thickness,
163 &parsed.wallWidth, &parsed.slitHeight, &parsed.slitSeparation
164 };
165 const int fieldCount = static_cast<int>(sizeof(fields) / sizeof(fields[0]));
166 for (int i = 0; i < fieldCount; ++i) {
167 if (!finiteJsonNumber(json, fields[i], *values[i])) {
168 errorMessage = QStringLiteral("Potential scene object %1 has invalid numeric field '%2'.")
169 .arg(index)
170 .arg(QString::fromLatin1(fields[i]));
171 return false;
172 }
173 }
174
175 const char *smoothFields[] = {
176 "sigmaX", "sigmaY", "curvatureX", "curvatureY",
177 "slopeX", "slopeY", "softening"
178 };
179 float *smoothValues[] = {
180 &parsed.sigmaX, &parsed.sigmaY, &parsed.curvatureX, &parsed.curvatureY,
181 &parsed.slopeX, &parsed.slopeY, &parsed.softening
182 };
183 const int smoothCount = static_cast<int>(sizeof(smoothFields) / sizeof(smoothFields[0]));
184 for (int i = 0; i < smoothCount; ++i) {
185 const QJsonValue item = json.value(QString::fromLatin1(smoothFields[i]));
186 if (item.isUndefined()) {
187 continue; // schema-2 geometric scene
188 }
189 if (!finiteJsonNumber(json, smoothFields[i], *smoothValues[i])) {
190 errorMessage = QStringLiteral("Potential scene object %1 has invalid numeric field '%2'.")
191 .arg(index)
192 .arg(QString::fromLatin1(smoothFields[i]));
193 return false;
194 }
195 }
196
197 if (!parsed.valid()) {
198 errorMessage = QStringLiteral("Potential scene object %1 contains invalid geometry dimensions.").arg(index);
199 return false;
200 }
201
202 object = parsed;
203 return true;
204}
205
206/**
207 * @brief Performs potential scene to json.
208 * @param document The document value used by the operation.
209 */
210QJsonObject potentialSceneToJson(const ExperimentDocument2D &document)
211{
212 QJsonArray objects;
213 const std::vector<PotentialObject2D> &sceneObjects = document.potentialScene.objects();
214 for (const PotentialObject2D &object : sceneObjects) {
215 objects.append(potentialObjectToJson(object));
216 }
217
218 QJsonObject scene;
219 scene.insert(QStringLiteral("active"), document.potentialSceneActive);
220 scene.insert(QStringLiteral("composition"), QStringLiteral("additive"));
221 scene.insert(QStringLiteral("objects"), objects);
222 return scene;
223}
224
225/**
226 * @brief Performs potential scene from json.
227 * @param json The json value used by the operation.
228 * @param document The document value used by the operation.
229 * @param errorMessage The error message value used by the operation.
230 */
231bool potentialSceneFromJson(const QJsonObject &json,
232 ExperimentDocument2D &document,
233 QString &errorMessage)
234{
235 const QJsonValue sceneValue = json.value(QStringLiteral("potentialScene"));
236 if (!sceneValue.isObject()) {
237 errorMessage = QStringLiteral("Experiment schema 2/3/4/5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23 is missing a valid potentialScene object.");
238 return false;
239 }
240
241 const QJsonObject sceneJson = sceneValue.toObject();
242 const QJsonValue activeValue = sceneJson.value(QStringLiteral("active"));
243 const QJsonValue objectsValue = sceneJson.value(QStringLiteral("objects"));
244 if (!activeValue.isBool() || !objectsValue.isArray()) {
245 errorMessage = QStringLiteral("Experiment potentialScene must contain active and objects fields.");
246 return false;
247 }
248
249 const QString composition = sceneJson.value(QStringLiteral("composition")).toString();
250 if (!composition.isEmpty() && composition != QStringLiteral("additive")) {
251 errorMessage = QStringLiteral("Unsupported potential scene composition '%1'.").arg(composition);
252 return false;
253 }
254
255 PotentialScene2D scene;
256 const QJsonArray objects = objectsValue.toArray();
257 if (objects.size() > 512) {
258 errorMessage = QStringLiteral("Potential scene contains too many objects (%1).").arg(objects.size());
259 return false;
260 }
261
262 for (int i = 0; i < objects.size(); ++i) {
263 if (!objects.at(i).isObject()) {
264 errorMessage = QStringLiteral("Potential scene object %1 is not a JSON object.").arg(i);
265 return false;
266 }
267 PotentialObject2D object;
268 if (!potentialObjectFromJson(objects.at(i).toObject(), object, errorMessage, i)) {
269 return false;
270 }
271 const std::uint64_t requestedId = object.id;
272 const std::uint64_t insertedId = scene.add(object);
273 if (insertedId != requestedId) {
274 errorMessage = QStringLiteral("Potential scene contains duplicate object id %1.")
275 .arg(QString::number(static_cast<qulonglong>(requestedId)));
276 return false;
277 }
278 }
279
280 document.potentialSceneActive = activeValue.toBool();
281 document.potentialScene = scene;
282 if (document.potentialSceneActive && document.potentialScene.empty()) {
283 document.potentialSceneActive = false;
284 }
285 return true;
286}
287
288/**
289 * @brief Initializes ial preparation to json.
290 * @param document The document value used by the operation.
291 */
293{
294 QJsonObject prep;
295 QString type = QStringLiteral("gaussian");
296 if (document.initialPreparationMode == 1) type = QStringLiteral("boundEigenstate");
297 else if (document.initialPreparationMode == 2) type = QStringLiteral("boundSuperposition");
298 else if (document.initialPreparationMode == 3) type = QStringLiteral("talbotComb");
299 else if (document.initialPreparationMode == 4) type = QStringLiteral("vortex");
300 else if (document.initialPreparationMode == 5) type = QStringLiteral("andersonDualLane");
301 else if (document.initialPreparationMode == 6) type = QStringLiteral("kickedRotor");
302 else if (document.initialPreparationMode == 7) type = QStringLiteral("quantumZeno");
303 else if (document.initialPreparationMode == 8) type = QStringLiteral("berryFirstExcited");
304 else if (document.initialPreparationMode == 9) type = QStringLiteral("moshinskyShutter");
305 else if (document.initialPreparationMode == 10) type = QStringLiteral("kapitzaDiracBeam");
306 else if (document.initialPreparationMode == 11) type = QStringLiteral("aharonovBohmBeam");
307 else if (document.initialPreparationMode == 12) type = QStringLiteral("landauMagneticState");
308 else if (document.initialPreparationMode == 13) type = QStringLiteral("quantumHallEdgeState");
309 else if (document.initialPreparationMode == 14) type = QStringLiteral("quantumBackflowState");
310 else if (document.initialPreparationMode == 15) type = QStringLiteral("diracZitterbewegungState");
311 else if (document.initialPreparationMode == 16) type = QStringLiteral("diracKleinTunnelingState");
312 prep.insert(QStringLiteral("type"), type);
313 prep.insert(QStringLiteral("stateA"), document.boundStateA);
314 prep.insert(QStringLiteral("stateB"), document.boundStateB);
315 prep.insert(QStringLiteral("relativePhaseDegrees"), document.boundRelativePhaseDegrees);
316 return prep;
317}
318
319
320/**
321 * @brief Measures ment collapse to json.
322 * @param document The document value used by the operation.
323 */
325{
326 QJsonObject measurement;
327 measurement.insert(QStringLiteral("resolution"), document.collapseResolution);
328 return measurement;
329}
330
331/**
332 * @brief Measures ment collapse from json.
333 * @param json The json value used by the operation.
334 * @param document The document value used by the operation.
335 * @param errorMessage The error message value used by the operation.
336 */
337bool measurementCollapseFromJson(const QJsonObject &json,
338 ExperimentDocument2D &document,
339 QString &errorMessage)
340{
341 const QJsonValue value = json.value(QStringLiteral("measurementCollapse"));
342 if (!value.isObject()) {
343 errorMessage = QStringLiteral("Experiment schema 5/6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23/24 is missing a valid measurementCollapse object.");
344 return false;
345 }
346 const QJsonValue resolution = value.toObject().value(QStringLiteral("resolution"));
347 if (!resolution.isDouble()) {
348 errorMessage = QStringLiteral("Experiment measurementCollapse contains an invalid resolution.");
349 return false;
350 }
351 document.collapseResolution = resolution.toDouble();
352 if (!(document.collapseResolution > 0.0) ||
353 !std::isfinite(document.collapseResolution) ||
354 document.collapseResolution > 20.0) {
355 errorMessage = QStringLiteral("Experiment measurement-collapse resolution is out of range.");
356 return false;
357 }
358 return true;
359}
360
361
362/**
363 * @brief Performs quantum quench to json.
364 * @param document The document value used by the operation.
365 */
366QJsonObject quantumQuenchToJson(const ExperimentDocument2D &document)
367{
368 QJsonObject q;
369 q.insert(QStringLiteral("enabled"), document.quench.enabled);
370 q.insert(QStringLiteral("targetObjectId"), QString::number(static_cast<qulonglong>(document.quench.targetObjectId)));
371 q.insert(QStringLiteral("parameter"), static_cast<int>(document.quench.parameter));
372 q.insert(QStringLiteral("time"), document.quench.quenchTime);
373 q.insert(QStringLiteral("before"), document.quench.beforeValue);
374 q.insert(QStringLiteral("after"), document.quench.afterValue);
375 return q;
376}
377
378/**
379 * @brief Performs quantum quench from json.
380 * @param json The json value used by the operation.
381 * @param document The document value used by the operation.
382 * @param errorMessage The error message value used by the operation.
383 */
384bool quantumQuenchFromJson(const QJsonObject &json,
385 ExperimentDocument2D &document,
386 QString &errorMessage)
387{
388 const QJsonValue value = json.value(QStringLiteral("quantumQuench"));
389 if (!value.isObject()) {
390 errorMessage = QStringLiteral("Experiment schema 6/7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23 is missing a valid quantumQuench object.");
391 return false;
392 }
393 const QJsonObject q = value.toObject();
394 if (!q.value(QStringLiteral("enabled")).isBool() ||
395 !q.value(QStringLiteral("parameter")).isDouble() ||
396 !q.value(QStringLiteral("time")).isDouble() ||
397 !q.value(QStringLiteral("before")).isDouble() ||
398 !q.value(QStringLiteral("after")).isDouble()) {
399 errorMessage = QStringLiteral("Experiment quantumQuench contains invalid fields.");
400 return false;
401 }
402 document.quench.enabled = q.value(QStringLiteral("enabled")).toBool();
403 bool idOk = false;
404 const qulonglong id = q.value(QStringLiteral("targetObjectId")).toString().toULongLong(&idOk);
405 document.quench.targetObjectId = idOk ? static_cast<std::uint64_t>(id) : 0;
406 const int param = q.value(QStringLiteral("parameter")).toInt(-1);
407 if (param < 0 || param > 7) {
408 errorMessage = QStringLiteral("Experiment quantumQuench has an unsupported parameter.");
409 return false;
410 }
411 document.quench.parameter = static_cast<TimePotentialParameter2D>(param);
412 document.quench.quenchTime = q.value(QStringLiteral("time")).toDouble();
413 document.quench.beforeValue = q.value(QStringLiteral("before")).toDouble();
414 document.quench.afterValue = q.value(QStringLiteral("after")).toDouble();
415 if (document.quench.enabled && !TimeDependentPotential2D::validate(document.potentialScene, document.quench)) {
416 errorMessage = QStringLiteral("Experiment quantumQuench does not match its potential scene.");
417 return false;
418 }
419 return true;
420}
421
422
423/**
424 * @brief Performs periodic drive to json.
425 * @param document The document value used by the operation.
426 */
427QJsonObject periodicDriveToJson(const ExperimentDocument2D &document)
428{
429 QJsonObject d;
430 d.insert(QStringLiteral("enabled"), document.periodicDrive.enabled);
431 d.insert(QStringLiteral("targetObjectId"), QString::number(static_cast<qulonglong>(document.periodicDrive.targetObjectId)));
432 d.insert(QStringLiteral("parameter"), static_cast<int>(document.periodicDrive.parameter));
433 d.insert(QStringLiteral("mean"), document.periodicDrive.meanValue);
434 d.insert(QStringLiteral("amplitude"), document.periodicDrive.amplitude);
435 d.insert(QStringLiteral("angularFrequency"), document.periodicDrive.angularFrequency);
436 d.insert(QStringLiteral("phaseDegrees"), document.periodicDrive.phaseDegrees);
437 return d;
438}
439
440/**
441 * @brief Performs periodic drive from json.
442 * @param json The json value used by the operation.
443 * @param document The document value used by the operation.
444 * @param errorMessage The error message value used by the operation.
445 */
446bool periodicDriveFromJson(const QJsonObject &json,
447 ExperimentDocument2D &document,
448 QString &errorMessage)
449{
450 const QJsonValue value = json.value(QStringLiteral("periodicDrive"));
451 if (!value.isObject()) {
452 errorMessage = QStringLiteral("Experiment schema 7/8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23 is missing a valid periodicDrive object.");
453 return false;
454 }
455 const QJsonObject d = value.toObject();
456 if (!d.value(QStringLiteral("enabled")).isBool() ||
457 !d.value(QStringLiteral("parameter")).isDouble() ||
458 !d.value(QStringLiteral("mean")).isDouble() ||
459 !d.value(QStringLiteral("amplitude")).isDouble() ||
460 !d.value(QStringLiteral("angularFrequency")).isDouble() ||
461 !d.value(QStringLiteral("phaseDegrees")).isDouble()) {
462 errorMessage = QStringLiteral("Experiment periodicDrive contains invalid fields.");
463 return false;
464 }
465 document.periodicDrive.enabled = d.value(QStringLiteral("enabled")).toBool();
466 bool idOk = false;
467 const qulonglong id = d.value(QStringLiteral("targetObjectId")).toString().toULongLong(&idOk);
468 document.periodicDrive.targetObjectId = idOk ? static_cast<std::uint64_t>(id) : 0;
469 const int param = d.value(QStringLiteral("parameter")).toInt(-1);
470 if (param < 0 || param > 7) {
471 errorMessage = QStringLiteral("Experiment periodicDrive has an unsupported parameter.");
472 return false;
473 }
474 document.periodicDrive.parameter = static_cast<TimePotentialParameter2D>(param);
475 document.periodicDrive.meanValue = d.value(QStringLiteral("mean")).toDouble();
476 document.periodicDrive.amplitude = d.value(QStringLiteral("amplitude")).toDouble();
477 document.periodicDrive.angularFrequency = d.value(QStringLiteral("angularFrequency")).toDouble();
478 document.periodicDrive.phaseDegrees = d.value(QStringLiteral("phaseDegrees")).toDouble();
479 if (document.periodicDrive.enabled &&
481 errorMessage = QStringLiteral("Experiment periodicDrive does not match its potential scene.");
482 return false;
483 }
484 return true;
485}
486
487/**
488 * @brief Performs linear sweep to json.
489 * @param document The document value used by the operation.
490 */
491QJsonObject linearSweepToJson(const ExperimentDocument2D &document)
492{
493 QJsonObject d;
494 d.insert(QStringLiteral("enabled"), document.linearSweep.enabled);
495 d.insert(QStringLiteral("targetObjectId"), QString::number(static_cast<qulonglong>(document.linearSweep.targetObjectId)));
496 d.insert(QStringLiteral("parameter"), static_cast<int>(document.linearSweep.parameter));
497 d.insert(QStringLiteral("startValue"), document.linearSweep.startValue);
498 d.insert(QStringLiteral("endValue"), document.linearSweep.endValue);
499 d.insert(QStringLiteral("startTime"), document.linearSweep.startTime);
500 d.insert(QStringLiteral("duration"), document.linearSweep.duration);
501 d.insert(QStringLiteral("returnEnabled"), document.linearSweep.returnEnabled);
502 d.insert(QStringLiteral("holdDuration"), document.linearSweep.holdDuration);
503 d.insert(QStringLiteral("returnDuration"), document.linearSweep.returnDuration);
504 return d;
505}
506
507/**
508 * @brief Performs linear sweep from json.
509 * @param json The json value used by the operation.
510 * @param document The document value used by the operation.
511 * @param errorMessage The error message value used by the operation.
512 */
513bool linearSweepFromJson(const QJsonObject &json,
514 ExperimentDocument2D &document,
515 QString &errorMessage)
516{
517 const QJsonValue value = json.value(QStringLiteral("linearSweep"));
518 if (!value.isObject()) {
519 errorMessage = QStringLiteral("Experiment schema 8/9/10/11/12/13/14/15/16/17/18/19/20/21/22/23 is missing a valid linearSweep object.");
520 return false;
521 }
522 const QJsonObject d = value.toObject();
523 if (!d.value(QStringLiteral("enabled")).isBool() ||
524 !d.value(QStringLiteral("parameter")).isDouble() ||
525 !d.value(QStringLiteral("startValue")).isDouble() ||
526 !d.value(QStringLiteral("endValue")).isDouble() ||
527 !d.value(QStringLiteral("startTime")).isDouble() ||
528 !d.value(QStringLiteral("duration")).isDouble()) {
529 errorMessage = QStringLiteral("Experiment linearSweep contains invalid fields.");
530 return false;
531 }
532 document.linearSweep.enabled = d.value(QStringLiteral("enabled")).toBool();
533 bool idOk = false;
534 const qulonglong id = d.value(QStringLiteral("targetObjectId")).toString().toULongLong(&idOk);
535 document.linearSweep.targetObjectId = idOk ? static_cast<std::uint64_t>(id) : 0;
536 const int param = d.value(QStringLiteral("parameter")).toInt(-1);
537 if (param < 0 || param > 7) {
538 errorMessage = QStringLiteral("Experiment linearSweep has an unsupported parameter.");
539 return false;
540 }
541 document.linearSweep.parameter = static_cast<TimePotentialParameter2D>(param);
542 document.linearSweep.startValue = d.value(QStringLiteral("startValue")).toDouble();
543 document.linearSweep.endValue = d.value(QStringLiteral("endValue")).toDouble();
544 document.linearSweep.startTime = d.value(QStringLiteral("startTime")).toDouble();
545 document.linearSweep.duration = d.value(QStringLiteral("duration")).toDouble();
546 // Schema 8 had only a one-way sweep. Schema 9 adds optional return-leg
547 // fields; when they are absent we preserve the old one-way semantics.
548 const QJsonValue returnEnabledValue = d.value(QStringLiteral("returnEnabled"));
549 const QJsonValue holdDurationValue = d.value(QStringLiteral("holdDuration"));
550 const QJsonValue returnDurationValue = d.value(QStringLiteral("returnDuration"));
551 if (!returnEnabledValue.isUndefined()) {
552 if (!returnEnabledValue.isBool()) {
553 errorMessage = QStringLiteral("Experiment linearSweep returnEnabled is invalid.");
554 return false;
555 }
556 document.linearSweep.returnEnabled = returnEnabledValue.toBool();
557 }
558 if (!holdDurationValue.isUndefined()) {
559 if (!holdDurationValue.isDouble()) {
560 errorMessage = QStringLiteral("Experiment linearSweep holdDuration is invalid.");
561 return false;
562 }
563 document.linearSweep.holdDuration = holdDurationValue.toDouble();
564 }
565 if (!returnDurationValue.isUndefined()) {
566 if (!returnDurationValue.isDouble()) {
567 errorMessage = QStringLiteral("Experiment linearSweep returnDuration is invalid.");
568 return false;
569 }
570 document.linearSweep.returnDuration = returnDurationValue.toDouble();
571 }
572 if (document.linearSweep.enabled &&
574 errorMessage = QStringLiteral("Experiment linearSweep does not match its potential scene.");
575 return false;
576 }
577 return true;
578}
579
580/**
581 * @brief Performs ramsey sequence to json.
582 * @param document The document value used by the operation.
583 */
584QJsonObject ramseySequenceToJson(const ExperimentDocument2D &document)
585{
586 QJsonObject d;
587 d.insert(QStringLiteral("enabled"), document.ramseySequence.enabled);
588 d.insert(QStringLiteral("targetObjectId"), QString::number(static_cast<qulonglong>(document.ramseySequence.targetObjectId)));
589 d.insert(QStringLiteral("parameter"), static_cast<int>(document.ramseySequence.parameter));
590 d.insert(QStringLiteral("mean"), document.ramseySequence.meanValue);
591 d.insert(QStringLiteral("amplitude"), document.ramseySequence.amplitude);
592 d.insert(QStringLiteral("angularFrequency"), document.ramseySequence.angularFrequency);
593 d.insert(QStringLiteral("firstPhaseDegrees"), document.ramseySequence.firstPulsePhaseDegrees);
594 d.insert(QStringLiteral("secondPhaseDegrees"), document.ramseySequence.secondPulsePhaseDegrees);
595 d.insert(QStringLiteral("startTime"), document.ramseySequence.startTime);
596 d.insert(QStringLiteral("pulseDuration"), document.ramseySequence.pulseDuration);
597 d.insert(QStringLiteral("freeEvolutionDuration"), document.ramseySequence.freeEvolutionDuration);
598 d.insert(QStringLiteral("echoEnabled"), document.ramseySequence.echoEnabled);
599 d.insert(QStringLiteral("echoPulseDuration"), document.ramseySequence.echoPulseDuration);
600 d.insert(QStringLiteral("echoPulsePhaseDegrees"), document.ramseySequence.echoPulsePhaseDegrees);
601 return d;
602}
603
604/**
605 * @brief Performs ramsey sequence from json.
606 * @param json The json value used by the operation.
607 * @param document The document value used by the operation.
608 * @param errorMessage The error message value used by the operation.
609 */
610bool ramseySequenceFromJson(const QJsonObject &json,
611 ExperimentDocument2D &document,
612 QString &errorMessage)
613{
614 const QJsonValue value = json.value(QStringLiteral("ramseySequence"));
615 if (!value.isObject()) {
616 errorMessage = QStringLiteral("Experiment schema 10/11/12/13/14/15/16/17/18/19/20/21/22/23 is missing a valid ramseySequence object.");
617 return false;
618 }
619 const QJsonObject d = value.toObject();
620 const char *numericFields[] = {
621 "parameter", "mean", "amplitude", "angularFrequency",
622 "firstPhaseDegrees", "secondPhaseDegrees", "startTime",
623 "pulseDuration", "freeEvolutionDuration"
624 };
625 if (!d.value(QStringLiteral("enabled")).isBool()) {
626 errorMessage = QStringLiteral("Experiment ramseySequence contains an invalid enabled field.");
627 return false;
628 }
629 for (const char *field : numericFields) {
630 if (!d.value(QString::fromLatin1(field)).isDouble()) {
631 errorMessage = QStringLiteral("Experiment ramseySequence contains invalid numeric fields.");
632 return false;
633 }
634 }
635 document.ramseySequence.enabled = d.value(QStringLiteral("enabled")).toBool();
636 bool idOk = false;
637 const qulonglong id = d.value(QStringLiteral("targetObjectId")).toString().toULongLong(&idOk);
638 document.ramseySequence.targetObjectId = idOk ? static_cast<std::uint64_t>(id) : 0;
639 const int param = d.value(QStringLiteral("parameter")).toInt(-1);
640 if (param < 0 || param > 7) {
641 errorMessage = QStringLiteral("Experiment ramseySequence has an unsupported parameter.");
642 return false;
643 }
644 document.ramseySequence.parameter = static_cast<TimePotentialParameter2D>(param);
645 document.ramseySequence.meanValue = d.value(QStringLiteral("mean")).toDouble();
646 document.ramseySequence.amplitude = d.value(QStringLiteral("amplitude")).toDouble();
647 document.ramseySequence.angularFrequency = d.value(QStringLiteral("angularFrequency")).toDouble();
648 document.ramseySequence.firstPulsePhaseDegrees = d.value(QStringLiteral("firstPhaseDegrees")).toDouble();
649 document.ramseySequence.secondPulsePhaseDegrees = d.value(QStringLiteral("secondPhaseDegrees")).toDouble();
650 document.ramseySequence.startTime = d.value(QStringLiteral("startTime")).toDouble();
651 document.ramseySequence.pulseDuration = d.value(QStringLiteral("pulseDuration")).toDouble();
652 document.ramseySequence.freeEvolutionDuration = d.value(QStringLiteral("freeEvolutionDuration")).toDouble();
653 // Schema 10 had no echo fields. Missing values therefore mean ordinary Ramsey.
654 document.ramseySequence.echoEnabled = d.value(QStringLiteral("echoEnabled")).toBool(false);
655 if (d.value(QStringLiteral("echoPulseDuration")).isDouble())
656 document.ramseySequence.echoPulseDuration = d.value(QStringLiteral("echoPulseDuration")).toDouble();
657 if (d.value(QStringLiteral("echoPulsePhaseDegrees")).isDouble())
658 document.ramseySequence.echoPulsePhaseDegrees = d.value(QStringLiteral("echoPulsePhaseDegrees")).toDouble();
659 if (document.ramseySequence.enabled &&
661 errorMessage = QStringLiteral("Experiment ramseySequence does not match its potential scene.");
662 return false;
663 }
664 return true;
665}
666
667/**
668 * @brief Performs ramsey ensemble to json.
669 * @param document The document value used by the operation.
670 */
671QJsonObject ramseyEnsembleToJson(const ExperimentDocument2D &document)
672{
673 QJsonObject d;
674 d.insert(QStringLiteral("enabled"), document.ramseyEnsemble.enabled);
675 d.insert(QStringLiteral("detuningStdDev"), document.ramseyEnsemble.detuningStdDev);
676 d.insert(QStringLiteral("memberCount"), document.ramseyEnsemble.memberCount);
677 return d;
678}
679
680/**
681 * @brief Performs ramsey ensemble from json.
682 * @param json The json value used by the operation.
683 * @param document The document value used by the operation.
684 * @param errorMessage The error message value used by the operation.
685 */
686bool ramseyEnsembleFromJson(const QJsonObject &json,
687 ExperimentDocument2D &document,
688 QString &errorMessage)
689{
690 const QJsonValue value = json.value(QStringLiteral("ramseyEnsemble"));
691 if (!value.isObject()) {
692 errorMessage = QStringLiteral("Experiment schema 12/13/14/15/16/17/18/19/20/21/22/23 is missing a valid ramseyEnsemble object.");
693 return false;
694 }
695 const QJsonObject d = value.toObject();
696 if (!d.value(QStringLiteral("enabled")).isBool() ||
697 !d.value(QStringLiteral("detuningStdDev")).isDouble() ||
698 !d.value(QStringLiteral("memberCount")).isDouble()) {
699 errorMessage = QStringLiteral("Experiment ramseyEnsemble contains invalid fields.");
700 return false;
701 }
702 document.ramseyEnsemble.enabled = d.value(QStringLiteral("enabled")).toBool();
703 document.ramseyEnsemble.detuningStdDev = d.value(QStringLiteral("detuningStdDev")).toDouble();
704 document.ramseyEnsemble.memberCount = d.value(QStringLiteral("memberCount")).toInt(-1);
706 errorMessage = QStringLiteral("Experiment ramseyEnsemble values are out of range.");
707 return false;
708 }
709 return true;
710}
711
712/**
713 * @brief Performs talbot initial state to json.
714 * @param document The document value used by the operation.
715 */
717{
718 QJsonObject d;
719 d.insert(QStringLiteral("period"), document.talbotInitialState.period);
720 d.insert(QStringLiteral("toothSigma"), document.talbotInitialState.toothSigma);
721 d.insert(QStringLiteral("offsetX"), document.talbotInitialState.offsetX);
722 d.insert(QStringLiteral("centerY"), document.talbotInitialState.centerY);
723 d.insert(QStringLiteral("sigmaY"), document.talbotInitialState.sigmaY);
724 d.insert(QStringLiteral("momentumY"), document.talbotInitialState.momentumY);
725 return d;
726}
727
728/**
729 * @brief Performs talbot initial state from json.
730 * @param json The json value used by the operation.
731 * @param document The document value used by the operation.
732 * @param errorMessage The error message value used by the operation.
733 */
734bool talbotInitialStateFromJson(const QJsonObject &json,
735 ExperimentDocument2D &document,
736 QString &errorMessage)
737{
738 const QJsonValue value = json.value(QStringLiteral("talbotInitialState"));
739 if (!value.isObject()) {
740 errorMessage = QStringLiteral("Experiment schema 13/14 is missing a valid talbotInitialState object.");
741 return false;
742 }
743 const QJsonObject d = value.toObject();
744 const char *const names[] = {"period", "toothSigma", "offsetX", "centerY", "sigmaY", "momentumY"};
745 for (const char *name : names) {
746 if (!d.value(QString::fromLatin1(name)).isDouble()) {
747 errorMessage = QStringLiteral("Experiment talbotInitialState contains invalid fields.");
748 return false;
749 }
750 }
751 document.talbotInitialState.period = d.value(QStringLiteral("period")).toDouble();
752 document.talbotInitialState.toothSigma = d.value(QStringLiteral("toothSigma")).toDouble();
753 document.talbotInitialState.offsetX = d.value(QStringLiteral("offsetX")).toDouble();
754 document.talbotInitialState.centerY = d.value(QStringLiteral("centerY")).toDouble();
755 document.talbotInitialState.sigmaY = d.value(QStringLiteral("sigmaY")).toDouble();
756 document.talbotInitialState.momentumY = d.value(QStringLiteral("momentumY")).toDouble();
757 if (!QuantumTalbot2D::validateConfig(document.talbotInitialState, nullptr)) {
758 errorMessage = QStringLiteral("Experiment talbotInitialState values are out of range.");
759 return false;
760 }
761 return true;
762}
763
764/**
765 * @brief Performs vortex initial state to json.
766 * @param document The document value used by the operation.
767 */
769{
770 QJsonObject d;
771 d.insert(QStringLiteral("envelopeCenterX"), document.vortexInitialState.envelopeCenterX);
772 d.insert(QStringLiteral("envelopeCenterY"), document.vortexInitialState.envelopeCenterY);
773 d.insert(QStringLiteral("envelopeSigma"), document.vortexInitialState.envelopeSigma);
774 d.insert(QStringLiteral("coreX"), document.vortexInitialState.coreX);
775 d.insert(QStringLiteral("coreY"), document.vortexInitialState.coreY);
776 d.insert(QStringLiteral("charge"), document.vortexInitialState.charge);
777 return d;
778}
779
780/**
781 * @brief Performs vortex initial state from json.
782 * @param json The json value used by the operation.
783 * @param document The document value used by the operation.
784 * @param errorMessage The error message value used by the operation.
785 */
786bool vortexInitialStateFromJson(const QJsonObject &json,
787 ExperimentDocument2D &document,
788 QString &errorMessage)
789{
790 const QJsonValue value = json.value(QStringLiteral("vortexInitialState"));
791 if (!value.isObject()) {
792 errorMessage = QStringLiteral("Experiment schema 14/15/16/17/18/19/20/21/22/23 is missing a valid vortexInitialState object.");
793 return false;
794 }
795 const QJsonObject d = value.toObject();
796 const char *const names[] = {"envelopeCenterX", "envelopeCenterY", "envelopeSigma", "coreX", "coreY", "charge"};
797 for (const char *name : names) {
798 if (!d.value(QString::fromLatin1(name)).isDouble()) {
799 errorMessage = QStringLiteral("Experiment vortexInitialState contains invalid fields.");
800 return false;
801 }
802 }
803 document.vortexInitialState.envelopeCenterX = d.value(QStringLiteral("envelopeCenterX")).toDouble();
804 document.vortexInitialState.envelopeCenterY = d.value(QStringLiteral("envelopeCenterY")).toDouble();
805 document.vortexInitialState.envelopeSigma = d.value(QStringLiteral("envelopeSigma")).toDouble();
806 document.vortexInitialState.coreX = d.value(QStringLiteral("coreX")).toDouble();
807 document.vortexInitialState.coreY = d.value(QStringLiteral("coreY")).toDouble();
808 document.vortexInitialState.charge = d.value(QStringLiteral("charge")).toInt(0);
809 if (!QuantumVortex2D::validateConfig(document.vortexInitialState, nullptr)) {
810 errorMessage = QStringLiteral("Experiment vortexInitialState values are out of range.");
811 return false;
812 }
813 return true;
814}
815
816
817/**
818 * @brief Performs anderson initial state to json.
819 * @param document The document value used by the operation.
820 */
822{
823 QJsonObject d;
824 d.insert(QStringLiteral("centerX"), document.andersonInitialState.centerX);
825 d.insert(QStringLiteral("cleanLaneY"), document.andersonInitialState.cleanLaneY);
826 d.insert(QStringLiteral("disorderLaneY"), document.andersonInitialState.disorderLaneY);
827 d.insert(QStringLiteral("sigma"), document.andersonInitialState.sigma);
828 d.insert(QStringLiteral("relativePhaseDegrees"), document.andersonInitialState.relativePhaseDegrees);
829 return d;
830}
831
832/**
833 * @brief Performs anderson initial state from json.
834 * @param json The json value used by the operation.
835 * @param document The document value used by the operation.
836 * @param errorMessage The error message value used by the operation.
837 */
838bool andersonInitialStateFromJson(const QJsonObject &json,
839 ExperimentDocument2D &document,
840 QString &errorMessage)
841{
842 const QJsonValue value = json.value(QStringLiteral("andersonInitialState"));
843 if (!value.isObject()) {
844 errorMessage = QStringLiteral("Experiment schema 15 is missing a valid andersonInitialState object.");
845 return false;
846 }
847 const QJsonObject d = value.toObject();
848 const char *const names[] = {"centerX", "cleanLaneY", "disorderLaneY", "sigma", "relativePhaseDegrees"};
849 for (const char *name : names) {
850 if (!d.value(QString::fromLatin1(name)).isDouble()) {
851 errorMessage = QStringLiteral("Experiment andersonInitialState contains invalid fields.");
852 return false;
853 }
854 }
855 document.andersonInitialState.centerX = d.value(QStringLiteral("centerX")).toDouble();
856 document.andersonInitialState.cleanLaneY = d.value(QStringLiteral("cleanLaneY")).toDouble();
857 document.andersonInitialState.disorderLaneY = d.value(QStringLiteral("disorderLaneY")).toDouble();
858 document.andersonInitialState.sigma = d.value(QStringLiteral("sigma")).toDouble();
859 document.andersonInitialState.relativePhaseDegrees = d.value(QStringLiteral("relativePhaseDegrees")).toDouble();
861 errorMessage = QStringLiteral("Experiment andersonInitialState values are out of range.");
862 return false;
863 }
864 return true;
865}
866
867
868/**
869 * @brief Performs kicked rotor to json.
870 * @param document The document value used by the operation.
871 */
872QJsonObject kickedRotorToJson(const ExperimentDocument2D &document)
873{
874 QJsonObject d;
875 d.insert(QStringLiteral("enabled"), document.kickedRotor.enabled);
876 d.insert(QStringLiteral("firstKickTime"), document.kickedRotor.firstKickTime);
877 d.insert(QStringLiteral("kickPeriod"), document.kickedRotor.kickPeriod);
878 d.insert(QStringLiteral("phaseStrength"), document.kickedRotor.phaseStrength);
879 return d;
880}
881
882/**
883 * @brief Performs kicked rotor from json.
884 * @param json The json value used by the operation.
885 * @param document The document value used by the operation.
886 * @param errorMessage The error message value used by the operation.
887 */
888bool kickedRotorFromJson(const QJsonObject &json,
889 ExperimentDocument2D &document,
890 QString &errorMessage)
891{
892 const QJsonValue value = json.value(QStringLiteral("kickedRotor"));
893 if (!value.isObject()) {
894 errorMessage = QStringLiteral("Experiment schema 16/17/18/19/20/21/22/23 is missing a valid kickedRotor object.");
895 return false;
896 }
897 const QJsonObject d = value.toObject();
898 if (!d.value(QStringLiteral("enabled")).isBool() ||
899 !d.value(QStringLiteral("firstKickTime")).isDouble() ||
900 !d.value(QStringLiteral("kickPeriod")).isDouble() ||
901 !d.value(QStringLiteral("phaseStrength")).isDouble()) {
902 errorMessage = QStringLiteral("Experiment kickedRotor contains invalid fields.");
903 return false;
904 }
905 document.kickedRotor.enabled = d.value(QStringLiteral("enabled")).toBool();
906 document.kickedRotor.firstKickTime = d.value(QStringLiteral("firstKickTime")).toDouble();
907 document.kickedRotor.kickPeriod = d.value(QStringLiteral("kickPeriod")).toDouble();
908 document.kickedRotor.phaseStrength = d.value(QStringLiteral("phaseStrength")).toDouble();
909 if (!QuantumKickedRotor2D::validateConfig(document.kickedRotor, nullptr)) {
910 errorMessage = QStringLiteral("Experiment kickedRotor values are out of range.");
911 return false;
912 }
913 return true;
914}
915
916/**
917 * @brief Performs kicked rotor initial state to json.
918 * @param document The document value used by the operation.
919 */
921{
922 QJsonObject d;
923 d.insert(QStringLiteral("yCenter"), document.kickedRotorInitialState.yCenter);
924 d.insert(QStringLiteral("ySigma"), document.kickedRotorInitialState.ySigma);
925 d.insert(QStringLiteral("initialMomentumMode"), document.kickedRotorInitialState.initialMomentumMode);
926 return d;
927}
928
929/**
930 * @brief Performs kicked rotor initial state from json.
931 * @param json The json value used by the operation.
932 * @param document The document value used by the operation.
933 * @param errorMessage The error message value used by the operation.
934 */
935bool kickedRotorInitialStateFromJson(const QJsonObject &json,
936 ExperimentDocument2D &document,
937 QString &errorMessage)
938{
939 const QJsonValue value = json.value(QStringLiteral("kickedRotorInitialState"));
940 if (!value.isObject()) {
941 errorMessage = QStringLiteral("Experiment schema 16/17/18/19/20/21/22/23 is missing a valid kickedRotorInitialState object.");
942 return false;
943 }
944 const QJsonObject d = value.toObject();
945 if (!d.value(QStringLiteral("yCenter")).isDouble() ||
946 !d.value(QStringLiteral("ySigma")).isDouble() ||
947 !d.value(QStringLiteral("initialMomentumMode")).isDouble()) {
948 errorMessage = QStringLiteral("Experiment kickedRotorInitialState contains invalid fields.");
949 return false;
950 }
951 document.kickedRotorInitialState.yCenter = d.value(QStringLiteral("yCenter")).toDouble();
952 document.kickedRotorInitialState.ySigma = d.value(QStringLiteral("ySigma")).toDouble();
954 d.value(QStringLiteral("initialMomentumMode")).toInt(0);
956 errorMessage = QStringLiteral("Experiment kickedRotorInitialState values are out of range.");
957 return false;
958 }
959 return true;
960}
961
962
963/**
964 * @brief Performs quantum zeno to json.
965 * @param document The document value used by the operation.
966 */
967QJsonObject quantumZenoToJson(const ExperimentDocument2D &document)
968{
969 QJsonObject d;
970 d.insert(QStringLiteral("enabled"), document.quantumZeno.enabled);
971 d.insert(QStringLiteral("firstMeasurementTime"), document.quantumZeno.firstMeasurementTime);
972 d.insert(QStringLiteral("measurementPeriod"), document.quantumZeno.measurementPeriod);
973 d.insert(QStringLiteral("laneSplitY"), document.quantumZeno.laneSplitY);
974 d.insert(QStringLiteral("survivalBoundaryX"), document.quantumZeno.survivalBoundaryX);
975 d.insert(QStringLiteral("edgeWidth"), document.quantumZeno.edgeWidth);
976 return d;
977}
978
979/**
980 * @brief Performs quantum zeno from json.
981 * @param json The json value used by the operation.
982 * @param document The document value used by the operation.
983 * @param errorMessage The error message value used by the operation.
984 */
985bool quantumZenoFromJson(const QJsonObject &json,
986 ExperimentDocument2D &document,
987 QString &errorMessage)
988{
989 const QJsonValue value = json.value(QStringLiteral("quantumZeno"));
990 if (!value.isObject()) {
991 errorMessage = QStringLiteral("Experiment schema 17/18 is missing a valid quantumZeno object.");
992 return false;
993 }
994 const QJsonObject d = value.toObject();
995 if (!d.value(QStringLiteral("enabled")).isBool() ||
996 !d.value(QStringLiteral("firstMeasurementTime")).isDouble() ||
997 !d.value(QStringLiteral("measurementPeriod")).isDouble() ||
998 !d.value(QStringLiteral("laneSplitY")).isDouble() ||
999 !d.value(QStringLiteral("survivalBoundaryX")).isDouble() ||
1000 !d.value(QStringLiteral("edgeWidth")).isDouble()) {
1001 errorMessage = QStringLiteral("Experiment quantumZeno contains invalid fields.");
1002 return false;
1003 }
1004 document.quantumZeno.enabled = d.value(QStringLiteral("enabled")).toBool();
1005 document.quantumZeno.firstMeasurementTime = d.value(QStringLiteral("firstMeasurementTime")).toDouble();
1006 document.quantumZeno.measurementPeriod = d.value(QStringLiteral("measurementPeriod")).toDouble();
1007 document.quantumZeno.laneSplitY = d.value(QStringLiteral("laneSplitY")).toDouble();
1008 document.quantumZeno.survivalBoundaryX = d.value(QStringLiteral("survivalBoundaryX")).toDouble();
1009 document.quantumZeno.edgeWidth = d.value(QStringLiteral("edgeWidth")).toDouble();
1010 if (!QuantumZeno2D::validateConfig(document.quantumZeno, nullptr)) {
1011 errorMessage = QStringLiteral("Experiment quantumZeno values are out of range.");
1012 return false;
1013 }
1014 return true;
1015}
1016
1017/**
1018 * @brief Performs quantum zeno initial state to json.
1019 * @param document The document value used by the operation.
1020 */
1022{
1023 QJsonObject d;
1024 d.insert(QStringLiteral("centerX"), document.quantumZenoInitialState.centerX);
1025 d.insert(QStringLiteral("controlLaneY"), document.quantumZenoInitialState.controlLaneY);
1026 d.insert(QStringLiteral("watchedLaneY"), document.quantumZenoInitialState.watchedLaneY);
1027 d.insert(QStringLiteral("sigma"), document.quantumZenoInitialState.sigma);
1028 d.insert(QStringLiteral("momentumX"), document.quantumZenoInitialState.momentumX);
1029 d.insert(QStringLiteral("relativePhaseDegrees"), document.quantumZenoInitialState.relativePhaseDegrees);
1030 return d;
1031}
1032
1033/**
1034 * @brief Performs quantum zeno initial state from json.
1035 * @param json The json value used by the operation.
1036 * @param document The document value used by the operation.
1037 * @param errorMessage The error message value used by the operation.
1038 */
1039bool quantumZenoInitialStateFromJson(const QJsonObject &json,
1040 ExperimentDocument2D &document,
1041 QString &errorMessage)
1042{
1043 const QJsonValue value = json.value(QStringLiteral("quantumZenoInitialState"));
1044 if (!value.isObject()) {
1045 errorMessage = QStringLiteral("Experiment schema 17/18 is missing a valid quantumZenoInitialState object.");
1046 return false;
1047 }
1048 const QJsonObject d = value.toObject();
1049 if (!d.value(QStringLiteral("centerX")).isDouble() ||
1050 !d.value(QStringLiteral("controlLaneY")).isDouble() ||
1051 !d.value(QStringLiteral("watchedLaneY")).isDouble() ||
1052 !d.value(QStringLiteral("sigma")).isDouble() ||
1053 !d.value(QStringLiteral("momentumX")).isDouble() ||
1054 !d.value(QStringLiteral("relativePhaseDegrees")).isDouble()) {
1055 errorMessage = QStringLiteral("Experiment quantumZenoInitialState contains invalid fields.");
1056 return false;
1057 }
1058 document.quantumZenoInitialState.centerX = d.value(QStringLiteral("centerX")).toDouble();
1059 document.quantumZenoInitialState.controlLaneY = d.value(QStringLiteral("controlLaneY")).toDouble();
1060 document.quantumZenoInitialState.watchedLaneY = d.value(QStringLiteral("watchedLaneY")).toDouble();
1061 document.quantumZenoInitialState.sigma = d.value(QStringLiteral("sigma")).toDouble();
1062 document.quantumZenoInitialState.momentumX = d.value(QStringLiteral("momentumX")).toDouble();
1063 document.quantumZenoInitialState.relativePhaseDegrees = d.value(QStringLiteral("relativePhaseDegrees")).toDouble();
1065 errorMessage = QStringLiteral("Experiment quantumZenoInitialState values are out of range.");
1066 return false;
1067 }
1068 return true;
1069}
1070
1071/**
1072 * @brief Performs quantum scar to json.
1073 * @param document The document value used by the operation.
1074 */
1075QJsonObject quantumScarToJson(const ExperimentDocument2D &document)
1076{
1077 QJsonObject d;
1078 d.insert(QStringLiteral("enabled"), document.quantumScar.enabled);
1079 d.insert(QStringLiteral("orbitBandHalfWidth"), document.quantumScar.orbitBandHalfWidth);
1080 d.insert(QStringLiteral("referenceEnergy"), document.quantumScar.referenceEnergy);
1081 return d;
1082}
1083
1084/**
1085 * @brief Performs quantum scar from json.
1086 * @param json The json value used by the operation.
1087 * @param document The document value used by the operation.
1088 * @param errorMessage The error message value used by the operation.
1089 */
1090bool quantumScarFromJson(const QJsonObject &json,
1091 ExperimentDocument2D &document,
1092 QString &errorMessage)
1093{
1094 const QJsonValue value = json.value(QStringLiteral("quantumScar"));
1095 if (!value.isObject()) {
1096 errorMessage = QStringLiteral("Experiment schema 18 is missing a valid quantumScar object.");
1097 return false;
1098 }
1099 const QJsonObject d = value.toObject();
1100 if (!d.value(QStringLiteral("enabled")).isBool() ||
1101 !d.value(QStringLiteral("orbitBandHalfWidth")).isDouble() ||
1102 !d.value(QStringLiteral("referenceEnergy")).isDouble()) {
1103 errorMessage = QStringLiteral("Experiment quantumScar contains invalid fields.");
1104 return false;
1105 }
1106 document.quantumScar.enabled = d.value(QStringLiteral("enabled")).toBool();
1107 document.quantumScar.orbitBandHalfWidth = d.value(QStringLiteral("orbitBandHalfWidth")).toDouble();
1108 document.quantumScar.referenceEnergy = d.value(QStringLiteral("referenceEnergy")).toDouble();
1109 if (!QuantumScars2D::validateConfig(document.quantumScar, nullptr)) {
1110 errorMessage = QStringLiteral("Experiment quantumScar values are out of range.");
1111 return false;
1112 }
1113 return true;
1114}
1115
1116/**
1117 * @brief Performs quantum berry to json.
1118 * @param document The document value used by the operation.
1119 */
1120QJsonObject quantumBerryToJson(const ExperimentDocument2D &document)
1121{
1122 QJsonObject d;
1123 d.insert(QStringLiteral("enabled"), document.quantumBerry.enabled);
1124 d.insert(QStringLiteral("anisotropy"), document.quantumBerry.anisotropy);
1125 d.insert(QStringLiteral("startTime"), document.quantumBerry.startTime);
1126 d.insert(QStringLiteral("duration"), document.quantumBerry.duration);
1127 d.insert(QStringLiteral("winding"), document.quantumBerry.winding);
1128 return d;
1129}
1130
1131/**
1132 * @brief Performs quantum berry from json.
1133 * @param json The json value used by the operation.
1134 * @param document The document value used by the operation.
1135 * @param errorMessage The error message value used by the operation.
1136 */
1137bool quantumBerryFromJson(const QJsonObject &json,
1138 ExperimentDocument2D &document,
1139 QString &errorMessage)
1140{
1141 const QJsonValue value = json.value(QStringLiteral("quantumBerry"));
1142 if (!value.isObject()) {
1143 errorMessage = QStringLiteral("Experiment schema 19 is missing a valid quantumBerry object.");
1144 return false;
1145 }
1146 const QJsonObject d = value.toObject();
1147 if (!d.value(QStringLiteral("enabled")).isBool() ||
1148 !d.value(QStringLiteral("anisotropy")).isDouble() ||
1149 !d.value(QStringLiteral("startTime")).isDouble() ||
1150 !d.value(QStringLiteral("duration")).isDouble() ||
1151 !d.value(QStringLiteral("winding")).isDouble()) {
1152 errorMessage = QStringLiteral("Experiment quantumBerry contains invalid fields.");
1153 return false;
1154 }
1155 document.quantumBerry.enabled = d.value(QStringLiteral("enabled")).toBool();
1156 document.quantumBerry.anisotropy = d.value(QStringLiteral("anisotropy")).toDouble();
1157 document.quantumBerry.startTime = d.value(QStringLiteral("startTime")).toDouble();
1158 document.quantumBerry.duration = d.value(QStringLiteral("duration")).toDouble();
1159 document.quantumBerry.winding = d.value(QStringLiteral("winding")).toInt(0);
1160
1161 if (document.quantumBerry.enabled) {
1162 QuantumBerryTrap2D trap;
1163 if (!QuantumBerryPhase2D::identifyTrap(document.potentialScene, trap, nullptr) ||
1164 !QuantumBerryPhase2D::validateConfig(document.quantumBerry, trap, nullptr)) {
1165 errorMessage = QStringLiteral("Experiment quantumBerry values or base harmonic trap are invalid.");
1166 return false;
1167 }
1168 }
1169 return true;
1170}
1171
1172
1173/**
1174 * @brief Performs quantum loschmidt to json.
1175 * @param document The document value used by the operation.
1176 */
1178{
1179 QJsonObject d;
1180 d.insert(QStringLiteral("enabled"), document.quantumLoschmidt.enabled);
1181 d.insert(QStringLiteral("reversalTime"), document.quantumLoschmidt.reversalTime);
1182 d.insert(QStringLiteral("momentumErrorX"), document.quantumLoschmidt.momentumErrorX);
1183 d.insert(QStringLiteral("momentumErrorY"), document.quantumLoschmidt.momentumErrorY);
1184 return d;
1185}
1186
1187/**
1188 * @brief Performs quantum loschmidt from json.
1189 * @param json The json value used by the operation.
1190 * @param document The document value used by the operation.
1191 * @param errorMessage The error message value used by the operation.
1192 */
1193bool quantumLoschmidtFromJson(const QJsonObject &json,
1194 ExperimentDocument2D &document,
1195 QString &errorMessage)
1196{
1197 const QJsonValue value = json.value(QStringLiteral("quantumLoschmidt"));
1198 if (!value.isObject()) {
1199 errorMessage = QStringLiteral("Experiment schema 20 is missing a valid quantumLoschmidt object.");
1200 return false;
1201 }
1202 const QJsonObject d = value.toObject();
1203 if (!d.value(QStringLiteral("enabled")).isBool() ||
1204 !d.value(QStringLiteral("reversalTime")).isDouble() ||
1205 !d.value(QStringLiteral("momentumErrorX")).isDouble() ||
1206 !d.value(QStringLiteral("momentumErrorY")).isDouble()) {
1207 errorMessage = QStringLiteral("Experiment quantumLoschmidt contains invalid fields.");
1208 return false;
1209 }
1210 document.quantumLoschmidt.enabled = d.value(QStringLiteral("enabled")).toBool();
1211 document.quantumLoschmidt.reversalTime = d.value(QStringLiteral("reversalTime")).toDouble();
1212 document.quantumLoschmidt.momentumErrorX = d.value(QStringLiteral("momentumErrorX")).toDouble();
1213 document.quantumLoschmidt.momentumErrorY = d.value(QStringLiteral("momentumErrorY")).toDouble();
1215 errorMessage = QStringLiteral("Experiment quantumLoschmidt values are out of range.");
1216 return false;
1217 }
1218 return true;
1219}
1220
1221
1222/**
1223 * @brief Performs moshinsky initial state to json.
1224 * @param document The document value used by the operation.
1225 */
1227{
1228 QJsonObject d;
1229 d.insert(QStringLiteral("enabled"), document.moshinskyInitialState.enabled);
1230 d.insert(QStringLiteral("shutterX"), document.moshinskyInitialState.shutterX);
1231 d.insert(QStringLiteral("envelopeCenterX"), document.moshinskyInitialState.envelopeCenterX);
1232 d.insert(QStringLiteral("envelopeSigmaX"), document.moshinskyInitialState.envelopeSigmaX);
1233 d.insert(QStringLiteral("centerY"), document.moshinskyInitialState.centerY);
1234 d.insert(QStringLiteral("transverseSigmaY"), document.moshinskyInitialState.transverseSigmaY);
1235 d.insert(QStringLiteral("momentumX"), document.moshinskyInitialState.momentumX);
1236 d.insert(QStringLiteral("edgeWidth"), document.moshinskyInitialState.edgeWidth);
1237 return d;
1238}
1239
1240/**
1241 * @brief Performs moshinsky initial state from json.
1242 * @param json The json value used by the operation.
1243 * @param document The document value used by the operation.
1244 * @param errorMessage The error message value used by the operation.
1245 */
1246bool moshinskyInitialStateFromJson(const QJsonObject &json,
1247 ExperimentDocument2D &document,
1248 QString &errorMessage)
1249{
1250 const QJsonValue value = json.value(QStringLiteral("moshinskyInitialState"));
1251 if (!value.isObject()) {
1252 errorMessage = QStringLiteral("Experiment schema 21 is missing a valid moshinskyInitialState object.");
1253 return false;
1254 }
1255 const QJsonObject d = value.toObject();
1256 const char *names[] = {
1257 "shutterX", "envelopeCenterX", "envelopeSigmaX", "centerY",
1258 "transverseSigmaY", "momentumX", "edgeWidth"
1259 };
1260 if (!d.value(QStringLiteral("enabled")).isBool()) {
1261 errorMessage = QStringLiteral("Experiment moshinskyInitialState has invalid enabled field.");
1262 return false;
1263 }
1264 for (const char *name : names) {
1265 if (!d.value(QString::fromLatin1(name)).isDouble()) {
1266 errorMessage = QStringLiteral("Experiment moshinskyInitialState contains invalid numeric fields.");
1267 return false;
1268 }
1269 }
1270 document.moshinskyInitialState.enabled = d.value(QStringLiteral("enabled")).toBool();
1271 document.moshinskyInitialState.shutterX = d.value(QStringLiteral("shutterX")).toDouble();
1272 document.moshinskyInitialState.envelopeCenterX = d.value(QStringLiteral("envelopeCenterX")).toDouble();
1273 document.moshinskyInitialState.envelopeSigmaX = d.value(QStringLiteral("envelopeSigmaX")).toDouble();
1274 document.moshinskyInitialState.centerY = d.value(QStringLiteral("centerY")).toDouble();
1275 document.moshinskyInitialState.transverseSigmaY = d.value(QStringLiteral("transverseSigmaY")).toDouble();
1276 document.moshinskyInitialState.momentumX = d.value(QStringLiteral("momentumX")).toDouble();
1277 document.moshinskyInitialState.edgeWidth = d.value(QStringLiteral("edgeWidth")).toDouble();
1279 errorMessage = QStringLiteral("Experiment moshinskyInitialState values are out of range.");
1280 return false;
1281 }
1282 return true;
1283}
1284
1285/**
1286 * @brief Performs quantum moshinsky to json.
1287 * @param document The document value used by the operation.
1288 */
1290{
1291 QJsonObject d;
1292 d.insert(QStringLiteral("enabled"), document.quantumMoshinsky.enabled);
1293 d.insert(QStringLiteral("shutterObjectId"),
1294 QString::number(static_cast<qulonglong>(document.quantumMoshinsky.shutterObjectId)));
1295 d.insert(QStringLiteral("openTime"), document.quantumMoshinsky.openTime);
1296 d.insert(QStringLiteral("detectorX"), document.quantumMoshinsky.detectorX);
1297 d.insert(QStringLiteral("analysisEndTime"), document.quantumMoshinsky.analysisEndTime);
1298 return d;
1299}
1300
1301/**
1302 * @brief Performs quantum moshinsky from json.
1303 * @param json The json value used by the operation.
1304 * @param document The document value used by the operation.
1305 * @param errorMessage The error message value used by the operation.
1306 */
1307bool quantumMoshinskyFromJson(const QJsonObject &json,
1308 ExperimentDocument2D &document,
1309 QString &errorMessage)
1310{
1311 const QJsonValue value = json.value(QStringLiteral("quantumMoshinsky"));
1312 if (!value.isObject()) {
1313 errorMessage = QStringLiteral("Experiment schema 21 is missing a valid quantumMoshinsky object.");
1314 return false;
1315 }
1316 const QJsonObject d = value.toObject();
1317 if (!d.value(QStringLiteral("enabled")).isBool() ||
1318 !d.value(QStringLiteral("openTime")).isDouble() ||
1319 !d.value(QStringLiteral("detectorX")).isDouble() ||
1320 !d.value(QStringLiteral("analysisEndTime")).isDouble()) {
1321 errorMessage = QStringLiteral("Experiment quantumMoshinsky contains invalid fields.");
1322 return false;
1323 }
1324 document.quantumMoshinsky.enabled = d.value(QStringLiteral("enabled")).toBool();
1325 bool idOk = false;
1326 const qulonglong id = d.value(QStringLiteral("shutterObjectId")).toString().toULongLong(&idOk);
1327 document.quantumMoshinsky.shutterObjectId = idOk ? static_cast<std::uint64_t>(id) : 0u;
1328 document.quantumMoshinsky.openTime = d.value(QStringLiteral("openTime")).toDouble();
1329 document.quantumMoshinsky.detectorX = d.value(QStringLiteral("detectorX")).toDouble();
1330 document.quantumMoshinsky.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1331 if (document.quantumMoshinsky.enabled &&
1332 !QuantumMoshinsky2D::validateConfig(document.potentialScene, document.quantumMoshinsky, nullptr, nullptr)) {
1333 errorMessage = QStringLiteral("Experiment quantumMoshinsky does not match its potential scene.");
1334 return false;
1335 }
1336 return true;
1337}
1338
1339
1340/**
1341 * @brief Performs kapitza dirac initial state to json.
1342 * @param document The document value used by the operation.
1343 */
1345{
1346 QJsonObject d;
1347 d.insert(QStringLiteral("centerX"), document.kapitzaDiracInitialState.centerX);
1348 d.insert(QStringLiteral("centerY"), document.kapitzaDiracInitialState.centerY);
1349 d.insert(QStringLiteral("sigmaX"), document.kapitzaDiracInitialState.sigmaX);
1350 d.insert(QStringLiteral("sigmaY"), document.kapitzaDiracInitialState.sigmaY);
1351 d.insert(QStringLiteral("momentumX"), document.kapitzaDiracInitialState.momentumX);
1352 d.insert(QStringLiteral("momentumY"), document.kapitzaDiracInitialState.momentumY);
1353 return d;
1354}
1355
1356/**
1357 * @brief Performs kapitza dirac initial state from json.
1358 * @param json The json value used by the operation.
1359 * @param document The document value used by the operation.
1360 * @param errorMessage The error message value used by the operation.
1361 */
1362bool kapitzaDiracInitialStateFromJson(const QJsonObject &json,
1363 ExperimentDocument2D &document,
1364 QString &errorMessage)
1365{
1366 const QJsonValue value = json.value(QStringLiteral("kapitzaDiracInitialState"));
1367 if (!value.isObject()) {
1368 errorMessage = QStringLiteral("Experiment schema 22 is missing a valid kapitzaDiracInitialState object.");
1369 return false;
1370 }
1371 const QJsonObject d = value.toObject();
1372 const char *names[] = {"centerX", "centerY", "sigmaX", "sigmaY", "momentumX", "momentumY"};
1373 for (const char *name : names) {
1374 if (!d.value(QString::fromLatin1(name)).isDouble()) {
1375 errorMessage = QStringLiteral("Experiment kapitzaDiracInitialState contains invalid numeric fields.");
1376 return false;
1377 }
1378 }
1379 document.kapitzaDiracInitialState.centerX = d.value(QStringLiteral("centerX")).toDouble();
1380 document.kapitzaDiracInitialState.centerY = d.value(QStringLiteral("centerY")).toDouble();
1381 document.kapitzaDiracInitialState.sigmaX = d.value(QStringLiteral("sigmaX")).toDouble();
1382 document.kapitzaDiracInitialState.sigmaY = d.value(QStringLiteral("sigmaY")).toDouble();
1383 document.kapitzaDiracInitialState.momentumX = d.value(QStringLiteral("momentumX")).toDouble();
1384 document.kapitzaDiracInitialState.momentumY = d.value(QStringLiteral("momentumY")).toDouble();
1386 errorMessage = QStringLiteral("Experiment kapitzaDiracInitialState values are out of range.");
1387 return false;
1388 }
1389 return true;
1390}
1391
1392/**
1393 * @brief Performs quantum kapitza dirac to json.
1394 * @param document The document value used by the operation.
1395 */
1397{
1398 QJsonObject d;
1399 d.insert(QStringLiteral("enabled"), document.quantumKapitzaDirac.enabled);
1400 d.insert(QStringLiteral("latticePeriod"), document.quantumKapitzaDirac.latticePeriod);
1401 d.insert(QStringLiteral("latticeDepth"), document.quantumKapitzaDirac.latticeDepth);
1402 d.insert(QStringLiteral("latticePhaseDegrees"), document.quantumKapitzaDirac.latticePhaseDegrees);
1403 d.insert(QStringLiteral("pulseStartTime"), document.quantumKapitzaDirac.pulseStartTime);
1404 d.insert(QStringLiteral("pulseDuration"), document.quantumKapitzaDirac.pulseDuration);
1405 d.insert(QStringLiteral("analysisEndTime"), document.quantumKapitzaDirac.analysisEndTime);
1406 d.insert(QStringLiteral("maximumOrder"), document.quantumKapitzaDirac.maximumOrder);
1407 return d;
1408}
1409
1410/**
1411 * @brief Performs quantum kapitza dirac from json.
1412 * @param json The json value used by the operation.
1413 * @param document The document value used by the operation.
1414 * @param errorMessage The error message value used by the operation.
1415 */
1416bool quantumKapitzaDiracFromJson(const QJsonObject &json,
1417 ExperimentDocument2D &document,
1418 QString &errorMessage)
1419{
1420 const QJsonValue value = json.value(QStringLiteral("quantumKapitzaDirac"));
1421 if (!value.isObject()) {
1422 errorMessage = QStringLiteral("Experiment schema 22 is missing a valid quantumKapitzaDirac object.");
1423 return false;
1424 }
1425 const QJsonObject d = value.toObject();
1426 if (!d.value(QStringLiteral("enabled")).isBool() ||
1427 !d.value(QStringLiteral("latticePeriod")).isDouble() ||
1428 !d.value(QStringLiteral("latticeDepth")).isDouble() ||
1429 !d.value(QStringLiteral("latticePhaseDegrees")).isDouble() ||
1430 !d.value(QStringLiteral("pulseStartTime")).isDouble() ||
1431 !d.value(QStringLiteral("pulseDuration")).isDouble() ||
1432 !d.value(QStringLiteral("analysisEndTime")).isDouble() ||
1433 !d.value(QStringLiteral("maximumOrder")).isDouble()) {
1434 errorMessage = QStringLiteral("Experiment quantumKapitzaDirac contains invalid fields.");
1435 return false;
1436 }
1437 document.quantumKapitzaDirac.enabled = d.value(QStringLiteral("enabled")).toBool();
1438 document.quantumKapitzaDirac.latticePeriod = d.value(QStringLiteral("latticePeriod")).toDouble();
1439 document.quantumKapitzaDirac.latticeDepth = d.value(QStringLiteral("latticeDepth")).toDouble();
1440 document.quantumKapitzaDirac.latticePhaseDegrees = d.value(QStringLiteral("latticePhaseDegrees")).toDouble();
1441 document.quantumKapitzaDirac.pulseStartTime = d.value(QStringLiteral("pulseStartTime")).toDouble();
1442 document.quantumKapitzaDirac.pulseDuration = d.value(QStringLiteral("pulseDuration")).toDouble();
1443 document.quantumKapitzaDirac.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1444 document.quantumKapitzaDirac.maximumOrder = d.value(QStringLiteral("maximumOrder")).toInt();
1445 if (!QuantumKapitzaDirac2D::validateConfig(document.quantumKapitzaDirac, 1.0, nullptr)) {
1446 errorMessage = QStringLiteral("Experiment quantumKapitzaDirac values are out of range.");
1447 return false;
1448 }
1449 return true;
1450}
1451
1452
1453/**
1454 * @brief Performs quantum aharonov bohm to json.
1455 * @param document The document value used by the operation.
1456 */
1458{
1459 QJsonObject d;
1460 d.insert(QStringLiteral("enabled"), document.quantumAharonovBohm.enabled);
1461 d.insert(QStringLiteral("solenoidX"), document.quantumAharonovBohm.solenoidX);
1462 d.insert(QStringLiteral("solenoidY"), document.quantumAharonovBohm.solenoidY);
1463 d.insert(QStringLiteral("solenoidRadius"), document.quantumAharonovBohm.solenoidRadius);
1464 d.insert(QStringLiteral("fluxQuanta"), document.quantumAharonovBohm.fluxQuanta);
1465 d.insert(QStringLiteral("barrierHeight"), document.quantumAharonovBohm.barrierHeight);
1466 d.insert(QStringLiteral("detectorX"), document.quantumAharonovBohm.detectorX);
1467 d.insert(QStringLiteral("analysisEndTime"), document.quantumAharonovBohm.analysisEndTime);
1468 return d;
1469}
1470
1471/**
1472 * @brief Performs quantum aharonov bohm from json.
1473 * @param json The json value used by the operation.
1474 * @param document The document value used by the operation.
1475 * @param errorMessage The error message value used by the operation.
1476 */
1477bool quantumAharonovBohmFromJson(const QJsonObject &json,
1478 ExperimentDocument2D &document,
1479 QString &errorMessage)
1480{
1481 const QJsonValue value = json.value(QStringLiteral("quantumAharonovBohm"));
1482 if (!value.isObject()) {
1483 errorMessage = QStringLiteral("Experiment schema 23 is missing a valid quantumAharonovBohm object.");
1484 return false;
1485 }
1486 const QJsonObject d = value.toObject();
1487 const char *numeric[] = {"solenoidX","solenoidY","solenoidRadius","fluxQuanta","barrierHeight","detectorX","analysisEndTime"};
1488 if (!d.value(QStringLiteral("enabled")).isBool()) {
1489 errorMessage = QStringLiteral("Experiment quantumAharonovBohm contains an invalid enabled field.");
1490 return false;
1491 }
1492 for (const char *name : numeric) {
1493 if (!d.value(QString::fromLatin1(name)).isDouble()) {
1494 errorMessage = QStringLiteral("Experiment quantumAharonovBohm contains invalid numeric fields.");
1495 return false;
1496 }
1497 }
1498 document.quantumAharonovBohm.enabled = d.value(QStringLiteral("enabled")).toBool();
1499 document.quantumAharonovBohm.solenoidX = d.value(QStringLiteral("solenoidX")).toDouble();
1500 document.quantumAharonovBohm.solenoidY = d.value(QStringLiteral("solenoidY")).toDouble();
1501 document.quantumAharonovBohm.solenoidRadius = d.value(QStringLiteral("solenoidRadius")).toDouble();
1502 document.quantumAharonovBohm.fluxQuanta = d.value(QStringLiteral("fluxQuanta")).toDouble();
1503 document.quantumAharonovBohm.barrierHeight = d.value(QStringLiteral("barrierHeight")).toDouble();
1504 document.quantumAharonovBohm.detectorX = d.value(QStringLiteral("detectorX")).toDouble();
1505 document.quantumAharonovBohm.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1507 errorMessage = QStringLiteral("Experiment quantumAharonovBohm values are out of range.");
1508 return false;
1509 }
1510 return true;
1511}
1512
1513/**
1514 * @brief Performs quantum landau to json.
1515 * @param document The document value used by the operation.
1516 */
1517QJsonObject quantumLandauToJson(const ExperimentDocument2D &document)
1518{
1519 QJsonObject d;
1520 d.insert(QStringLiteral("enabled"), document.quantumLandau.enabled);
1521 d.insert(QStringLiteral("fieldStrength"), document.quantumLandau.fieldStrength);
1522 d.insert(QStringLiteral("preparationMode"), document.quantumLandau.preparationMode);
1523 d.insert(QStringLiteral("landauIndex"), document.quantumLandau.landauIndex);
1524 d.insert(QStringLiteral("orbitRadius"), document.quantumLandau.orbitRadius);
1525 d.insert(QStringLiteral("analysisEndTime"), document.quantumLandau.analysisEndTime);
1526 return d;
1527}
1528
1529/**
1530 * @brief Performs quantum landau from json.
1531 * @param json The json value used by the operation.
1532 * @param document The document value used by the operation.
1533 * @param errorMessage The error message value used by the operation.
1534 */
1535bool quantumLandauFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
1536{
1537 const QJsonValue value = json.value(QStringLiteral("quantumLandau"));
1538 if (!value.isObject()) {
1539 errorMessage = QStringLiteral("Experiment schema 24 is missing a valid quantumLandau object.");
1540 return false;
1541 }
1542 const QJsonObject d = value.toObject();
1543 if (!d.value(QStringLiteral("enabled")).isBool() ||
1544 !d.value(QStringLiteral("fieldStrength")).isDouble() ||
1545 !d.value(QStringLiteral("preparationMode")).isDouble() ||
1546 !d.value(QStringLiteral("landauIndex")).isDouble() ||
1547 !d.value(QStringLiteral("orbitRadius")).isDouble() ||
1548 !d.value(QStringLiteral("analysisEndTime")).isDouble()) {
1549 errorMessage = QStringLiteral("Experiment quantumLandau contains invalid fields.");
1550 return false;
1551 }
1552 document.quantumLandau.enabled = d.value(QStringLiteral("enabled")).toBool();
1553 document.quantumLandau.fieldStrength = d.value(QStringLiteral("fieldStrength")).toDouble();
1554 document.quantumLandau.preparationMode = d.value(QStringLiteral("preparationMode")).toInt();
1555 document.quantumLandau.landauIndex = d.value(QStringLiteral("landauIndex")).toInt();
1556 document.quantumLandau.orbitRadius = d.value(QStringLiteral("orbitRadius")).toDouble();
1557 document.quantumLandau.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1558 if (!QuantumLandau2D::validateConfig(document.quantumLandau, nullptr)) {
1559 errorMessage = QStringLiteral("Experiment quantumLandau values are out of range.");
1560 return false;
1561 }
1562 return true;
1563}
1564
1565/**
1566 * @brief Performs quantum hall edge to json.
1567 * @param document The document value used by the operation.
1568 */
1570{
1571 QJsonObject d;
1572 d.insert(QStringLiteral("enabled"), document.quantumHallEdge.enabled);
1573 d.insert(QStringLiteral("fieldStrength"), document.quantumHallEdge.fieldStrength);
1574 d.insert(QStringLiteral("edgeY"), document.quantumHallEdge.edgeY);
1575 d.insert(QStringLiteral("wallHeight"), document.quantumHallEdge.wallHeight);
1576 d.insert(QStringLiteral("launchY"), document.quantumHallEdge.launchY);
1577 d.insert(QStringLiteral("orbitRadius"), document.quantumHallEdge.orbitRadius);
1578 d.insert(QStringLiteral("packetSigma"), document.quantumHallEdge.packetSigma);
1579 d.insert(QStringLiteral("edgeBand"), document.quantumHallEdge.edgeBand);
1580 d.insert(QStringLiteral("analysisEndTime"), document.quantumHallEdge.analysisEndTime);
1581 return d;
1582}
1583
1584/**
1585 * @brief Performs quantum hall edge from json.
1586 * @param json The json value used by the operation.
1587 * @param document The document value used by the operation.
1588 * @param errorMessage The error message value used by the operation.
1589 */
1590bool quantumHallEdgeFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
1591{
1592 const QJsonValue value = json.value(QStringLiteral("quantumHallEdge"));
1593 if (!value.isObject()) {
1594 errorMessage = QStringLiteral("Experiment schema 25 is missing a valid quantumHallEdge object.");
1595 return false;
1596 }
1597 const QJsonObject d = value.toObject();
1598 const char *fields[] = {"fieldStrength","edgeY","wallHeight","launchY","orbitRadius","packetSigma","edgeBand","analysisEndTime"};
1599 if (!d.value(QStringLiteral("enabled")).isBool()) {
1600 errorMessage = QStringLiteral("Experiment quantumHallEdge contains invalid fields."); return false;
1601 }
1602 for (const char *f : fields) {
1603 if (!d.value(QString::fromLatin1(f)).isDouble()) {
1604 errorMessage = QStringLiteral("Experiment quantumHallEdge contains invalid fields."); return false;
1605 }
1606 }
1607 document.quantumHallEdge.enabled = d.value(QStringLiteral("enabled")).toBool();
1608 document.quantumHallEdge.fieldStrength = d.value(QStringLiteral("fieldStrength")).toDouble();
1609 document.quantumHallEdge.edgeY = d.value(QStringLiteral("edgeY")).toDouble();
1610 document.quantumHallEdge.wallHeight = d.value(QStringLiteral("wallHeight")).toDouble();
1611 document.quantumHallEdge.launchY = d.value(QStringLiteral("launchY")).toDouble();
1612 document.quantumHallEdge.orbitRadius = d.value(QStringLiteral("orbitRadius")).toDouble();
1613 document.quantumHallEdge.packetSigma = d.value(QStringLiteral("packetSigma")).toDouble();
1614 document.quantumHallEdge.edgeBand = d.value(QStringLiteral("edgeBand")).toDouble();
1615 document.quantumHallEdge.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1616 if (!QuantumHallEdge2D::validateConfig(document.quantumHallEdge, nullptr)) {
1617 errorMessage = QStringLiteral("Experiment quantumHallEdge values are out of range."); return false;
1618 }
1619 return true;
1620}
1621
1622
1623/**
1624 * @brief Performs quantum backflow to json.
1625 * @param document The document value used by the operation.
1626 */
1628{
1629 QJsonObject d;
1630 d.insert(QStringLiteral("enabled"), document.quantumBackflow.enabled);
1631 d.insert(QStringLiteral("detectorX"), document.quantumBackflow.detectorX);
1632 d.insert(QStringLiteral("slowWaveNumber"), document.quantumBackflow.slowWaveNumber);
1633 d.insert(QStringLiteral("fastWaveNumber"), document.quantumBackflow.fastWaveNumber);
1634 d.insert(QStringLiteral("momentumSigma"), document.quantumBackflow.momentumSigma);
1635 d.insert(QStringLiteral("fastAmplitudeRatio"), document.quantumBackflow.fastAmplitudeRatio);
1636 d.insert(QStringLiteral("relativePhaseDegrees"), document.quantumBackflow.relativePhaseDegrees);
1637 d.insert(QStringLiteral("initialCenterX"), document.quantumBackflow.initialCenterX);
1638 d.insert(QStringLiteral("transverseSigma"), document.quantumBackflow.transverseSigma);
1639 d.insert(QStringLiteral("analysisEndTime"), document.quantumBackflow.analysisEndTime);
1640 return d;
1641}
1642
1643/**
1644 * @brief Performs quantum backflow from json.
1645 * @param json The json value used by the operation.
1646 * @param document The document value used by the operation.
1647 * @param errorMessage The error message value used by the operation.
1648 */
1649bool quantumBackflowFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
1650{
1651 const QJsonValue value = json.value(QStringLiteral("quantumBackflow"));
1652 if (!value.isObject()) {
1653 errorMessage = QStringLiteral("Experiment schema 26 is missing a valid quantumBackflow object.");
1654 return false;
1655 }
1656 const QJsonObject d = value.toObject();
1657 const char *fields[] = {"detectorX","slowWaveNumber","fastWaveNumber","momentumSigma",
1658 "fastAmplitudeRatio","relativePhaseDegrees","initialCenterX",
1659 "transverseSigma","analysisEndTime"};
1660 if (!d.value(QStringLiteral("enabled")).isBool()) {
1661 errorMessage = QStringLiteral("Experiment quantumBackflow contains invalid fields.");
1662 return false;
1663 }
1664 for (const char *f : fields) {
1665 if (!d.value(QString::fromLatin1(f)).isDouble()) {
1666 errorMessage = QStringLiteral("Experiment quantumBackflow contains invalid fields.");
1667 return false;
1668 }
1669 }
1670 document.quantumBackflow.enabled = d.value(QStringLiteral("enabled")).toBool();
1671 document.quantumBackflow.detectorX = d.value(QStringLiteral("detectorX")).toDouble();
1672 document.quantumBackflow.slowWaveNumber = d.value(QStringLiteral("slowWaveNumber")).toDouble();
1673 document.quantumBackflow.fastWaveNumber = d.value(QStringLiteral("fastWaveNumber")).toDouble();
1674 document.quantumBackflow.momentumSigma = d.value(QStringLiteral("momentumSigma")).toDouble();
1675 document.quantumBackflow.fastAmplitudeRatio = d.value(QStringLiteral("fastAmplitudeRatio")).toDouble();
1676 document.quantumBackflow.relativePhaseDegrees = d.value(QStringLiteral("relativePhaseDegrees")).toDouble();
1677 document.quantumBackflow.initialCenterX = d.value(QStringLiteral("initialCenterX")).toDouble();
1678 document.quantumBackflow.transverseSigma = d.value(QStringLiteral("transverseSigma")).toDouble();
1679 document.quantumBackflow.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1680 if (!QuantumBackflow2D::validateConfig(document.quantumBackflow, nullptr)) {
1681 errorMessage = QStringLiteral("Experiment quantumBackflow values are out of range.");
1682 return false;
1683 }
1684 return true;
1685}
1686
1687
1688/**
1689 * @brief Performs quantum zitterbewegung to json.
1690 * @param document The document value used by the operation.
1691 */
1693{
1694 QJsonObject d;
1695 d.insert(QStringLiteral("enabled"), document.quantumZitterbewegung.enabled);
1696 d.insert(QStringLiteral("lightSpeed"), document.quantumZitterbewegung.lightSpeed);
1697 d.insert(QStringLiteral("restMass"), document.quantumZitterbewegung.restMass);
1698 d.insert(QStringLiteral("centerX"), document.quantumZitterbewegung.centerX);
1699 d.insert(QStringLiteral("centerY"), document.quantumZitterbewegung.centerY);
1700 d.insert(QStringLiteral("sigma"), document.quantumZitterbewegung.sigma);
1701 d.insert(QStringLiteral("momentumX"), document.quantumZitterbewegung.momentumX);
1702 d.insert(QStringLiteral("momentumY"), document.quantumZitterbewegung.momentumY);
1703 d.insert(QStringLiteral("preparationMode"), document.quantumZitterbewegung.preparationMode);
1704 d.insert(QStringLiteral("analysisEndTime"), document.quantumZitterbewegung.analysisEndTime);
1705 return d;
1706}
1707
1708/**
1709 * @brief Performs quantum zitterbewegung from json.
1710 * @param json The json value used by the operation.
1711 * @param document The document value used by the operation.
1712 * @param errorMessage The error message value used by the operation.
1713 */
1714bool quantumZitterbewegungFromJson(const QJsonObject &json,
1715 ExperimentDocument2D &document,
1716 QString &errorMessage)
1717{
1718 const QJsonValue value = json.value(QStringLiteral("quantumZitterbewegung"));
1719 if (!value.isObject()) {
1720 errorMessage = QStringLiteral("Experiment schema 27 is missing a valid quantumZitterbewegung object.");
1721 return false;
1722 }
1723 const QJsonObject d = value.toObject();
1724 if (!d.value(QStringLiteral("enabled")).isBool() ||
1725 !d.value(QStringLiteral("preparationMode")).isDouble()) {
1726 errorMessage = QStringLiteral("Experiment quantumZitterbewegung contains invalid fields.");
1727 return false;
1728 }
1729 const char *fields[] = {"lightSpeed","restMass","centerX","centerY","sigma",
1730 "momentumX","momentumY","analysisEndTime"};
1731 for (const char *f : fields) {
1732 if (!d.value(QString::fromLatin1(f)).isDouble()) {
1733 errorMessage = QStringLiteral("Experiment quantumZitterbewegung contains invalid fields.");
1734 return false;
1735 }
1736 }
1737 document.quantumZitterbewegung.enabled = d.value(QStringLiteral("enabled")).toBool();
1738 document.quantumZitterbewegung.lightSpeed = d.value(QStringLiteral("lightSpeed")).toDouble();
1739 document.quantumZitterbewegung.restMass = d.value(QStringLiteral("restMass")).toDouble();
1740 document.quantumZitterbewegung.centerX = d.value(QStringLiteral("centerX")).toDouble();
1741 document.quantumZitterbewegung.centerY = d.value(QStringLiteral("centerY")).toDouble();
1742 document.quantumZitterbewegung.sigma = d.value(QStringLiteral("sigma")).toDouble();
1743 document.quantumZitterbewegung.momentumX = d.value(QStringLiteral("momentumX")).toDouble();
1744 document.quantumZitterbewegung.momentumY = d.value(QStringLiteral("momentumY")).toDouble();
1745 document.quantumZitterbewegung.preparationMode = d.value(QStringLiteral("preparationMode")).toInt(-1);
1746 document.quantumZitterbewegung.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1748 errorMessage = QStringLiteral("Experiment quantumZitterbewegung values are out of range.");
1749 return false;
1750 }
1751 return true;
1752}
1753
1754
1755/**
1756 * @brief Performs quantum klein tunneling to json.
1757 * @param document The document value used by the operation.
1758 */
1760{
1761 QJsonObject d;
1762 const auto &c = document.quantumKleinTunneling;
1763 d.insert(QStringLiteral("enabled"), c.enabled);
1764 d.insert(QStringLiteral("lightSpeed"), c.lightSpeed);
1765 d.insert(QStringLiteral("restMass"), c.restMass);
1766 d.insert(QStringLiteral("centerX"), c.centerX);
1767 d.insert(QStringLiteral("centerY"), c.centerY);
1768 d.insert(QStringLiteral("sigma"), c.sigma);
1769 d.insert(QStringLiteral("momentumX"), c.momentumX);
1770 d.insert(QStringLiteral("momentumY"), c.momentumY);
1771 d.insert(QStringLiteral("barrierCenterX"), c.barrierCenterX);
1772 d.insert(QStringLiteral("barrierWidth"), c.barrierWidth);
1773 d.insert(QStringLiteral("barrierHeight"), c.barrierHeight);
1774 d.insert(QStringLiteral("detectorX"), c.detectorX);
1775 d.insert(QStringLiteral("analysisEndTime"), c.analysisEndTime);
1776 return d;
1777}
1778
1779/**
1780 * @brief Performs quantum klein tunneling from json.
1781 * @param json The json value used by the operation.
1782 * @param document The document value used by the operation.
1783 * @param errorMessage The error message value used by the operation.
1784 */
1785bool quantumKleinTunnelingFromJson(const QJsonObject &json,
1786 ExperimentDocument2D &document,
1787 QString &errorMessage)
1788{
1789 const QJsonValue value = json.value(QStringLiteral("quantumKleinTunneling"));
1790 if (!value.isObject()) {
1791 errorMessage = QStringLiteral("Experiment schema 28 is missing a valid quantumKleinTunneling object.");
1792 return false;
1793 }
1794 const QJsonObject d = value.toObject();
1795 if (!d.value(QStringLiteral("enabled")).isBool()) {
1796 errorMessage = QStringLiteral("Experiment quantumKleinTunneling contains invalid fields.");
1797 return false;
1798 }
1799 const char *fields[] = {"lightSpeed","restMass","centerX","centerY","sigma","momentumX","momentumY",
1800 "barrierCenterX","barrierWidth","barrierHeight","detectorX","analysisEndTime"};
1801 for (const char *f : fields) {
1802 if (!d.value(QString::fromLatin1(f)).isDouble()) {
1803 errorMessage = QStringLiteral("Experiment quantumKleinTunneling contains invalid fields.");
1804 return false;
1805 }
1806 }
1807 auto &c = document.quantumKleinTunneling;
1808 c.enabled = d.value(QStringLiteral("enabled")).toBool();
1809 c.lightSpeed = d.value(QStringLiteral("lightSpeed")).toDouble();
1810 c.restMass = d.value(QStringLiteral("restMass")).toDouble();
1811 c.centerX = d.value(QStringLiteral("centerX")).toDouble();
1812 c.centerY = d.value(QStringLiteral("centerY")).toDouble();
1813 c.sigma = d.value(QStringLiteral("sigma")).toDouble();
1814 c.momentumX = d.value(QStringLiteral("momentumX")).toDouble();
1815 c.momentumY = d.value(QStringLiteral("momentumY")).toDouble();
1816 c.barrierCenterX = d.value(QStringLiteral("barrierCenterX")).toDouble();
1817 c.barrierWidth = d.value(QStringLiteral("barrierWidth")).toDouble();
1818 c.barrierHeight = d.value(QStringLiteral("barrierHeight")).toDouble();
1819 c.detectorX = d.value(QStringLiteral("detectorX")).toDouble();
1820 c.analysisEndTime = d.value(QStringLiteral("analysisEndTime")).toDouble();
1821 if (!QuantumKleinTunneling2D::validateConfig(c, nullptr)) {
1822 errorMessage = QStringLiteral("Experiment quantumKleinTunneling values are out of range.");
1823 return false;
1824 }
1825 return true;
1826}
1827
1828/**
1829 * @brief Initializes ial preparation from json.
1830 * @param json The json value used by the operation.
1831 * @param document The document value used by the operation.
1832 * @param errorMessage The error message value used by the operation.
1833 */
1834bool initialPreparationFromJson(const QJsonObject &json,
1835 ExperimentDocument2D &document,
1836 QString &errorMessage)
1837{
1838 const QJsonValue value = json.value(QStringLiteral("initialPreparation"));
1839 if (!value.isObject()) {
1840 errorMessage = QStringLiteral("Experiment schema 4+ is missing a valid initialPreparation object.");
1841 return false;
1842 }
1843 const QJsonObject prep = value.toObject();
1844 const QString type = prep.value(QStringLiteral("type")).toString();
1845 if (type == QStringLiteral("gaussian")) document.initialPreparationMode = 0;
1846 else if (type == QStringLiteral("boundEigenstate")) document.initialPreparationMode = 1;
1847 else if (type == QStringLiteral("boundSuperposition")) document.initialPreparationMode = 2;
1848 else if (type == QStringLiteral("talbotComb")) document.initialPreparationMode = 3;
1849 else if (type == QStringLiteral("vortex")) document.initialPreparationMode = 4;
1850 else if (type == QStringLiteral("andersonDualLane")) document.initialPreparationMode = 5;
1851 else if (type == QStringLiteral("kickedRotor")) document.initialPreparationMode = 6;
1852 else if (type == QStringLiteral("quantumZeno")) document.initialPreparationMode = 7;
1853 else if (type == QStringLiteral("berryFirstExcited")) document.initialPreparationMode = 8;
1854 else if (type == QStringLiteral("moshinskyShutter")) document.initialPreparationMode = 9;
1855 else if (type == QStringLiteral("kapitzaDiracBeam")) document.initialPreparationMode = 10;
1856 else if (type == QStringLiteral("aharonovBohmBeam")) document.initialPreparationMode = 11;
1857 else if (type == QStringLiteral("landauMagneticState")) document.initialPreparationMode = 12;
1858 else if (type == QStringLiteral("quantumHallEdgeState")) document.initialPreparationMode = 13;
1859 else if (type == QStringLiteral("quantumBackflowState")) document.initialPreparationMode = 14;
1860 else if (type == QStringLiteral("diracZitterbewegungState")) document.initialPreparationMode = 15;
1861 else if (type == QStringLiteral("diracKleinTunnelingState")) document.initialPreparationMode = 16;
1862 else {
1863 errorMessage = QStringLiteral("Experiment initialPreparation has unknown type '%1'.").arg(type);
1864 return false;
1865 }
1866
1867 const QJsonValue a = prep.value(QStringLiteral("stateA"));
1868 const QJsonValue b = prep.value(QStringLiteral("stateB"));
1869 const QJsonValue phase = prep.value(QStringLiteral("relativePhaseDegrees"));
1870 if (!a.isDouble() || !b.isDouble() || !phase.isDouble()) {
1871 errorMessage = QStringLiteral("Experiment initialPreparation contains invalid state/phase fields.");
1872 return false;
1873 }
1874 document.boundStateA = a.toInt(-1);
1875 document.boundStateB = b.toInt(-1);
1876 document.boundRelativePhaseDegrees = phase.toDouble();
1877 if (document.boundStateA < 0 || document.boundStateA > 31 ||
1878 document.boundStateB < 0 || document.boundStateB > 31 ||
1879 !std::isfinite(document.boundRelativePhaseDegrees)) {
1880 errorMessage = QStringLiteral("Experiment initialPreparation values are out of range.");
1881 return false;
1882 }
1883 if (document.initialPreparationMode == 2 && document.boundStateA == document.boundStateB) {
1884 errorMessage = QStringLiteral("Bound-state superposition requires two different states.");
1885 return false;
1886 }
1887 return true;
1888}
1889
1890} // namespace
1891
1893{
1894 return QStringLiteral("QuantumPhenomenaExplorer.Experiment2D");
1895}
1896
1898{
1899 QJsonObject controlsObject;
1900 QMap<QString, QVariant>::const_iterator it = document.controls.constBegin();
1901 for (; it != document.controls.constEnd(); ++it) {
1902 controlsObject.insert(it.key(), QJsonValue::fromVariant(it.value()));
1903 }
1904
1905 QJsonObject root;
1906 root.insert(QStringLiteral("format"), formatId());
1907 root.insert(QStringLiteral("schemaVersion"), document.schemaVersion);
1908 root.insert(QStringLiteral("name"), document.name);
1909 root.insert(QStringLiteral("sourcePreset"), document.sourcePreset);
1910 root.insert(QStringLiteral("controls"), controlsObject);
1911 if (document.schemaVersion >= 2) {
1912 root.insert(QStringLiteral("potentialScene"), potentialSceneToJson(document));
1913 }
1914 if (document.schemaVersion >= 4) {
1915 root.insert(QStringLiteral("initialPreparation"), initialPreparationToJson(document));
1916 }
1917 if (document.schemaVersion >= 5) {
1918 root.insert(QStringLiteral("measurementCollapse"), measurementCollapseToJson(document));
1919 }
1920 if (document.schemaVersion >= 6) {
1921 root.insert(QStringLiteral("quantumQuench"), quantumQuenchToJson(document));
1922 }
1923 if (document.schemaVersion >= 7) {
1924 root.insert(QStringLiteral("periodicDrive"), periodicDriveToJson(document));
1925 }
1926 if (document.schemaVersion >= 8) {
1927 root.insert(QStringLiteral("linearSweep"), linearSweepToJson(document));
1928 }
1929 if (document.schemaVersion >= 10) {
1930 root.insert(QStringLiteral("ramseySequence"), ramseySequenceToJson(document));
1931 }
1932 if (document.schemaVersion >= 12) {
1933 root.insert(QStringLiteral("ramseyEnsemble"), ramseyEnsembleToJson(document));
1934 }
1935 if (document.schemaVersion >= 13) {
1936 root.insert(QStringLiteral("talbotInitialState"), talbotInitialStateToJson(document));
1937 }
1938 if (document.schemaVersion >= 14) {
1939 root.insert(QStringLiteral("vortexInitialState"), vortexInitialStateToJson(document));
1940 }
1941 if (document.schemaVersion >= 15) {
1942 root.insert(QStringLiteral("andersonInitialState"), andersonInitialStateToJson(document));
1943 }
1944 if (document.schemaVersion >= 16) {
1945 root.insert(QStringLiteral("kickedRotor"), kickedRotorToJson(document));
1946 root.insert(QStringLiteral("kickedRotorInitialState"), kickedRotorInitialStateToJson(document));
1947 }
1948 if (document.schemaVersion >= 17) {
1949 root.insert(QStringLiteral("quantumZeno"), quantumZenoToJson(document));
1950 root.insert(QStringLiteral("quantumZenoInitialState"), quantumZenoInitialStateToJson(document));
1951 }
1952 if (document.schemaVersion >= 18) {
1953 root.insert(QStringLiteral("quantumScar"), quantumScarToJson(document));
1954 }
1955 if (document.schemaVersion >= 19) {
1956 root.insert(QStringLiteral("quantumBerry"), quantumBerryToJson(document));
1957 }
1958 if (document.schemaVersion >= 20) {
1959 root.insert(QStringLiteral("quantumLoschmidt"), quantumLoschmidtToJson(document));
1960 }
1961 if (document.schemaVersion >= 21) {
1962 root.insert(QStringLiteral("moshinskyInitialState"), moshinskyInitialStateToJson(document));
1963 root.insert(QStringLiteral("quantumMoshinsky"), quantumMoshinskyToJson(document));
1964 }
1965 if (document.schemaVersion >= 22) {
1966 root.insert(QStringLiteral("kapitzaDiracInitialState"), kapitzaDiracInitialStateToJson(document));
1967 root.insert(QStringLiteral("quantumKapitzaDirac"), quantumKapitzaDiracToJson(document));
1968 }
1969 if (document.schemaVersion >= 23) {
1970 root.insert(QStringLiteral("quantumAharonovBohm"), quantumAharonovBohmToJson(document));
1971 }
1972 if (document.schemaVersion >= 24) {
1973 root.insert(QStringLiteral("quantumLandau"), quantumLandauToJson(document));
1974 }
1975 if (document.schemaVersion >= 25) {
1976 root.insert(QStringLiteral("quantumHallEdge"), quantumHallEdgeToJson(document));
1977 }
1978 if (document.schemaVersion >= 26) {
1979 root.insert(QStringLiteral("quantumBackflow"), quantumBackflowToJson(document));
1980 }
1981 if (document.schemaVersion >= 27) {
1982 root.insert(QStringLiteral("quantumZitterbewegung"), quantumZitterbewegungToJson(document));
1983 }
1984 if (document.schemaVersion >= 28) {
1985 root.insert(QStringLiteral("quantumKleinTunneling"), quantumKleinTunnelingToJson(document));
1986 }
1987 return root;
1988}
1989
1990bool ExperimentDocument2DJson::fromJson(const QJsonObject &json,
1991 ExperimentDocument2D &document,
1992 QString &errorMessage)
1993{
1994 errorMessage.clear();
1995
1996 const QString format = json.value(QStringLiteral("format")).toString();
1997 if (format != formatId()) {
1998 errorMessage = QStringLiteral("This JSON file is not a Quantum Phenomena Explorer experiment document.");
1999 return false;
2000 }
2001
2002 const QJsonValue versionValue = json.value(QStringLiteral("schemaVersion"));
2003 if (!versionValue.isDouble()) {
2004 errorMessage = QStringLiteral("Experiment document is missing a valid schemaVersion.");
2005 return false;
2006 }
2007
2008 const int version = versionValue.toInt(-1);
2009 if (version < 1 || version > ExperimentDocument2D::CurrentSchemaVersion) {
2010 errorMessage = QStringLiteral("Unsupported experiment schema version %1 (this build supports versions 1 through %2).")
2011 .arg(version)
2013 return false;
2014 }
2015
2016 const QJsonValue controlsValue = json.value(QStringLiteral("controls"));
2017 if (!controlsValue.isObject()) {
2018 errorMessage = QStringLiteral("Experiment document does not contain a valid controls object.");
2019 return false;
2020 }
2021
2022 ExperimentDocument2D parsed;
2023 // In-memory documents are always promoted to the current schema after a
2024 // successful load. Re-saving an older document therefore writes the current schema.
2026 parsed.name = json.value(QStringLiteral("name")).toString();
2027 parsed.sourcePreset = json.value(QStringLiteral("sourcePreset")).toString();
2028
2029 const QJsonObject controlsObject = controlsValue.toObject();
2030 QJsonObject::const_iterator it = controlsObject.constBegin();
2031 for (; it != controlsObject.constEnd(); ++it) {
2032 if (it.value().isUndefined() || it.value().isNull() ||
2033 it.value().isArray() || it.value().isObject()) {
2034 continue;
2035 }
2036 parsed.controls.insert(it.key(), it.value().toVariant());
2037 }
2038
2039 if (parsed.controls.isEmpty()) {
2040 errorMessage = QStringLiteral("Experiment document contains no usable control values.");
2041 return false;
2042 }
2043
2044 if (version >= 2 && !potentialSceneFromJson(json, parsed, errorMessage)) {
2045 return false;
2046 }
2047 if (version >= 4 && !initialPreparationFromJson(json, parsed, errorMessage)) {
2048 return false;
2049 }
2050 if (version >= 5 && !measurementCollapseFromJson(json, parsed, errorMessage)) {
2051 return false;
2052 }
2053 if (version >= 6 && !quantumQuenchFromJson(json, parsed, errorMessage)) {
2054 return false;
2055 }
2056 if (version >= 7 && !periodicDriveFromJson(json, parsed, errorMessage)) {
2057 return false;
2058 }
2059 if (version >= 8 && !linearSweepFromJson(json, parsed, errorMessage)) {
2060 return false;
2061 }
2062 if (version >= 10 && !ramseySequenceFromJson(json, parsed, errorMessage)) {
2063 return false;
2064 }
2065 if (version >= 12 && !ramseyEnsembleFromJson(json, parsed, errorMessage)) {
2066 return false;
2067 }
2068 if (version >= 13 && !talbotInitialStateFromJson(json, parsed, errorMessage)) {
2069 return false;
2070 }
2071 if (version >= 14 && !vortexInitialStateFromJson(json, parsed, errorMessage)) {
2072 return false;
2073 }
2074 if (version >= 15 && !andersonInitialStateFromJson(json, parsed, errorMessage)) {
2075 return false;
2076 }
2077 if (version >= 16 && !kickedRotorFromJson(json, parsed, errorMessage)) {
2078 return false;
2079 }
2080 if (version >= 16 && !kickedRotorInitialStateFromJson(json, parsed, errorMessage)) {
2081 return false;
2082 }
2083 if (version >= 17 && !quantumZenoFromJson(json, parsed, errorMessage)) {
2084 return false;
2085 }
2086 if (version >= 17 && !quantumZenoInitialStateFromJson(json, parsed, errorMessage)) {
2087 return false;
2088 }
2089 if (version >= 18 && !quantumScarFromJson(json, parsed, errorMessage)) {
2090 return false;
2091 }
2092 if (version >= 19 && !quantumBerryFromJson(json, parsed, errorMessage)) {
2093 return false;
2094 }
2095 if (version >= 20 && !quantumLoschmidtFromJson(json, parsed, errorMessage)) {
2096 return false;
2097 }
2098 if (version >= 21 && !moshinskyInitialStateFromJson(json, parsed, errorMessage)) {
2099 return false;
2100 }
2101 if (version >= 21 && !quantumMoshinskyFromJson(json, parsed, errorMessage)) {
2102 return false;
2103 }
2104 if (version >= 22 && !kapitzaDiracInitialStateFromJson(json, parsed, errorMessage)) {
2105 return false;
2106 }
2107 if (version >= 22 && !quantumKapitzaDiracFromJson(json, parsed, errorMessage)) {
2108 return false;
2109 }
2110 if (version >= 23 && !quantumAharonovBohmFromJson(json, parsed, errorMessage)) {
2111 return false;
2112 }
2113 if (version >= 24 && !quantumLandauFromJson(json, parsed, errorMessage)) {
2114 return false;
2115 }
2116 if (version >= 25 && !quantumHallEdgeFromJson(json, parsed, errorMessage)) {
2117 return false;
2118 }
2119 if (version >= 26 && !quantumBackflowFromJson(json, parsed, errorMessage)) {
2120 return false;
2121 }
2122 if (version >= 27 && !quantumZitterbewegungFromJson(json, parsed, errorMessage)) {
2123 return false;
2124 }
2125 if (version >= 28 && !quantumKleinTunnelingFromJson(json, parsed, errorMessage)) {
2126 return false;
2127 }
2128
2129 document = parsed;
2130 return true;
2131}
2132
2133bool ExperimentDocument2DJson::saveFile(const QString &fileName,
2134 const ExperimentDocument2D &document,
2135 QString &errorMessage)
2136{
2137 errorMessage.clear();
2138
2139 QSaveFile file(fileName);
2140 if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
2141 errorMessage = QStringLiteral("Cannot open '%1' for writing: %2")
2142 .arg(fileName, file.errorString());
2143 return false;
2144 }
2145
2146 const QJsonDocument jsonDocument(toJson(document));
2147 const QByteArray bytes = jsonDocument.toJson(QJsonDocument::Indented);
2148 if (file.write(bytes) != bytes.size()) {
2149 errorMessage = QStringLiteral("Cannot write '%1': %2")
2150 .arg(fileName, file.errorString());
2151 file.cancelWriting();
2152 return false;
2153 }
2154
2155 if (!file.commit()) {
2156 errorMessage = QStringLiteral("Cannot commit '%1': %2")
2157 .arg(fileName, file.errorString());
2158 return false;
2159 }
2160
2161 return true;
2162}
2163
2164bool ExperimentDocument2DJson::loadFile(const QString &fileName,
2165 ExperimentDocument2D &document,
2166 QString &errorMessage)
2167{
2168 errorMessage.clear();
2169
2170 QFile file(fileName);
2171 if (!file.open(QIODevice::ReadOnly)) {
2172 errorMessage = QStringLiteral("Cannot open '%1': %2")
2173 .arg(fileName, file.errorString());
2174 return false;
2175 }
2176
2177 QJsonParseError parseError;
2178 const QJsonDocument jsonDocument = QJsonDocument::fromJson(file.readAll(), &parseError);
2179 if (parseError.error != QJsonParseError::NoError) {
2180 errorMessage = QStringLiteral("JSON parse error at offset %1: %2")
2181 .arg(parseError.offset)
2182 .arg(parseError.errorString());
2183 return false;
2184 }
2185
2186 if (!jsonDocument.isObject()) {
2187 errorMessage = QStringLiteral("Experiment JSON root must be an object.");
2188 return false;
2189 }
2190
2191 return fromJson(jsonDocument.object(), document, errorMessage);
2192}
2193
2194} // namespace qpe
static bool fromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs from json.
static QJsonObject toJson(const ExperimentDocument2D &document)
Performs to json.
static bool saveFile(const QString &fileName, const ExperimentDocument2D &document, QString &errorMessage)
Saves file.
static bool loadFile(const QString &fileName, ExperimentDocument2D &document, QString &errorMessage)
Loads file.
static QString formatId()
Performs format id.
Implements the Potential Scene2D component.
std::uint64_t add(PotentialObject2D object)
Performs add.
bool empty() const noexcept
Performs empty.
const std::vector< PotentialObject2D > & objects() const noexcept
Performs objects.
static bool validateConfig(const QuantumAharonovBohm2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumAndersonInitialState2DConfig &config, std::string *reason=nullptr)
Validates config.
static bool validateConfig(const QuantumBackflow2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumBerryLoop2DConfig &config, const QuantumBerryTrap2D &trap, const char **reason=nullptr) noexcept
Validates config.
static bool identifyTrap(const PotentialScene2D &scene, QuantumBerryTrap2D &trap, const char **reason=nullptr) noexcept
Returns identify trap.
static bool validateConfig(const QuantumHallEdge2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateInitialState(const QuantumKapitzaDiracInitialState2DConfig &config, std::string *reason=nullptr)
Validates initial state.
static bool validateConfig(const QuantumKapitzaDirac2DConfig &config, double hbar, std::string *reason=nullptr)
Validates config.
static bool validateConfig(const QuantumKickedRotor2DConfig &config, std::string *reason=nullptr)
Validates config.
static bool validateInitialState(const QuantumKickedRotorInitialState2DConfig &config, std::string *reason=nullptr)
Validates initial state.
static bool validateConfig(const QuantumKleinTunneling2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumLandau2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumLoschmidt2DConfig &config, const char **reason=nullptr) noexcept
Validates config.
static bool validateInitialState(const QuantumMoshinskyInitialState2DConfig &config, const char **reason=nullptr) noexcept
Validates initial state.
static bool validateConfig(const PotentialScene2D &scene, const QuantumMoshinsky2DConfig &config, QuantumMoshinskyGeometry2D *geometry=nullptr, const char **reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumScarConfig2D &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumTalbotInitialState2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateConfig(const QuantumVortexInitialState2DConfig &config, std::string *reason=nullptr)
Validates config.
static bool validateConfig(const QuantumZeno2DConfig &config, std::string *reason=nullptr)
Validates config.
static bool validateInitialState(const QuantumZenoInitialState2DConfig &config, std::string *reason=nullptr)
Validates initial state.
static bool validateConfig(const QuantumZitterbewegung2DConfig &config, std::string *reason=nullptr) noexcept
Validates config.
static bool validateEnsembleConfig(const RamseyEnsemble2DConfig &config) noexcept
Validates ensemble config.
static bool validatePeriodic(const PotentialScene2D &scene, const PeriodicPotentialDrive2DConfig &config) noexcept
Validates periodic.
static bool validateSweep(const PotentialScene2D &scene, const LinearPotentialSweep2DConfig &config) noexcept
Validates sweep.
static bool validateRamsey(const PotentialScene2D &scene, const RamseyPulseSequence2DConfig &config) noexcept
Validates ramsey.
static bool validate(const PotentialScene2D &scene, const QuantumQuench2DConfig &config) noexcept
Performs validate.
Declares the schema-28 experiment persistence document and JSON conversion API.
QJsonObject quantumBerryToJson(const ExperimentDocument2D &document)
Performs quantum berry to json.
QJsonObject andersonInitialStateToJson(const ExperimentDocument2D &document)
Performs anderson initial state to json.
bool kickedRotorInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs kicked rotor initial state from json.
QJsonObject quantumHallEdgeToJson(const ExperimentDocument2D &document)
Performs quantum hall edge to json.
bool quantumBerryFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum berry from json.
QJsonObject quantumZitterbewegungToJson(const ExperimentDocument2D &document)
Performs quantum zitterbewegung to json.
bool quantumKapitzaDiracFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum kapitza dirac from json.
QJsonObject kapitzaDiracInitialStateToJson(const ExperimentDocument2D &document)
Performs kapitza dirac initial state to json.
QJsonObject periodicDriveToJson(const ExperimentDocument2D &document)
Performs periodic drive to json.
QJsonObject quantumMoshinskyToJson(const ExperimentDocument2D &document)
Performs quantum moshinsky to json.
QJsonObject quantumZenoToJson(const ExperimentDocument2D &document)
Performs quantum zeno to json.
bool linearSweepFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs linear sweep from json.
QJsonObject quantumBackflowToJson(const ExperimentDocument2D &document)
Performs quantum backflow to json.
QJsonObject quantumKleinTunnelingToJson(const ExperimentDocument2D &document)
Performs quantum klein tunneling to json.
QJsonObject potentialSceneToJson(const ExperimentDocument2D &document)
Performs potential scene to json.
QString potentialTypeName(PotentialObjectType2D type)
Performs potential type name.
bool finiteJsonNumber(const QJsonObject &json, const char *name, float &value)
Performs finite json number.
QJsonObject talbotInitialStateToJson(const ExperimentDocument2D &document)
Performs talbot initial state to json.
bool quantumZenoFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum zeno from json.
bool measurementCollapseFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Measures ment collapse from json.
bool quantumLoschmidtFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum loschmidt from json.
bool quantumAharonovBohmFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum aharonov bohm from json.
QJsonObject kickedRotorInitialStateToJson(const ExperimentDocument2D &document)
Performs kicked rotor initial state to json.
bool quantumHallEdgeFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum hall edge from json.
QJsonObject quantumQuenchToJson(const ExperimentDocument2D &document)
Performs quantum quench to json.
bool potentialSceneFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs potential scene from json.
bool ramseySequenceFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs ramsey sequence from json.
bool quantumMoshinskyFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum moshinsky from json.
QJsonObject quantumScarToJson(const ExperimentDocument2D &document)
Performs quantum scar to json.
QJsonObject quantumZenoInitialStateToJson(const ExperimentDocument2D &document)
Performs quantum zeno initial state to json.
QJsonObject measurementCollapseToJson(const ExperimentDocument2D &document)
Measures ment collapse to json.
QJsonObject initialPreparationToJson(const ExperimentDocument2D &document)
Initializes ial preparation to json.
bool vortexInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs vortex initial state from json.
bool moshinskyInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs moshinsky initial state from json.
bool kapitzaDiracInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs kapitza dirac initial state from json.
bool quantumQuenchFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum quench from json.
bool quantumKleinTunnelingFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum klein tunneling from json.
bool periodicDriveFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs periodic drive from json.
QJsonObject potentialObjectToJson(const PotentialObject2D &object)
Performs potential object to json.
QJsonObject quantumLoschmidtToJson(const ExperimentDocument2D &document)
Performs quantum loschmidt to json.
bool kickedRotorFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs kicked rotor from json.
QJsonObject linearSweepToJson(const ExperimentDocument2D &document)
Performs linear sweep to json.
bool talbotInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs talbot initial state from json.
bool potentialTypeFromName(const QString &name, PotentialObjectType2D &type)
Performs potential type from name.
bool quantumZitterbewegungFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum zitterbewegung from json.
QJsonObject vortexInitialStateToJson(const ExperimentDocument2D &document)
Performs vortex initial state to json.
QJsonObject moshinskyInitialStateToJson(const ExperimentDocument2D &document)
Performs moshinsky initial state to json.
QJsonObject quantumLandauToJson(const ExperimentDocument2D &document)
Performs quantum landau to json.
bool potentialObjectFromJson(const QJsonObject &json, PotentialObject2D &object, QString &errorMessage, int index)
Performs potential object from json.
bool quantumBackflowFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum backflow from json.
bool andersonInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs anderson initial state from json.
bool quantumZenoInitialStateFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum zeno initial state from json.
QJsonObject quantumAharonovBohmToJson(const ExperimentDocument2D &document)
Performs quantum aharonov bohm to json.
bool initialPreparationFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Initializes ial preparation from json.
bool quantumLandauFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum landau from json.
bool ramseyEnsembleFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs ramsey ensemble from json.
QJsonObject kickedRotorToJson(const ExperimentDocument2D &document)
Performs kicked rotor to json.
QJsonObject ramseyEnsembleToJson(const ExperimentDocument2D &document)
Performs ramsey ensemble to json.
QJsonObject ramseySequenceToJson(const ExperimentDocument2D &document)
Performs ramsey sequence to json.
bool quantumScarFromJson(const QJsonObject &json, ExperimentDocument2D &document, QString &errorMessage)
Performs quantum scar from json.
QJsonObject quantumKapitzaDiracToJson(const ExperimentDocument2D &document)
Performs quantum kapitza dirac to json.
TimePotentialParameter2D
Enumerates the supported Time Potential Parameter2D values.
PotentialObjectType2D
Enumerates the supported Potential Object Type2D values.
Serializable experiment document used by QPE schema 28.
QuantumVortexInitialState2DConfig vortexInitialState
QMap< QString, QVariant > controls
QuantumTalbotInitialState2DConfig talbotInitialState
QuantumBackflow2DConfig quantumBackflow
QuantumLoschmidt2DConfig quantumLoschmidt
LinearPotentialSweep2DConfig linearSweep
QuantumLandau2DConfig quantumLandau
QuantumKickedRotor2DConfig kickedRotor
PeriodicPotentialDrive2DConfig periodicDrive
QuantumAharonovBohm2DConfig quantumAharonovBohm
static const int CurrentSchemaVersion
QuantumBerryLoop2DConfig quantumBerry
QuantumMoshinsky2DConfig quantumMoshinsky
RamseyEnsemble2DConfig ramseyEnsemble
QuantumKapitzaDiracInitialState2DConfig kapitzaDiracInitialState
QuantumZitterbewegung2DConfig quantumZitterbewegung
QuantumHallEdge2DConfig quantumHallEdge
QuantumMoshinskyInitialState2DConfig moshinskyInitialState
QuantumAndersonInitialState2DConfig andersonInitialState
QuantumKapitzaDirac2DConfig quantumKapitzaDirac
RamseyPulseSequence2DConfig ramseySequence
QuantumKleinTunneling2DConfig quantumKleinTunneling
QuantumZenoInitialState2DConfig quantumZenoInitialState
QuantumKickedRotorInitialState2DConfig kickedRotorInitialState
QuantumQuench2DConfig quench
Data structure used by the Potential Object2D component.
PotentialObjectType2D type
bool valid() const noexcept
Performs valid.
Data structure used by the Quantum Berry Trap2D component.
TimePotentialParameter2D parameter