ترى في الإطار أعلاه محاكاة حاسوبية لفيزياء النوابض وهي تعمل بالكامل في متصفحك. يمكنك التفاعل معها باستخدام الماوس لتغيير منظور الكاميرا أو تعديل مدخلات المحاكاة. يمكنك كذلك فتح المحاكاة في صفحة جديدة باتباع هذا الرابط. الكود المصدري كاملا موجود هنا.
المحاكاة الحاسوبية (Computer Simulation) أداة قوية تُستخدم في مختلف التخصصات لفهم سلوك الأنظمة المعقدة والتنبؤ به. فمن خلال إنشاء نماذج رياضية أو حسابية، يمكننا استكشاف سيناريوهات صعبة أو مكلفة أو حتى مستحيلة الدراسة في العالم الحقيقي. من الفيزياء والهندسة إلى عالم المال والرعاية الصحية، توفر المحاكاة رؤى تساعدنا على التصميم والتحسين واتخاذ قرارات مستنيرة.
تسمح لنا المحاكاة بتقريب الواقع من خلال التقاط الديناميكيات الرئيسية للنظام المراد دراسته. وسواءً كانت هذه الديناميكيات تمثل حركة الأجرام السماوية أو انتشار الأمراض أو تدفق حركة المرور، فإن المحاكاة تعتمد على المعادلات الرياضية لنمذجة التفاعلات والقوى المؤثرة. ومن خلال حل هذه المعادلات بشكل متكرر، يمكننا مراقبة كيفية تطور النظام بمرور الوقت والتحقيق في تأثير التغييرات التي تطرأ على بارامتراته أو ظروفه.
في هذا المقال سنقدم شرحا مبسطا لمبادئ المحاكاة الحاسوبية من خلال بناء البرنامج الموجود في أعلى الصفحة والذي يحاكي حركة كتلة متربطة بنابض ومخمّد. نظام الـ”كتلة-نابض-مخمد” (Mass-spring-damper)، هو نموذج كلاسيكي مبسط يُستخدم لدراسة الحركة التذبذبية التخامدية. لا يشكل هذا النظام أساسًا للعديد من التطبيقات الواقعية فحسب، مثل أنظمة تعليق المركبات وتصاميم المباني، بل يوفر أيضًا نقطة انطلاق غنية لفهم مبادئ المحاكاة الديناميكية.
نظام الكتلة – نابض – مخمد
تتمثل الخطوة الأولى في بناء أي محاكاة بتوصيف المشكلة بشكل دقيق حيث يجب تحديد النظام المراد محاكاته والمتغيرات المراد دراسة تأثيرها على سلوك النظام (المدخلات) والمتغيرات المراد قياسها (المخرجات). في المحاكاة الحالية، نريد دراسة حركة جسم فيزيائي كلاسيكي مرتبط بنابض ومخمد.
النابض (أو الزنبرك) هو جهاز يخزن الطاقة ويطلقها عن طريق التمدد أو الانضغاط. وهو يعمل مثل الشريط المطاطي – فعندما تسحبه يتمدد، وعندما تتركه يعود إلى شكله الأصلي. تتواجد الزنبركات في كل مكان في حياتنا اليومية، حيث تساعد على امتصاص الصدمات وتخزين الطاقة وإعادة الأجسام إلى وضعها الأصلي. بالمقابل فإن المخمّد هو جهاز يقاوم الحركة عن طريق امتصاص الطاقة وتقليل الاهتزازات. تعمل المخمّدات مثل الوسادة التي تبطئ الأشياء عندما تتحرك بسرعة كبيرة وتدفعها نحو التوقف.
في هذه المحاكاة سوف نتجاهل شكل الجسم وأبعاده فيما يعرف بمصطلح “الجسيم النقطي“. كذك سنفترض أن النابض مثالي أي أن قوته الإرجاعية تتناسب طردا مع الاستطالة وهو مايعرف بـ”قانون هوك“. على أرض الواقع فإن هذا مجرد تقريب يصلح ضمن حدود معينة فجميع النوابض لها حد معين من الاستطالة تفقد بعدها هذه الخواص المثالية ويمكن أن تتشوه بشكل غير قابل للإصلاح. بشكل مشابه سنفترض أن المخمد يعمل بشكل مثالي وأن قوته التخامدية تتناسب طردا مع سرعة الجسيم المرتبط.
هذه الافتراضات المثالية، توضح النقطة المهمة التالية في أي محاكاة حاسوبية. المحاكاة هي دائما تقريب للواقع وليست نسخة طبق الأصل عنه. فهي تعتمد على النماذج الرياضية والافتراضات والتمثيلات المبسطة، مما يعني أنها لا يمكنها أبدًا التقاط كل تفاصيل العالم الحقيقي. يمكننا دائما تحسين النموذج المستخدم وإضافة معاملات جديدة إلى المحاكاة ولكن يبقى هنالك دائمًا عوامل لا يمكن التقاطها بشكل كامل بغض النظر عن مدى تقدم النموذج، ويجب على المستخدم أن يكون على دراية بمحدوديته.
وفق الافتراضات سابقة الذكر، يمكننا تحديد مدخلات هذه المحاكاة بالمعاملات التالية:
- كتلة الجسيم المرتبط بالنابض ولنرمز له بالحرف \(m\).
- ثابت صلابة النابض \(k\): يمثل القوة الإرجائية للنابض ويعتمد على خواصه الفيزيائية (بنيته والمادة المصنوع منها). يتم عادة قياس هذا الثابت عن طريق التجربة العمليّة.
- ثابت التخميد \(c\) : يمثل القوة التخميدية للمخمد وكذلك يعتمد على خواصه الفيزيائية ويقاس بالتجربة.
- الانزياح المبدئي \(x_0\): تمثل مقدار استطالة النابض عن وضعه الأصلي في بداية المحاكاة.
المخرج الأساسي لهذه المحاكاة هو موضع الجسيم \(x(t)\) في لحظة زمنية ما \(t\). من الممكن أن يكون هدف المحاكاة هو حساب العديد من المتغيرات الأخرى مثل سرعة الجسيم \(v(t)\) أو طاقته ولكننا هنا سنتكفي بالتركيز على دراسة موضع الجسيم.
من أجل التبسيط، سنأخذ كمبدأ للإحداثيات مكان ارتباط الجسيم بالنابض في وضعه الأصلي، وبالتالي فإن الانزياح المبدئي \(x_0\) يمثل موضع الجسيم \(x\) في اللحظة \(t=0\). كذلك سنفترض أن الجسم يبدأ من السكون في بداية المحاكاة، أي أن سرعته الابتدائية معدومة.
النموذج الرياضي
الخطوة التالية في بناء المحاكاة هي تحديد النموذج الرياضي الذي يحكم تطور النظام التي تم محاكاته عبر الزمن. بالنسبة للجسيمات النقطية يشكل قانون نيوتن الثاني حجر الأساس الذي يحكم فيزياء هذه الجسيمات ويسمح لنا بحساب حركتها من خلال تحديد القوى المؤثرة بها.
يخضع الجسيم في محاكاتنا لقوتين: الأولى هي القوة الأرجاعية للنابض والتي تتناسب طردا مع الاستطالة وبالتالي تتناسب طردا مع موضع الجسيم \(x\). معامل التناسب هو ثابت الصلابة \(k\) و جهة القوة هي بجهة معاكسة للموضع لأنها تسعى دائما لإعادة الجسيم إلى موضعه الأصلي. القوة الثانية هي التخميد والتي تتناسب طردا مع سرعة الجسيم \(v\) بمعامل تناسب هو ثابت التخميد. جهة قوة التخميد معاكسة لجهة السرعة لأنها تسعى لإبطاء الجسيم. بناءاً على ذلك، فإن القوى المؤثرة في الجسيم \(F\) في أي لحظة زمنية \(t\) هي: $$ F(t) = -k\ x(t)\ – c\ v(t) $$
حسب قانون نيوتن الثاني فإن هذه القوى المؤثرة في الجسيم تسبب تسارعاً \(a\) يتناسب عكسا مع كتلته: $$ a(t) = F(t)/m $$
يمثل التسارع التغير الآني في سرعة الجسيم \(v\)، ويُعبّر عنه رياضيا كمشتق السرعة بالنسبة للزمن: $$ a(t) = \frac{dv}{dt} $$ كذلك تمثل السرعة التغير الآني في موضع الجسم \(x\) وبالتالي فهي مشتق الموضع بالنسبة للزمن: $$ v(t) = \frac{dx}{dt} $$
تعطي المعادلات الأربعة أعلاه، بالإضافة إلى الموضع المبدئي للجسيم \(x(0)=x_0\) وسرعته الابتدائية \(v(0)=0\)، توصيفا رياضيا كاملا لديناميكية النظام في هذه المحاكاة. يدعى هذه النوع من المعادلات بـ”المعادلات التفاضلية” نتيجة لاحتوائها على معامل التفاضل (المشتق). من أجل حل هذه المعادلات على الحاسوب، فإننا بحاجة إلى صيغة تقريبة تسمح لنا بتمثيل معامل التفاضل حاسوبيا ولو بشكل تقريبي.
التقريب الحسابي للمعادلات التفاضلية
يمثل المشتق في لحظة ما التغير المتناهي في الصغر في قيمة التابع خلال فترة زمنية متناهية في الصغر حول هذه اللحظة. يمكننا تقريب هذه القيمة بالفرق بين قيمة هذا التابع في اللحظة الحالية وقيمته في لحظة لاحقة قريبة منها: $$ \frac{dx}{dt} \approx \frac{x(t+\Delta t)\ – x(t)}{\Delta t} $$ وتزداد دقة هذا التقريب كلما قصرت الفترة الزمنية \(\Delta t\) بين اللحظتين.
بشكل عام، تدعى هذه الطريقة في تقريب المشتق بـ”الفروق المحدودة“(Finite Diffrences)، ولها أنواع عديدة تختلف حسب عدد قيم التابع المستخدمة في صيغة التقريب و اللحظات الزمنية التي تم تقييم التابع عندها. الصيغة التي استخدمنها هنا، وتدعى بـ”الفروق الأمامية من الدرجة الأولى” (First-oder Forward Difference)، تعتبر من أبسط الصيغ حيث تحتوي فقط قيمتين للتابع إحداها في اللحظة الحالية والأخرى في لحظة لاحقة.
سنقوم بإعادة ترتيب هذه الصيغة بشكل أكثر ملائمة لاستخدامها في حل المعادلات التفاضلية: $$ x(t+\Delta t) \approx x(t) + \frac{dx}{dt} \Delta t $$ يدعى هذا الشكل بـ”صيغة أويلر الصريحة من الدرجة الأولى” (First-order Explicit Euler Formula) وهي تعبر عن قيمة التابع في اللحظة التالية بدلالة قيمته في اللحظة الحالية وقيمة المشتق.
بمساعدة هذه الصيغة يمكننا الأن كتابة معادلات النموذج الرياضي بالشكل التالي المناسب للمحاكاة الحاسوبية:
$$ \begin{align} F(t) &= -k\ x(t)\ – c\ v(t) \tag{Eq. 1}\\ a(t) &= F(t)/m \tag{Eq. 2} \\ v(t+\Delta t) &\approx v(t) + a(t) \Delta t \tag{Eq. 3} \\ x(t+\Delta t) &\approx x(t) + v(t) \Delta t \tag{Eq. 4} \end{align}$$ يسمح هذا الشكل بحساب تقريبي لموضع الجسيم وسرعته في لحظة زمنية لاحقة بدلالة قيمتهم في لحظة زمنية سابقة قريبة منها.
يزداد خطأ التقريب في حساب الموضع والسرعة في اللحظة الجديدة كلما ازدات الفترة الزمنية الفاصلة بين اللحظتين \(\Delta t\). ولكن ماذا لو أردنا محاكاة النظام لفترة زمنية طويلة؟ عندها فإننا بحاجة لتقسيم هذه الفترة الطويلة إلى خطوات زمنية قصيرة جدا وتطبيق المعادلات بشكل متكرر. تعتمد دقة المحاكاة على طول الخطوة الزمنية القصيرة، وبالتالي فإن زيادة دقة المحاكاة تتطلب عدد أكبر من الخطوات الحسابية.
الكود البرمجي للمحاكاة الفيزيائية
فيما يلي كود برمجي مبسط لمحاكاة نظام الكتلة-نابض -مخمد وفق المعادلات السابقة باستخدام لغة JavaScript:
class MassSpringDamperPhysics {
constructor(mass, stifness, dampness, displacement) {
this.mass = mass;
this.stifness = stifness;
this.dampness = dampness;
this.position = displacement;
this.velocity = 0;
}
advance(elapsedTime) {
const maxTimeStep = 0.01;
let timeStep;
while (elapsedTime > 0) {
if (elapsedTime > maxTimeStep) {
timeStep = maxTimeStep;
elapsedTime -= maxTimeStep;
} else {
timeStep = elapsedTime;
elapsedTime = 0;
}
var force = -this.stifness * this.position - this.dampness * this.velocity; //Eq. 1
var acceleration = force / this.mass; //Eq. 2
this.velocity += acceleration * timeStep; //Eq. 3
this.position += this.velocity * timeStep; //Eq. 4
}
}
}
لدينا هنا صف برمجي (class) يمثل حالة النظام في أي لحظة. نخزن في المتحولات: mass, stifness, dampness
مدخلات المحاكاة: الكتلة \(m\)، الصلابة \(k\)، التخميد \(c\). بينما نخزن في المتحولات position, velocity
موضع الجسيم \(x\) الحالي وسرعته \(v\) ونقوم بتهيئتها وفق الشروط الابتدائية، أي تهيئة الموضع بمدخل المحاكاة displacment
والذي يمثل الانزياح المبدئي \(x_0\)، وتهيئة السرعة بالقيمة صفر. لاحظ أننا لم نقم بتخزين التسارع والقوى بشكل دائم لأننا يمكننا دائما حسابهم من الموضع والسرعة وفق المعادلتين (Eq. 1-2).
يمتلك هذا الصف البرمجي تابع advance
يقوم بتحديث موضع وسرعة الجسيم بعد مرور فترة زمنية elapsedTime
. كما ذكرنا سابقا فإننا لانستطيع تطبيق المعادلتين (Eq. 3-4) إلا اذا كانت تلك الفترة الزمنية قصيرة جدا، لذلك فإننا نستخدم حد أعلى للخطوة الزمنية maxTimeStep
ونقوم بتطبيق المعادلات بشكل متكرر باستخدام هذه الخطوة الزمنية المحدودة. في كل تكرار نقوم بتقليص الزمن المتبقي وفق هذه الخطوة، وعندما يصبح الزمن المتبقي أصغر من الحد أعلى للخطوة الزمنية، نقوم باستخدامه بشكل مباشر.
التمثيل المرئي
يسمح الكود البرمجي السابق بحساب موضع الجسيم في أي لحظة زمنية من خلال استدعاء التابع advance
مرة واحدة أو أكثر وقراءة قيمة المتحول position
. في معظم التطبيقات العملية فإن هدف المحاكاة هو فقط حساب مثل هذه القيم واستخدامها في مكان أخر مثل مقارنتها مع التجربة أو استخدامها في حسابات لاحقة. ولكن في كثير من الأحيان، نريد تمثيل بصري لهذه البيانات يسمح لنا بفهم أعمق لسلوك النظام قيد المحاكاة. تدعى هذه الخطوة بـ”التمثيل المرئي” (Visulatization).
من أبسط أشكال التمثيل المرئي هو رسم مخطط بياني يربط متغيرات المحاكاة مع بعضها. في المحاكاة الحالية، يتمثل ذلك بمخطط يوضح موضع الجسيم \(x(t)\) في لحظات زمنية مختلفة \(t\):
هنالك تقنيات أكثر تعقيدا في التمثيل المرئي مثل تقنية التحريك الحاسوبي (Computer Animation) المستخدمة في البرنامج الموجود في أعلى الصفحة. في هذه التقنية يتم بناء نموذج ثنائي أو ثلاثي الأبعاد وتحريكه وفق مخرجات المحاكاة الفيزيائية من أجل توليد صور متحركة تظهر النظام المراد محاكاته بشكل واقعي.
الكود البرمجي للتحريك الحاسوبي
من أجل بناء المحاكاة التفاعلية أعلاه، قمنا باستخدام مكتبة threejs البرمجية للنمذجة ثلاثية الأبعاد.شرح أساسيات كيفية استخدام هذه المكتبة وبناء النموذج ثلاثي الأبعاد يتجاوز نطاق هذه المقالة ولكن بامكانك التحقق من الكود المصدري بالكامل هنا. سنركز فيما يلي على مقتطف من الكود البرمجي يوضح بعض النقاط الأساسية الشائعة في مثل برامج التحريك الحاسوبي هذه القائمة على الفيزياء:
// Create the physics simulator with some initial parameters
const params = { mass: 0.5, stifness: 5.0, dampness: 0.0, displacement: 2.0 };
let simulation = new MassSpringDamperPhysics(params.mass, params.stifness, params.dampness, params.displacement);
//Create the 3D model and add it to the scene
const model = createMassSpring3DModel();
scene.add(model);
// Create a clock to keep track of simulation time
const clock = new THREE.Clock();
// The animate function will be called every frame
function animate() {
// Advance the simulation based on the time elapsed since the last frame
simulation.advance(clock.getDelta());
// Update the model's stretch based on the particle's position
model.setStretch(simulation.position);
// Update the camera controls and render the scene
cameraControls.update();
renderer.render(scene, camera);
}
// Setup the animation loop
renderer.setAnimationLoop(animate);
بداية نقوم بانشاء المحاكي الفيزيائي الذي طورناه في قسم سابق وتهيئته بمدخلات المحاكاة. ثم سنقوم بانشاء النموذج ثلاثي الأبعاد للنابض والجسيم وإضافته إلى المشهد. كذلك سنقوم باستخدام ساعة من أجل تتبع وقت المحاكاة ومزامنتها مع الوقت الحقيقي.
في أي مكتبة للتحريك الحاسوبي، هنالك حلقة مستمرة يتم خلالها استدعاء تابع برمجي بشكل دوري من إعادة رسم الصورة الظاهرة على الشاشة. السطر 23 في الكود يخبر مكتبة threejs أن هذا تابع هو animate
.
ضمن التابع البرمجي animate
، نقوم باستدعاء التابع advance
للمحاكاة الفيزيائية ونمرر كمعامل له المدة الزمنية المنقضية منذ أخر تحديث للصورة حيث يقوم هذا الاستدعاء بتحديث موضع الجسيم في المحاكاة الفيزيائية. باستخدام هذا الموضع الجديد نقوم بتحديث النموذج ثلاثي الأبعاد عن طريق استدعاء التابع setStretch
والذي يقوم بالإجراءات اللازمة لتعديل شكل النموذج بحيث يعكس استطالة النابض ومكان الجسيم الجديدين. أخيرا نقوم باستدعاء توابع من مكتبة threejs من أجل تحديث إحداثيات الكاميرا في المشهد وفق تفاعل المستخدم وإعادة رسم المشهد.
ماذا بعد؟
نظام الكتلة-نابض-مخمد هو أكثر من مجرد بناء نظري، فهو بوابة لفهم الحركة الديناميكية في مختلف التخصصات. يمكن تعميم المحاكاة السابقة في اتجاهات مختلفة. فيمكن مثلا إضافة معاملات أخرى للنموذج الفيزيائي تأخذ بعين الاعتبار السلوك اللاخطي للنوابض الحقيقية. يمكن كذلك استخدام طرق عددية أخرى تختلف عن صيغة أويلر الصريحة من أجل إجراء الحسابات بشكل أكثر دقة. يمكنك أيضا استخدام المحاكاة السابقة كحجر أساس لدراسة سلوك أنظمة أكثر تعقيدا مثل محاكاة مجموعة من الجسيمات المترابطة فيما بينها بالنوابض، والتي لها تطبيقات عملية عديدة بدءا من التحريك الحاسوبي للأقشمة وانتهاء بنماذج تشوهات الهياكل تحت الأحمال.
الخطوة التالية؟ قم تنفيذ المحاكاة الخاصة بك بلغتك البرمجية المفضلة ومعرفة كيف يتفاعل النظام في ظل ظروف مختلفة.