Spaces:
Paused
Paused
harishaseebat92
commited on
Commit
·
c131b0b
1
Parent(s):
fd3d804
Refactored the EM backend selection by (1) rebranding the former IBM QPU path into a dedicated Statevector Estimator simulator and (2) rewiring the backend plumbing so the heavy lifting now happens inside
Browse files- em/excitation.py +2 -2
- em/handlers.py +8 -3
- em/qpu.py +13 -10
- em/simulation.py +48 -15
- em/state.py +11 -0
- em/ui.py +7 -6
- em_embedded.py +1 -1
- qlbm/qlbm_sample_app.py +27 -36
- utils/delta_impulse_generator.py +6 -5
em/excitation.py
CHANGED
|
@@ -7,7 +7,7 @@ import numpy as np
|
|
| 7 |
import pyvista as pv
|
| 8 |
import plotly.graph_objects as go
|
| 9 |
|
| 10 |
-
from .state import state, ctrl
|
| 11 |
from .globals import (
|
| 12 |
plotter, current_mesh, DEFAULT_AXIS_TICKS, EXCITATION_SURFACE_COLORSCALE
|
| 13 |
)
|
|
@@ -352,7 +352,7 @@ def update_qpu_sample_slot(slot_index: int):
|
|
| 352 |
snapped, message = snap_samples_to_grid(sample_value, int(nx_val))
|
| 353 |
setattr(state, grid_attr, snapped)
|
| 354 |
setattr(state, info_attr, message or "")
|
| 355 |
-
if state.backend_type == "QPU":
|
| 356 |
hide_qpu_plots()
|
| 357 |
|
| 358 |
|
|
|
|
| 7 |
import pyvista as pv
|
| 8 |
import plotly.graph_objects as go
|
| 9 |
|
| 10 |
+
from .state import state, ctrl, is_statevector_estimator_selected
|
| 11 |
from .globals import (
|
| 12 |
plotter, current_mesh, DEFAULT_AXIS_TICKS, EXCITATION_SURFACE_COLORSCALE
|
| 13 |
)
|
|
|
|
| 352 |
snapped, message = snap_samples_to_grid(sample_value, int(nx_val))
|
| 353 |
setattr(state, grid_attr, snapped)
|
| 354 |
setattr(state, info_attr, message or "")
|
| 355 |
+
if state.backend_type == "QPU" or is_statevector_estimator_selected():
|
| 356 |
hide_qpu_plots()
|
| 357 |
|
| 358 |
|
em/handlers.py
CHANGED
|
@@ -7,7 +7,7 @@ from __future__ import annotations
|
|
| 7 |
import re
|
| 8 |
from typing import TYPE_CHECKING
|
| 9 |
|
| 10 |
-
from .state import state, ctrl
|
| 11 |
from .geometry import compute_hole_edges as _compute_hole_edges, update_geometry_hole_preview
|
| 12 |
from .excitation import update_initial_state_preview, update_excitation_info_message
|
| 13 |
from .qpu import (
|
|
@@ -245,7 +245,7 @@ def register_handlers():
|
|
| 245 |
|
| 246 |
@state.change("backend_type")
|
| 247 |
def on_backend_change(backend_type, **kwargs):
|
| 248 |
-
if backend_type == "QPU":
|
| 249 |
_hide_qpu_plots()
|
| 250 |
_apply_workflow_highlights(_determine_workflow_step())
|
| 251 |
|
|
@@ -254,6 +254,11 @@ def register_handlers():
|
|
| 254 |
if state.backend_type == "QPU":
|
| 255 |
_hide_qpu_plots()
|
| 256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 257 |
@state.change("qpu_plot_filter")
|
| 258 |
def on_qpu_plot_filter_change(qpu_plot_filter, **kwargs):
|
| 259 |
# No-op: updates handled by controller bound to the VSelect to avoid double refresh
|
|
@@ -352,7 +357,7 @@ def register_handlers():
|
|
| 352 |
|
| 353 |
update_excitation_info_message()
|
| 354 |
|
| 355 |
-
if state.backend_type == "QPU":
|
| 356 |
state.qpu_ts_ready = False
|
| 357 |
state.qpu_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
| 358 |
state.qpu_ts_other_ready = False
|
|
|
|
| 7 |
import re
|
| 8 |
from typing import TYPE_CHECKING
|
| 9 |
|
| 10 |
+
from .state import state, ctrl, is_statevector_estimator_selected
|
| 11 |
from .geometry import compute_hole_edges as _compute_hole_edges, update_geometry_hole_preview
|
| 12 |
from .excitation import update_initial_state_preview, update_excitation_info_message
|
| 13 |
from .qpu import (
|
|
|
|
| 245 |
|
| 246 |
@state.change("backend_type")
|
| 247 |
def on_backend_change(backend_type, **kwargs):
|
| 248 |
+
if backend_type == "QPU" or (backend_type == "Simulator" and is_statevector_estimator_selected()):
|
| 249 |
_hide_qpu_plots()
|
| 250 |
_apply_workflow_highlights(_determine_workflow_step())
|
| 251 |
|
|
|
|
| 254 |
if state.backend_type == "QPU":
|
| 255 |
_hide_qpu_plots()
|
| 256 |
|
| 257 |
+
@state.change("selected_simulator")
|
| 258 |
+
def on_selected_simulator_change(selected_simulator, **kwargs):
|
| 259 |
+
if is_statevector_estimator_selected():
|
| 260 |
+
_hide_qpu_plots()
|
| 261 |
+
|
| 262 |
@state.change("qpu_plot_filter")
|
| 263 |
def on_qpu_plot_filter_change(qpu_plot_filter, **kwargs):
|
| 264 |
# No-op: updates handled by controller bound to the VSelect to avoid double refresh
|
|
|
|
| 357 |
|
| 358 |
update_excitation_info_message()
|
| 359 |
|
| 360 |
+
if state.backend_type == "QPU" or is_statevector_estimator_selected():
|
| 361 |
state.qpu_ts_ready = False
|
| 362 |
state.qpu_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
| 363 |
state.qpu_ts_other_ready = False
|
em/qpu.py
CHANGED
|
@@ -15,10 +15,8 @@ from .utils import normalized_position_label, format_grid_label
|
|
| 15 |
|
| 16 |
# Import backend functions
|
| 17 |
try:
|
| 18 |
-
from quantum.utils.delta_impulse_generator import create_time_frames, run_qpu
|
| 19 |
import quantum.utils.delta_impulse_generator as qutils
|
| 20 |
except ModuleNotFoundError:
|
| 21 |
-
from utils.delta_impulse_generator import create_time_frames, run_qpu
|
| 22 |
import utils.delta_impulse_generator as qutils
|
| 23 |
|
| 24 |
__all__ = [
|
|
@@ -208,8 +206,10 @@ def refresh_qpu_plot_figures():
|
|
| 208 |
state.qpu_other_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
| 209 |
|
| 210 |
|
| 211 |
-
def build_qpu_timeseries_plotly_multi(configs, nx: int, T: float, snapshot_dt: float, impulse_pos, progress_callback=None, print_callback=None):
|
| 212 |
-
"""Build multi-config Plotly time series
|
|
|
|
|
|
|
| 213 |
times = qutils.create_time_frames(T, snapshot_dt)
|
| 214 |
fig = go.Figure()
|
| 215 |
|
|
@@ -259,12 +259,15 @@ def build_qpu_timeseries_plotly_multi(configs, nx: int, T: float, snapshot_dt: f
|
|
| 259 |
progress_callback(total_p)
|
| 260 |
|
| 261 |
try:
|
| 262 |
-
series_map_field =
|
| 263 |
-
field_type,
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
|
|
|
|
|
|
|
|
|
| 268 |
)
|
| 269 |
except Exception as e:
|
| 270 |
msg = f"QPU error for {field_type} positions {valid_positions}: {e}"
|
|
|
|
| 15 |
|
| 16 |
# Import backend functions
|
| 17 |
try:
|
|
|
|
| 18 |
import quantum.utils.delta_impulse_generator as qutils
|
| 19 |
except ModuleNotFoundError:
|
|
|
|
| 20 |
import utils.delta_impulse_generator as qutils
|
| 21 |
|
| 22 |
__all__ = [
|
|
|
|
| 206 |
state.qpu_other_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
| 207 |
|
| 208 |
|
| 209 |
+
def build_qpu_timeseries_plotly_multi(configs, nx: int, T: float, snapshot_dt: float, impulse_pos, *, series_runner, progress_callback=None, print_callback=None):
|
| 210 |
+
"""Build multi-config Plotly time series using the provided series runner."""
|
| 211 |
+
if series_runner is None:
|
| 212 |
+
raise ValueError("series_runner callable is required for QPU timeseries builds.")
|
| 213 |
times = qutils.create_time_frames(T, snapshot_dt)
|
| 214 |
fig = go.Figure()
|
| 215 |
|
|
|
|
| 259 |
progress_callback(total_p)
|
| 260 |
|
| 261 |
try:
|
| 262 |
+
series_map_field = series_runner(
|
| 263 |
+
field_type=field_type,
|
| 264 |
+
positions=valid_positions,
|
| 265 |
+
total_time=float(T),
|
| 266 |
+
snapshot_dt=float(snapshot_dt),
|
| 267 |
+
nx=int(nx),
|
| 268 |
+
impulse_pos=impulse_pos,
|
| 269 |
+
progress_callback=_sub_progress,
|
| 270 |
+
print_callback=print_callback,
|
| 271 |
)
|
| 272 |
except Exception as e:
|
| 273 |
msg = f"QPU error for {field_type} positions {valid_positions}: {e}"
|
em/simulation.py
CHANGED
|
@@ -6,7 +6,7 @@ and stop handlers.
|
|
| 6 |
"""
|
| 7 |
import numpy as np
|
| 8 |
|
| 9 |
-
from .state import state, ctrl, _apply_workflow_highlights
|
| 10 |
from .globals import (
|
| 11 |
plotter, simulation_data, current_mesh, snapshot_times,
|
| 12 |
stop_simulation, qpu_ts_cache, sim_ts_cache, set_stop_simulation, reset_globals
|
|
@@ -317,11 +317,13 @@ def run_simulation_only():
|
|
| 317 |
state.stop_button_disabled = True
|
| 318 |
return
|
| 319 |
|
| 320 |
-
|
| 321 |
-
|
|
|
|
|
|
|
| 322 |
try:
|
| 323 |
-
log_to_console("Running
|
| 324 |
-
state.status_message = "Running
|
| 325 |
state.simulation_progress = 20
|
| 326 |
state.qpu_ts_ready = False
|
| 327 |
state.qpu_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
|
@@ -347,12 +349,27 @@ def run_simulation_only():
|
|
| 347 |
p = getattr(state, f"qpu_monitor_gridpoints_{slot_num}", "") or ""
|
| 348 |
configs.append({"field": f, "points": p})
|
| 349 |
|
| 350 |
-
state.status_message = "Building
|
| 351 |
state.simulation_progress = 60
|
| 352 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 353 |
# Build and render Plotly chart
|
| 354 |
fig = build_qpu_timeseries_plotly_multi(
|
| 355 |
-
configs, nx, T, snapshot_dt, impulse_pos,
|
|
|
|
| 356 |
progress_callback=_progress_callback,
|
| 357 |
print_callback=log_to_console
|
| 358 |
)
|
|
@@ -366,8 +383,8 @@ def run_simulation_only():
|
|
| 366 |
state.simulation_has_run = True
|
| 367 |
state.run_button_text = "Successful!"
|
| 368 |
state.simulation_progress = 100
|
| 369 |
-
state.status_message = "
|
| 370 |
-
log_to_console("
|
| 371 |
state.status_type = "success"
|
| 372 |
state.show_progress = False
|
| 373 |
|
|
@@ -381,19 +398,19 @@ def run_simulation_only():
|
|
| 381 |
state.qpu_other_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
| 382 |
|
| 383 |
if not ready:
|
| 384 |
-
state.error_message = "No
|
| 385 |
-
state.status_message = "Warning: No
|
| 386 |
state.status_type = "warning"
|
| 387 |
-
log_to_console("
|
| 388 |
|
| 389 |
except Exception as e:
|
| 390 |
-
state.error_message = f"
|
| 391 |
-
state.status_message = f"
|
| 392 |
state.status_type = "error"
|
| 393 |
state.show_progress = False
|
| 394 |
state.run_button_text = "RUN!"
|
| 395 |
state.qpu_ts_ready = False
|
| 396 |
-
log_to_console(f"
|
| 397 |
finally:
|
| 398 |
state.is_running = False
|
| 399 |
state.stop_button_disabled = True
|
|
@@ -403,6 +420,22 @@ def run_simulation_only():
|
|
| 403 |
pass
|
| 404 |
return
|
| 405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
# Simulator path
|
| 407 |
log_to_console("Running simulation...")
|
| 408 |
state.status_message = "Running simulation... This may take a while."
|
|
|
|
| 6 |
"""
|
| 7 |
import numpy as np
|
| 8 |
|
| 9 |
+
from .state import state, ctrl, _apply_workflow_highlights, is_statevector_estimator_selected
|
| 10 |
from .globals import (
|
| 11 |
plotter, simulation_data, current_mesh, snapshot_times,
|
| 12 |
stop_simulation, qpu_ts_cache, sim_ts_cache, set_stop_simulation, reset_globals
|
|
|
|
| 317 |
state.stop_button_disabled = True
|
| 318 |
return
|
| 319 |
|
| 320 |
+
sve_selected = is_statevector_estimator_selected()
|
| 321 |
+
|
| 322 |
+
# If Statevector Estimator selected, build time series chart and return
|
| 323 |
+
if sve_selected:
|
| 324 |
try:
|
| 325 |
+
log_to_console("Running Statevector Estimator...")
|
| 326 |
+
state.status_message = "Running Statevector Estimator simulation..."
|
| 327 |
state.simulation_progress = 20
|
| 328 |
state.qpu_ts_ready = False
|
| 329 |
state.qpu_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
|
|
|
| 349 |
p = getattr(state, f"qpu_monitor_gridpoints_{slot_num}", "") or ""
|
| 350 |
configs.append({"field": f, "points": p})
|
| 351 |
|
| 352 |
+
state.status_message = "Building Statevector Estimator time series..."
|
| 353 |
state.simulation_progress = 60
|
| 354 |
|
| 355 |
+
def _sve_series_runner(field_type, positions, total_time, snapshot_dt, nx, impulse_pos, progress_callback=None, print_callback=None):
|
| 356 |
+
return qutils.run_sve(
|
| 357 |
+
field_type,
|
| 358 |
+
positions,
|
| 359 |
+
None,
|
| 360 |
+
total_time,
|
| 361 |
+
snapshot_dt,
|
| 362 |
+
nx,
|
| 363 |
+
None,
|
| 364 |
+
impulse_pos,
|
| 365 |
+
progress_callback=progress_callback,
|
| 366 |
+
print_callback=print_callback,
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
# Build and render Plotly chart
|
| 370 |
fig = build_qpu_timeseries_plotly_multi(
|
| 371 |
+
configs, nx, T, snapshot_dt, impulse_pos,
|
| 372 |
+
series_runner=_sve_series_runner,
|
| 373 |
progress_callback=_progress_callback,
|
| 374 |
print_callback=log_to_console
|
| 375 |
)
|
|
|
|
| 383 |
state.simulation_has_run = True
|
| 384 |
state.run_button_text = "Successful!"
|
| 385 |
state.simulation_progress = 100
|
| 386 |
+
state.status_message = "Statevector Estimator simulation completed successfully!"
|
| 387 |
+
log_to_console("Statevector Estimator run completed")
|
| 388 |
state.status_type = "success"
|
| 389 |
state.show_progress = False
|
| 390 |
|
|
|
|
| 398 |
state.qpu_other_plot_style = "display: none; width: 900px; height: 660px; margin: 0 auto;"
|
| 399 |
|
| 400 |
if not ready:
|
| 401 |
+
state.error_message = "No Statevector Estimator time series generated. Check Δt, T, nx, and monitor points."
|
| 402 |
+
state.status_message = "Warning: No Statevector Estimator time series generated."
|
| 403 |
state.status_type = "warning"
|
| 404 |
+
log_to_console("Statevector Estimator complete.")
|
| 405 |
|
| 406 |
except Exception as e:
|
| 407 |
+
state.error_message = f"Statevector Estimator run failed: {e}"
|
| 408 |
+
state.status_message = f"Statevector Estimator Error: {e}"
|
| 409 |
state.status_type = "error"
|
| 410 |
state.show_progress = False
|
| 411 |
state.run_button_text = "RUN!"
|
| 412 |
state.qpu_ts_ready = False
|
| 413 |
+
log_to_console(f"Statevector Estimator error: {e}")
|
| 414 |
finally:
|
| 415 |
state.is_running = False
|
| 416 |
state.stop_button_disabled = True
|
|
|
|
| 420 |
pass
|
| 421 |
return
|
| 422 |
|
| 423 |
+
# IBM QPU placeholder branch
|
| 424 |
+
if state.backend_type == "QPU":
|
| 425 |
+
state.error_message = "IBM QPU backend is not yet available in this build. Please select the Statevector Estimator from the Simulator menu."
|
| 426 |
+
state.status_message = "IBM QPU backend unavailable."
|
| 427 |
+
state.status_type = "warning"
|
| 428 |
+
state.show_progress = False
|
| 429 |
+
state.is_running = False
|
| 430 |
+
state.run_button_text = "RUN!"
|
| 431 |
+
state.stop_button_disabled = True
|
| 432 |
+
log_to_console("IBM QPU backend not connected. Use the Statevector Estimator simulator instead.")
|
| 433 |
+
try:
|
| 434 |
+
ctrl.view_update()
|
| 435 |
+
except Exception:
|
| 436 |
+
pass
|
| 437 |
+
return
|
| 438 |
+
|
| 439 |
# Simulator path
|
| 440 |
log_to_console("Running simulation...")
|
| 441 |
state.status_message = "Running simulation... This may take a while."
|
em/state.py
CHANGED
|
@@ -10,6 +10,7 @@ __all__ = [
|
|
| 10 |
"state", "ctrl", "set_server", "init_state",
|
| 11 |
"enable_point_picking_on_plotter",
|
| 12 |
"_apply_workflow_highlights", "_determine_workflow_step",
|
|
|
|
| 13 |
]
|
| 14 |
|
| 15 |
|
|
@@ -337,5 +338,15 @@ def enable_point_picking_on_plotter():
|
|
| 337 |
pass
|
| 338 |
|
| 339 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 340 |
# Initialize state defaults at module load time
|
| 341 |
_init_state_defaults()
|
|
|
|
| 10 |
"state", "ctrl", "set_server", "init_state",
|
| 11 |
"enable_point_picking_on_plotter",
|
| 12 |
"_apply_workflow_highlights", "_determine_workflow_step",
|
| 13 |
+
"is_statevector_estimator_selected",
|
| 14 |
]
|
| 15 |
|
| 16 |
|
|
|
|
| 338 |
pass
|
| 339 |
|
| 340 |
|
| 341 |
+
def is_statevector_estimator_selected() -> bool:
|
| 342 |
+
"""Return True when the simulator dropdown targets the Statevector Estimator."""
|
| 343 |
+
try:
|
| 344 |
+
if state.backend_type != "Simulator":
|
| 345 |
+
return False
|
| 346 |
+
return (state.selected_simulator or "").strip().lower() == "statevector estimator"
|
| 347 |
+
except AttributeError:
|
| 348 |
+
return False
|
| 349 |
+
|
| 350 |
+
|
| 351 |
# Initialize state defaults at module load time
|
| 352 |
_init_state_defaults()
|
em/ui.py
CHANGED
|
@@ -404,6 +404,7 @@ def _build_backends_card():
|
|
| 404 |
vuetify3.VListItem(v_bind="props", title="Simulator", prepend_icon="mdi-robot-outline", append_icon="mdi-chevron-right")
|
| 405 |
with vuetify3.VList(density="compact"):
|
| 406 |
vuetify3.VListItem(title="IBM Qiskit simulator", click="backend_type = 'Simulator'; selected_simulator = 'IBM Qiskit simulator'")
|
|
|
|
| 407 |
with vuetify3.VMenu(open_on_hover=True, close_on_content_click=True, location="end", offset=8):
|
| 408 |
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 409 |
vuetify3.VListItem(v_bind="props", title="QPU", prepend_icon="mdi-chip", append_icon="mdi-chevron-right")
|
|
@@ -425,7 +426,7 @@ def _build_output_preferences_card():
|
|
| 425 |
vuetify3.VAlert(v_if="temporal_warning", type="warning", variant="tonal", density="compact", children=["{{ temporal_warning }}"], classes="mt-1")
|
| 426 |
|
| 427 |
# QPU monitor options
|
| 428 |
-
with vuetify3.VContainer(v_if="backend_type === 'QPU'", classes="pa-0 mt-2"):
|
| 429 |
with vuetify3.VRow(dense=True, classes="mb-1 align-center"):
|
| 430 |
with vuetify3.VCol(cols=4, sm=3, md=3):
|
| 431 |
vuetify3.VSelect(
|
|
@@ -500,7 +501,7 @@ def _build_reset_button():
|
|
| 500 |
|
| 501 |
def _build_output_config_card():
|
| 502 |
"""Build the Output Configuration card (appears after simulation, not for QPU)."""
|
| 503 |
-
with vuetify3.VCard(v_if="simulation_has_run && backend_type !== 'QPU'", classes="mb-1", style="font-size: 0.8rem;"):
|
| 504 |
with vuetify3.VCardSubtitle("Output Configuration", classes="text-subtitle-1 text-primary", style="font-size: 0.9rem; padding: 6px 10px; font-weight: 600; color: #1A1A1A;"):
|
| 505 |
with vuetify3.VCardText(classes="py-1 px-2", style="color: #1A1A1A;"):
|
| 506 |
with vuetify3.VRadioGroup(v_model=("output_type", "Surface Plot"), row=True, density="compact", color="primary"):
|
|
@@ -553,7 +554,7 @@ def _build_output_config_card():
|
|
| 553 |
def _build_main_plot_area():
|
| 554 |
"""Build the main plot area (PyVista for Simulator)."""
|
| 555 |
with vuetify3.VCard(
|
| 556 |
-
v_if="geometry_selection && (backend_type !== 'QPU' || !qpu_ts_ready)",
|
| 557 |
classes="mb-1 flex-grow-1 d-flex flex-column",
|
| 558 |
style="min-height: 0;",
|
| 559 |
):
|
|
@@ -605,17 +606,17 @@ def _build_main_plot_area():
|
|
| 605 |
ctrl.sim_ts_update = sim_ts.update
|
| 606 |
|
| 607 |
# Time slider for surface plot
|
| 608 |
-
with vuetify3.VContainer(v_if="simulation_has_run && output_type === 'Surface Plot' && backend_type !== 'QPU'", fluid=True, classes="pa-0 mt-2"):
|
| 609 |
vuetify3.VSlider(v_model=("time_val", 0.0), label="Time", min=0, max=("T", 10.0), step=("dt_user", 0.1), thumb_label="always", density="compact", color="primary")
|
| 610 |
|
| 611 |
|
| 612 |
def _build_qpu_plot_area():
|
| 613 |
"""Build the QPU plot area (Plotly time series)."""
|
| 614 |
-
with vuetify3.VCard(v_if="geometry_selection && backend_type === 'QPU' && (is_running || qpu_ts_ready)", classes="flex-grow-1", style="min-height: 0;"):
|
| 615 |
# Running indicator
|
| 616 |
with vuetify3.VContainer(v_if="is_running", fluid=True, classes="fill-height d-flex flex-column align-center justify-center"):
|
| 617 |
vuetify3.VProgressCircular(indeterminate=True, size=64, color="primary")
|
| 618 |
-
vuetify3.VCardSubtitle("Running QPU...", classes="mt-4")
|
| 619 |
|
| 620 |
# QPU timeseries with toolbar
|
| 621 |
with vuetify3.VContainer(v_if="!is_running && qpu_ts_ready", fluid=True, classes="pa-2"):
|
|
|
|
| 404 |
vuetify3.VListItem(v_bind="props", title="Simulator", prepend_icon="mdi-robot-outline", append_icon="mdi-chevron-right")
|
| 405 |
with vuetify3.VList(density="compact"):
|
| 406 |
vuetify3.VListItem(title="IBM Qiskit simulator", click="backend_type = 'Simulator'; selected_simulator = 'IBM Qiskit simulator'")
|
| 407 |
+
vuetify3.VListItem(title="Statevector Estimator", click="backend_type = 'Simulator'; selected_simulator = 'Statevector Estimator'")
|
| 408 |
with vuetify3.VMenu(open_on_hover=True, close_on_content_click=True, location="end", offset=8):
|
| 409 |
with vuetify3.Template(v_slot_activator="{ props }"):
|
| 410 |
vuetify3.VListItem(v_bind="props", title="QPU", prepend_icon="mdi-chip", append_icon="mdi-chevron-right")
|
|
|
|
| 426 |
vuetify3.VAlert(v_if="temporal_warning", type="warning", variant="tonal", density="compact", children=["{{ temporal_warning }}"], classes="mt-1")
|
| 427 |
|
| 428 |
# QPU monitor options
|
| 429 |
+
with vuetify3.VContainer(v_if="backend_type === 'QPU' || (backend_type === 'Simulator' && selected_simulator === 'Statevector Estimator')", classes="pa-0 mt-2"):
|
| 430 |
with vuetify3.VRow(dense=True, classes="mb-1 align-center"):
|
| 431 |
with vuetify3.VCol(cols=4, sm=3, md=3):
|
| 432 |
vuetify3.VSelect(
|
|
|
|
| 501 |
|
| 502 |
def _build_output_config_card():
|
| 503 |
"""Build the Output Configuration card (appears after simulation, not for QPU)."""
|
| 504 |
+
with vuetify3.VCard(v_if="simulation_has_run && backend_type !== 'QPU' && !(backend_type === 'Simulator' && selected_simulator === 'Statevector Estimator')", classes="mb-1", style="font-size: 0.8rem;"):
|
| 505 |
with vuetify3.VCardSubtitle("Output Configuration", classes="text-subtitle-1 text-primary", style="font-size: 0.9rem; padding: 6px 10px; font-weight: 600; color: #1A1A1A;"):
|
| 506 |
with vuetify3.VCardText(classes="py-1 px-2", style="color: #1A1A1A;"):
|
| 507 |
with vuetify3.VRadioGroup(v_model=("output_type", "Surface Plot"), row=True, density="compact", color="primary"):
|
|
|
|
| 554 |
def _build_main_plot_area():
|
| 555 |
"""Build the main plot area (PyVista for Simulator)."""
|
| 556 |
with vuetify3.VCard(
|
| 557 |
+
v_if="geometry_selection && ((backend_type !== 'QPU' && !(backend_type === 'Simulator' && selected_simulator === 'Statevector Estimator')) || !qpu_ts_ready)",
|
| 558 |
classes="mb-1 flex-grow-1 d-flex flex-column",
|
| 559 |
style="min-height: 0;",
|
| 560 |
):
|
|
|
|
| 606 |
ctrl.sim_ts_update = sim_ts.update
|
| 607 |
|
| 608 |
# Time slider for surface plot
|
| 609 |
+
with vuetify3.VContainer(v_if="simulation_has_run && output_type === 'Surface Plot' && backend_type !== 'QPU' && !(backend_type === 'Simulator' && selected_simulator === 'Statevector Estimator')", fluid=True, classes="pa-0 mt-2"):
|
| 610 |
vuetify3.VSlider(v_model=("time_val", 0.0), label="Time", min=0, max=("T", 10.0), step=("dt_user", 0.1), thumb_label="always", density="compact", color="primary")
|
| 611 |
|
| 612 |
|
| 613 |
def _build_qpu_plot_area():
|
| 614 |
"""Build the QPU plot area (Plotly time series)."""
|
| 615 |
+
with vuetify3.VCard(v_if="geometry_selection && (backend_type === 'QPU' || (backend_type === 'Simulator' && selected_simulator === 'Statevector Estimator')) && (is_running || qpu_ts_ready)", classes="flex-grow-1", style="min-height: 0;"):
|
| 616 |
# Running indicator
|
| 617 |
with vuetify3.VContainer(v_if="is_running", fluid=True, classes="fill-height d-flex flex-column align-center justify-center"):
|
| 618 |
vuetify3.VProgressCircular(indeterminate=True, size=64, color="primary")
|
| 619 |
+
vuetify3.VCardSubtitle("Running {{ backend_type === 'QPU' ? selected_qpu : selected_simulator }}...", classes="mt-4")
|
| 620 |
|
| 621 |
# QPU timeseries with toolbar
|
| 622 |
with vuetify3.VContainer(v_if="!is_running && qpu_ts_ready", fluid=True, classes="pa-2"):
|
em_embedded.py
CHANGED
|
@@ -581,7 +581,7 @@ def _build_qpu_timeseries_plotly_multi(configs, nx: int, T: float, snapshot_dt:
|
|
| 581 |
|
| 582 |
# Fetch time series from QPU for this field and the validated positions
|
| 583 |
try:
|
| 584 |
-
series_map_field = qutils.
|
| 585 |
except Exception as e:
|
| 586 |
msg = f"QPU error for {field_type} positions {valid_positions}: {e}"
|
| 587 |
if print_callback:
|
|
|
|
| 581 |
|
| 582 |
# Fetch time series from QPU for this field and the validated positions
|
| 583 |
try:
|
| 584 |
+
series_map_field = qutils.run_sve(field_type, valid_positions, None, float(T), float(snapshot_dt), int(nx), None, impulse_pos, progress_callback=_sub_progress, print_callback=print_callback)
|
| 585 |
except Exception as e:
|
| 586 |
msg = f"QPU error for {field_type} positions {valid_positions}: {e}"
|
| 587 |
if print_callback:
|
qlbm/qlbm_sample_app.py
CHANGED
|
@@ -873,20 +873,11 @@ def show_initial_distribution(
|
|
| 873 |
if __name__=="__main__":
|
| 874 |
|
| 875 |
n=3
|
| 876 |
-
|
| 877 |
-
#
|
| 878 |
-
# init_state_name="sin",
|
| 879 |
-
# sine_k_x=1.0,
|
| 880 |
-
# sine_k_y=1.0,
|
| 881 |
-
# sine_k_z=1.0,
|
| 882 |
-
# plot=True,
|
| 883 |
-
# return_data=False
|
| 884 |
-
# )
|
| 885 |
-
|
| 886 |
-
# Step 1: Create the initial state circuit ONCE with all parameters
|
| 887 |
init_state_prep_circ = get_named_init_state_circuit(
|
| 888 |
n=n,
|
| 889 |
-
init_state_name="
|
| 890 |
sine_k_x=1.0,
|
| 891 |
sine_k_y=1.0,
|
| 892 |
sine_k_z=1.0
|
|
@@ -896,36 +887,36 @@ if __name__=="__main__":
|
|
| 896 |
# gauss_sigma=0.2,
|
| 897 |
)
|
| 898 |
|
| 899 |
-
|
| 900 |
-
output, fig = run_sampling_sim(
|
| 901 |
-
|
| 902 |
-
|
| 903 |
-
|
| 904 |
-
|
| 905 |
-
|
| 906 |
-
|
| 907 |
-
|
| 908 |
-
)
|
| 909 |
-
fig.show()
|
| 910 |
|
| 911 |
# Step 2: (Optional) Preview the initial distribution
|
| 912 |
# show_initial_distribution(n=n, init_state_name="sin", sine_k_x=1, sine_k_y=1, sine_k_z=1)
|
| 913 |
|
| 914 |
# Step 3: Run simulation - pass the pre-built circuit
|
| 915 |
-
|
| 916 |
-
|
| 917 |
-
|
| 918 |
-
|
| 919 |
-
|
| 920 |
-
|
| 921 |
-
|
| 922 |
-
|
| 923 |
-
|
| 924 |
-
|
| 925 |
|
| 926 |
-
|
| 927 |
-
|
| 928 |
-
|
| 929 |
|
| 930 |
|
| 931 |
|
|
|
|
| 873 |
if __name__=="__main__":
|
| 874 |
|
| 875 |
n=3
|
| 876 |
+
|
| 877 |
+
# # Step 1: Create the initial state circuit ONCE with all parameters
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 878 |
init_state_prep_circ = get_named_init_state_circuit(
|
| 879 |
n=n,
|
| 880 |
+
init_state_name="sin", # or "gaussian", "dirac_delta"
|
| 881 |
sine_k_x=1.0,
|
| 882 |
sine_k_y=1.0,
|
| 883 |
sine_k_z=1.0
|
|
|
|
| 887 |
# gauss_sigma=0.2,
|
| 888 |
)
|
| 889 |
|
| 890 |
+
# # Alternative: Run on local simulator
|
| 891 |
+
# output, fig = run_sampling_sim(
|
| 892 |
+
# n=n,
|
| 893 |
+
# ux="sin(2*pi*y)*sin(2*pi*z)",
|
| 894 |
+
# uy="sin(2*pi*x)*sin(2*pi*z)",
|
| 895 |
+
# uz="sin(2*pi*x)*sin(2*pi*y)",
|
| 896 |
+
# init_state_prep_circ=init_state_prep_circ,
|
| 897 |
+
# T_list=[1,3,5],
|
| 898 |
+
# vel_resolution=2
|
| 899 |
+
# )
|
| 900 |
+
# fig.show()
|
| 901 |
|
| 902 |
# Step 2: (Optional) Preview the initial distribution
|
| 903 |
# show_initial_distribution(n=n, init_state_name="sin", sine_k_x=1, sine_k_y=1, sine_k_z=1)
|
| 904 |
|
| 905 |
# Step 3: Run simulation - pass the pre-built circuit
|
| 906 |
+
job, get_job_result = run_sampling_hw_ibm(
|
| 907 |
+
n=n,
|
| 908 |
+
ux=lambda x,y,z: 1,
|
| 909 |
+
uy=lambda x,y,z: 1,
|
| 910 |
+
uz=lambda x,y,z: 1,
|
| 911 |
+
init_state_prep_circ=init_state_prep_circ, # Pass the circuit directly
|
| 912 |
+
T_list=[1],
|
| 913 |
+
shots=2**19,
|
| 914 |
+
vel_resolution=2,
|
| 915 |
+
)
|
| 916 |
|
| 917 |
+
output = get_job_result(job)
|
| 918 |
+
for xx, yy, zz, dens in output:
|
| 919 |
+
plot_density_isosurface(xx, yy, zz, dens)
|
| 920 |
|
| 921 |
|
| 922 |
|
utils/delta_impulse_generator.py
CHANGED
|
@@ -375,7 +375,7 @@ def create_impulse_preview_state(preview_n: int, pos01, sigma01: float = 0.02):
|
|
| 375 |
|
| 376 |
|
| 377 |
|
| 378 |
-
#####
|
| 379 |
|
| 380 |
from .base_functions import *
|
| 381 |
|
|
@@ -412,9 +412,10 @@ def create_time_frames(total_time, snapshot_interval):
|
|
| 412 |
|
| 413 |
|
| 414 |
|
| 415 |
-
def
|
| 416 |
-
"""
|
| 417 |
-
|
|
|
|
| 418 |
|
| 419 |
- Single-point (backward compatible): x, y are integers; returns list[float].
|
| 420 |
- Multi-point: x is a list/tuple of (ix, iy) integer pairs and y is None; returns dict[(ix,iy) -> list[float]].
|
|
@@ -487,6 +488,6 @@ def run_qpu(field, x, y, T, snapshot_time, nx, initial_state, impulse_pos, progr
|
|
| 487 |
if progress_callback:
|
| 488 |
progress_callback((idx + 1) / total_frames * 100)
|
| 489 |
|
| 490 |
-
|
| 491 |
|
| 492 |
return series_by_point if multi else series_single
|
|
|
|
| 375 |
|
| 376 |
|
| 377 |
|
| 378 |
+
##### Statevector Estimator Simulation Code Below #####
|
| 379 |
|
| 380 |
from .base_functions import *
|
| 381 |
|
|
|
|
| 412 |
|
| 413 |
|
| 414 |
|
| 415 |
+
def run_sve(field, x, y, T, snapshot_time, nx, initial_state, impulse_pos, progress_callback=None, print_callback=None):
|
| 416 |
+
"""Statevector Estimator for time-series field values.
|
| 417 |
+
|
| 418 |
+
Supports both single-point and multi-point modes.
|
| 419 |
|
| 420 |
- Single-point (backward compatible): x, y are integers; returns list[float].
|
| 421 |
- Multi-point: x is a list/tuple of (ix, iy) integer pairs and y is None; returns dict[(ix,iy) -> list[float]].
|
|
|
|
| 488 |
if progress_callback:
|
| 489 |
progress_callback((idx + 1) / total_frames * 100)
|
| 490 |
|
| 491 |
+
_log("Statevector Estimator simulation completed.")
|
| 492 |
|
| 493 |
return series_by_point if multi else series_single
|