Memodelkan fluida tak-kental yang mengalir menggunakan QUICK-PDE
Qiskit Functions adalah fitur eksperimental yang hanya tersedia untuk pengguna IBM Quantum® Premium Plan, Flex Plan, dan On-Prem (via IBM Quantum Platform API) Plan. Fitur ini masih dalam status rilis pratinjau dan dapat berubah sewaktu-waktu.
Estimasi penggunaan: 50 menit pada prosesor Heron r2. (CATATAN: Ini hanya estimasi. Waktu aktual bisa berbeda.)
Perlu diketahui bahwa waktu eksekusi fungsi ini umumnya lebih dari 20 menit, sehingga kamu mungkin ingin membagi tutorial ini menjadi dua sesi: sesi pertama untuk membaca dan menjalankan job-nya, lalu sesi kedua beberapa jam kemudian (untuk memberi waktu job selesai), guna mengolah hasil dari job tersebut.
Latar Belakang​
Tutorial ini bertujuan memperkenalkan cara menggunakan fungsi QUICK-PDE untuk memecahkan masalah multi-fisika yang kompleks pada QPU Heron R2 156Q menggunakan H-DES (Hybrid Differential Equation Solver) dari ColibriTD. Algoritma yang mendasarinya dijelaskan dalam makalah H-DES. Perlu dicatat bahwa solver ini juga bisa menyelesaikan persamaan non-linear.
Masalah multi-fisika — termasuk dinamika fluida, difusi panas, dan deformasi material, untuk menyebut beberapa — dapat digambarkan secara umum menggunakan Persamaan Diferensial Parsial (PDE).
Masalah-masalah semacam ini sangat relevan di berbagai industri dan merupakan cabang penting dari matematika terapan. Namun, menyelesaikan PDE non-linear multivariat yang tergabung dengan alat klasik tetap menjadi tantangan karena membutuhkan sumber daya yang jumlahnya eksponensial.
Fungsi ini cocok untuk persamaan dengan kompleksitas dan variabel yang semakin besar, dan merupakan langkah pertama untuk membuka kemungkinan-kemungkinan yang sebelumnya dianggap tak terpecahkan. Untuk mendeskripsikan sebuah masalah yang dimodelkan oleh PDE secara lengkap, kita perlu mengetahui kondisi awal dan kondisi batas. Hal-hal ini dapat sangat memengaruhi solusi PDE dan jalur untuk menemukannya.
Tutorial ini mengajarkan cara:
- Mendefinisikan parameter dari fungsi kondisi awal.
- Menyesuaikan jumlah Qubit (yang digunakan untuk mengkodekan fungsi persamaan diferensial), kedalaman, dan jumlah shot.
- Menjalankan QUICK-PDE untuk menyelesaikan persamaan diferensial yang mendasarinya.
Persyaratan​
Sebelum memulai tutorial ini, pastikan kamu sudah menginstal hal-hal berikut:
- Qiskit SDK v2.0 atau lebih baru (
pip install qiskit) - Qiskit Functions Catalog (
pip install qiskit-ibm-catalog) - Matplotlib (
pip install matplotlib) - Akses ke fungsi QUICK-PDE. Isi formulir untuk meminta akses.
Setup​
Autentikasi menggunakan API key kamu dan pilih fungsinya seperti berikut:
# Added by doQumentation — required packages for this notebook
!pip install -q matplotlib numpy qiskit-ibm-catalog
import numpy as np
import matplotlib.pyplot as plt
from qiskit_ibm_catalog import QiskitFunctionsCatalog
catalog = QiskitFunctionsCatalog(
channel="ibm_quantum_platform",
instance="INSTANCE_CRN",
token="YOUR_API_KEY", # Use the 44-character API_KEY you created and saved from the IBM Quantum Platform Home dashboard
)
quick = catalog.load("colibritd/quick-pde")
Langkah 1: Atur properti masalah yang akan diselesaikan​
Tutorial ini membahas pengalaman pengguna dari dua perspektif: masalah fisika yang ditentukan oleh kondisi awal, dan komponen algoritmik dalam menyelesaikan contoh dinamika fluida pada komputer kuantum.
Computational Fluid Dynamics (CFD) memiliki berbagai aplikasi yang luas, sehingga penting untuk mempelajari dan menyelesaikan PDE yang mendasarinya. Salah satu keluarga PDE yang penting adalah persamaan Navier-Stokes, yaitu sistem persamaan diferensial parsial non-linear yang menggambarkan gerak fluida. Persamaan ini sangat relevan untuk masalah ilmiah dan aplikasi rekayasa.
Dalam kondisi tertentu, persamaan Navier-Stokes menyederhanakan menjadi persamaan Burgers' — persamaan konveksi-difusi yang menggambarkan fenomena dalam dinamika fluida, dinamika gas, dan akustik non-linear, antara lain, dengan memodelkan sistem disipasi.
Versi satu dimensi dari persamaan ini bergantung pada dua variabel: yang memodelkan dimensi temporal, dan yang merepresentasikan dimensi spasial. Bentuk umum persamaan ini disebut persamaan Burgers' viskos dan berbunyi:
di mana adalah medan kecepatan fluida pada posisi dan waktu , serta adalah viskositas fluida. Viskositas adalah sifat penting dari sebuah fluida yang mengukur resistansi gerak atau deformasinya yang bergantung pada laju, sehingga memainkan peran krusial dalam menentukan dinamika fluida. Ketika viskositas fluida bernilai nol ( = 0), persamaan ini menjadi persamaan konservasi yang dapat mengembangkan diskontinuitas (gelombang kejut), akibat tidak adanya resistansi internal. Dalam hal ini, persamaan tersebut disebut persamaan Burgers' tak-kental dan merupakan kasus khusus dari persamaan gelombang non-linear.
Secara teknis, aliran tak-kental tidak terjadi di alam, namun saat memodelkan aliran aerodinamika, karena efek transport yang sangat kecil, menggunakan deskripsi tak-kental pada masalah tersebut bisa berguna. Menariknya, lebih dari 70% teori aerodinamika berkaitan dengan aliran tak-kental.
Tutorial ini menggunakan persamaan Burgers' tak-kental sebagai contoh CFD yang diselesaikan pada QPU IBM® menggunakan QUICK-PDE, yang dinyatakan dengan persamaan:
Kondisi awal untuk masalah ini diatur sebagai fungsi linear: di mana dan adalah konstanta bebas yang memengaruhi bentuk solusi. Kamu bisa menyesuaikan dan dan melihat bagaimana pengaruhnya terhadap proses penyelesaian dan solusinya.
job = quick.run(
use_case="cfd",
physical_parameters={"a": 1.0, "b": 1.0},
)
print(job.result())
{'functions': {'u': array([[1. , 0.96112378, 0.9230742 , 0.88616096, 0.85058445,
0.81644741, 0.78376878, 0.75249908, 0.72253689, 0.69374562,
0.66597013, 0.63905258, 0.61284684, 0.58723093, 0.56211691,
0.53745752, 0.51324915, 0.48953036, 0.46637547, 0.44388257,
0.4221554 , 0.40127848, 0.38128488, 0.36211604, 0.34357308,
0.32525895, 0.30651089, 0.28632252, 0.26325504, 0.23533692],
[1.2375 , 1.19267729, 1.14850734, 1.10544526, 1.06382155,
1.02385326, 0.98565757, 0.94926734, 0.91464784, 0.88171402,
0.85034771, 0.82041411, 0.79177677, 0.76431068, 0.73791248,
0.71250742, 0.68805224, 0.66453346, 0.64196021, 0.62035121,
0.59971506, 0.5800232 , 0.56117499, 0.54295419, 0.52497612,
0.50662498, 0.48698059, 0.4647339 , 0.43809065, 0.40466247],
[1.475 , 1.4242308 , 1.37394048, 1.32472956, 1.27705866,
1.23125911, 1.18754636, 1.1460356 , 1.10675879, 1.06968242,
1.03472529, 1.00177563, 0.9707067 , 0.94139043, 0.91370806,
0.88755732, 0.86285533, 0.83953655, 0.81754494, 0.79681986,
0.77727473, 0.75876792, 0.74106511, 0.72379234, 0.70637915,
0.687991 , 0.66745028, 0.64314527, 0.61292625, 0.57398802],
[1.7125 , 1.65578431, 1.59937362, 1.54401386, 1.49029576,
1.43866495, 1.38943515, 1.34280386, 1.29886974, 1.25765082,
1.21910288, 1.18313715, 1.14963664, 1.11847019, 1.08950364,
1.06260722, 1.03765842, 1.01453964, 0.99312968, 0.97328851,
0.95483439, 0.93751264, 0.92095522, 0.90463049, 0.88778219,
0.86935702, 0.84791997, 0.82155665, 0.78776186, 0.74331358],
[1.95 , 1.88733782, 1.82480676, 1.76329816, 1.70353287,
1.6460708 , 1.59132394, 1.53957212, 1.49098069, 1.44561922,
1.40348046, 1.36449867, 1.32856657, 1.29554994, 1.26529921,
1.23765712, 1.21246152, 1.18954273, 1.16871442, 1.14975716,
1.13239406, 1.11625736, 1.10084533, 1.08546864, 1.06918523,
1.05072304, 1.02838966, 0.99996803, 0.96259746, 0.91263913]])}, 'samples': {'t': array([0. , 0.03275862, 0.06551724, 0.09827586, 0.13103448,
0.1637931 , 0.19655172, 0.22931034, 0.26206897, 0.29482759,
0.32758621, 0.36034483, 0.39310345, 0.42586207, 0.45862069,
0.49137931, 0.52413793, 0.55689655, 0.58965517, 0.62241379,
0.65517241, 0.68793103, 0.72068966, 0.75344828, 0.7862069 ,
0.81896552, 0.85172414, 0.88448276, 0.91724138, 0.95 ]), 'x': array([0. , 0.2375, 0.475 , 0.7125, 0.95 ])}}
Langkah 2 (jika diperlukan): Optimalkan masalah untuk eksekusi di perangkat keras kuantum​
Secara default, solver menggunakan parameter yang diinformasikan secara fisik, yaitu parameter sirkuit awal untuk jumlah qubit dan kedalaman tertentu yang menjadi titik awal solver kami.
Shot juga merupakan bagian dari parameter dengan nilai default, karena penyetelannya penting.
Tergantung pada konfigurasi yang ingin kamu selesaikan, parameter algoritma untuk mendapatkan solusi yang memuaskan mungkin perlu disesuaikan; misalnya, bisa membutuhkan lebih banyak atau lebih sedikit qubit per variabel dan , tergantung pada dan . Berikut ini menyesuaikan jumlah qubit per fungsi per variabel, kedalaman per fungsi, dan jumlah shot.
Kamu juga bisa melihat cara menentukan backend dan mode eksekusi.
Selain itu, parameter yang diinformasikan secara fisik bisa mengarahkan proses optimasi ke arah yang salah; dalam kasus itu, kamu bisa menonaktifkannya dengan mengatur strategi initialization ke "RANDOM".
job_2 = quick.run(
use_case="cfd",
physical_parameters={"a": 0.5, "b": 0.25},
nb_qubits={"u": {"t": 2, "x": 1}},
depth={"u": 3},
shots=[500, 2500, 5000, 10000],
initialization="RANDOM",
backend="ibm_kingston",
mode="session",
)
print(job_2.result())
{'functions': {'u': array([[0.25 , 0.24856543, 0.24687708, 0.2449444 , 0.24277686,
0.24038389, 0.23777496, 0.23495952, 0.23194702, 0.22874691,
0.22536866, 0.22182171, 0.21811551, 0.21425952, 0.2102632 ,
0.20613599, 0.20188736, 0.19752675, 0.19306361, 0.18850741,
0.18386759, 0.1791536 , 0.17437491, 0.16954096, 0.16466122,
0.15974512, 0.15480213, 0.1498417 , 0.14487328, 0.13990632],
[0.36875 , 0.36681313, 0.36457201, 0.36203594, 0.35921422,
0.35611615, 0.35275103, 0.34912817, 0.34525687, 0.34114643,
0.33680614, 0.33224532, 0.32747327, 0.32249928, 0.31733266,
0.31198271, 0.30645873, 0.30077002, 0.29492589, 0.28893564,
0.28280857, 0.27655397, 0.27018116, 0.26369944, 0.2571181 ,
0.25044645, 0.24369378, 0.23686941, 0.22998264, 0.22304275],
[0.4875 , 0.48506084, 0.48226695, 0.47912748, 0.47565158,
0.47184841, 0.46772711, 0.46329683, 0.45856672, 0.45354594,
0.44824363, 0.44266894, 0.43683103, 0.43073904, 0.42440212,
0.41782942, 0.4110301 , 0.4040133 , 0.39678818, 0.38936388,
0.38174955, 0.37395435, 0.36598742, 0.35785791, 0.34957498,
0.34114777, 0.33258544, 0.32389713, 0.315092 , 0.30617919],
[0.60625 , 0.60330854, 0.59996188, 0.59621902, 0.59208895,
0.58758067, 0.58270318, 0.57746549, 0.57187658, 0.56594545,
0.55968112, 0.55309256, 0.54618879, 0.53897879, 0.53147158,
0.52367614, 0.51560147, 0.50725658, 0.49865046, 0.48979211,
0.48069053, 0.47135472, 0.46179367, 0.45201638, 0.44203186,
0.4318491 , 0.42147709, 0.41092485, 0.40020136, 0.38931562],
[0.725 , 0.72155625, 0.71765682, 0.71331056, 0.70852631,
0.70331293, 0.69767926, 0.69163414, 0.68518643, 0.67834497,
0.6711186 , 0.66351618, 0.65554655, 0.64721855, 0.63854104,
0.62952285, 0.62017284, 0.61049986, 0.60051274, 0.59022035,
0.57963151, 0.56875509, 0.55759992, 0.54617486, 0.53448874,
0.52255042, 0.51036875, 0.49795257, 0.48531072, 0.47245205]])}, 'samples': {'t': array([0. , 0.03275862, 0.06551724, 0.09827586, 0.13103448,
0.1637931 , 0.19655172, 0.22931034, 0.26206897, 0.29482759,
0.32758621, 0.36034483, 0.39310345, 0.42586207, 0.45862069,
0.49137931, 0.52413793, 0.55689655, 0.58965517, 0.62241379,
0.65517241, 0.68793103, 0.72068966, 0.75344828, 0.7862069 ,
0.81896552, 0.85172414, 0.88448276, 0.91724138, 0.95 ]), 'x': array([0. , 0.2375, 0.475 , 0.7125, 0.95 ])}}
Langkah 3: Bandingkan performa algoritma​
Kamu bisa membandingkan proses konvergensi solusi kami (HDES) dari job_2 dengan performa algoritma dan solver physics-informed neural networks (PINN) (lihat paper dan repositori GitHub terkait).
Pada contoh output job_2 (pendekatan berbasis kuantum), hanya 13 parameter (12 parameter sirkuit ditambah 1 parameter penskalaan) yang dioptimalkan dengan solver klasik. Proses konvergensinya adalah sebagai berikut:
optimizers:
CMA: {'ftarget': np.float64(0.1), 'verb_disp': 10, 'maxiter': 100}
CMA: {'ftarget': np.float64(0.005), 'verb_disp': 10, 'maxiter': 20}
CMA: {'ftarget': np.float64(0.0025), 'verb_disp': 10, 'maxiter': 30}
CMA: {'ftarget': np.float64(0.0005), 'verb_disp': 10, 'maxiter': 10}
500 shots
================== CMA =================
option: {'ftarget': np.float64(0.1), 'verb_disp': 10, 'maxiter': 100}
0/100, loss: 0.02456641
1000 shots
================== CMA =================
option: {'ftarget': np.float64(0.005), 'verb_disp': 10, 'maxiter': 20}
0/20, loss: 0.03641833
1/20, loss: 0.02461719
2/20, loss: 0.0283689
3/20, loss: 0.009898383
4/20, loss: 0.04454522
5/20, loss: 0.007019971
6/20, loss: 0.00811147
7/20, loss: 0.01592619
8/20, loss: 0.00764708
9/20, loss: 0.01401516
10/20, loss: 0.01767467
11/20, loss: 0.01220387
5000 shots
================== CMA =================
option: {'ftarget': np.float64(0.0025), 'verb_disp': 10, 'maxiter': 30}
0/30, loss: 0.01024792
1/30, loss: 0.004343748
2/30, loss: 0.01450951
3/30, loss: 0.008591284
4/30, loss: 0.00266414
5/30, loss: 0.007923613
6/30, loss: 0.02023853
7/30, loss: 0.01031438
8/30, loss: 0.009513116
9/30, loss: 0.008132266
10/30, loss: 0.005787766
11/30, loss: 0.00390582
10000 shots
================== CMA =================
option: {'ftarget': np.float64(0.0005), 'verb_disp': 10, 'maxiter': 10}
0/10, loss: 0.002386168
1/10, loss: 0.004024823
2/10, loss: 0.001311999
3/10, loss: 0.003433991
4/10, loss: 0.002339664
5/10, loss: 0.002978438
6/10, loss: 0.005458391
7/10, loss: 0.002026701
8/10, loss: 0.00207467
9/10, loss: 0.001947627
final_loss: 0.00151994463476429
Artinya, loss di bawah 0,0015 bisa dicapai setelah 28 iterasi, dan dengan mengoptimalkan hanya sedikit parameter klasik.
Sekarang kita bisa membandingkannya dengan solusi PINN menggunakan konfigurasi default yang disarankan paper dengan optimizer berbasis gradien. Setara dengan sirkuit kita yang memiliki 13 parameter untuk dioptimalkan adalah jaringan saraf, yang membutuhkan setidaknya delapan lapisan berisi 20 neuron, sehingga melibatkan optimasi 3021 parameter. Kemudian, target loss tercapai pada Langkah 315, loss: 0.0014988397.

Sekarang, karena kita ingin melakukan perbandingan yang adil, kita harus menggunakan optimizer yang sama di kedua kasus. Jumlah iterasi terendah yang kami temukan untuk 12 lapisan berisi 20 neuron = 4701 parameter:
(10_w,20)-aCMA-ES (mu_w=5.9,w_1=27%) in dimension 4701 (seed=351961)
Iterat #Fevals function value axis ratio sigma min&max std t[m:s]
1 20 5.398521572351456e-02 1.0e+00 9.98e-03 1e-02 1e-02 0:02.3
2 40 5.444650724530220e-02 1.0e+00 9.97e-03 1e-02 1e-02 0:05.1
3 60 4.447407275438309e-02 1.0e+00 9.95e-03 1e-02 1e-02 0:08.2
4 80 2.068969979882240e-02 1.0e+00 9.94e-03 1e-02 1e-02 0:11.7
6 120 1.028892211616039e-02 1.0e+00 9.91e-03 1e-02 1e-02 0:20.1
7 140 5.140972323715687e-03 1.0e+00 9.90e-03 1e-02 1e-02 0:25.4
9 180 3.811701666563749e-03 1.0e+00 9.87e-03 1e-02 1e-02 0:37.4
10 200 3.189878538250923e-03 1.0e+00 9.85e-03 1e-02 1e-02 0:44.2
12 240 2.547040116041899e-03 1.0e+00 9.83e-03 1e-02 1e-02 0:59.7
14 280 2.166548743844032e-03 1.0e+00 9.80e-03 1e-02 1e-02 1:18.0
15 300 1.783065614290535e-03 1.0e+00 9.79e-03 1e-02 1e-02 1:28.4
16 320 2.045844215899706e-03 1.0e+00 9.78e-03 1e-02 1e-02 1:39.8
Stopping early: loss 0.001405 <= target 0.0015
CMA-ES finished. Best loss: 0.001404788694344461
Kamu bisa melakukan hal yang sama dengan data dari job_2, dan membuat plot perbandingan dengan solusi PINN.
# check the loss function and compare between the two approaches
print(job_2.logs())
Langkah 4: Gunakan hasilnya​
Dengan solusi yang kamu miliki, kamu bisa memilih apa yang ingin dilakukan dengannya. Berikut ini menunjukkan cara membuat plot hasilnya.
solution = job.result()
# Plot the solution of the second simulation job_2
_ = plt.figure()
ax = plt.axes(projection="3d")
# plot the solution using the 3d plotting capabilities of pyplot
t, x = np.meshgrid(solution["samples"]["t"], solution["samples"]["x"])
ax.plot_surface(
t,
x,
solution["functions"]["u"],
edgecolor="royalblue",
lw=0.25,
rstride=26,
cstride=26,
alpha=0.3,
)
ax.scatter(t, x, solution, marker=".")
ax.set(xlabel="t", ylabel="x", zlabel="u(t,x)")
plt.show()

Perhatikan perbedaan kondisi awal untuk simulasi kedua dan pengaruhnya terhadap hasil:
solution_2 = job_2.result()
# Plot the solution of the second simulation job_2
_ = plt.figure()
ax = plt.axes(projection="3d")
# plot the solution using the 3d plotting capabilities of pyplot
t, x = np.meshgrid(solution_2["samples"]["t"], solution_2["samples"]["x"])
ax.plot_surface(
t,
x,
solution_2["functions"]["u"],
edgecolor="royalblue",
lw=0.25,
rstride=26,
cstride=26,
alpha=0.3,
)
ax.scatter(t, x, solution_2, marker=".")
ax.set(xlabel="t", ylabel="x", zlabel="u(t,x)")
plt.show()

Survei tutorial​
Luangkan waktu sebentar untuk memberikan masukan tentang tutorial ini. Pendapatmu akan membantu kami meningkatkan konten dan pengalaman pengguna:
Note: This survey is provided by IBM Quantum and relates to the original English content. To give feedback on doQumentation's website, translations, or code execution, please open a GitHub issue.