محتوای این نوشته تجربیاتی هست که در عمل، حین نوشتن کتابخانه BFE با اون روبرو شدم. دوست داشتم اون رو برای دیگران بنویسم شاید جالب باشه و ایده بده به بقیه. هدف کلی، آشنایی بیشتر خوانندهی عزیز با روند و نکات مهم هنگام نوشتن یک برنامه المانمحدود هست. در این نوشته ها هدف این هست که خواننده بیشتر با مسایل حین ساخت کتابخانهی اجزا محدود آشنا بشه. سری بعدی نوشته ها در مورد این خواهد بود که کاربر درنهایت بتواند از اون در برنامهی خودش استفاده کنه و برنامه جدیدی بسازه یعنی موارد عملی و نه تئوری. و هم به مهندسی نرمافزار و علم اِلِمانمحدود و برنامهنویسی مرتبط هست ولی بیشتر سعی شده برای مهندسین عمران و مکانیک باشه تا راهشون رو به دنیای مهندسی نرمافزار باز کنه و آشناشون کنه.
این سری پستها نه به موارد ابتدایی المانمحدود و نه به موارد ابتدایی برنامهنویسی، کاری نداره! و شما دوست عزیز و خوانندهی گرامی باید از قبل در این دو مورد، پیشزمینهی کافی داشته باشید. حتی اگر یک برنامه کوچک در حد پروژهی درسی اجزامحدود مقطع ارشد یا تحلیل ماتریسی سازههای مقطع کارشناسی رو هم نوشته باشن که خیلی بهتره. فکر میکنم علیالخصوص برای کسی یا گروهی که بخواد یک برنامه المانمحدود از صفر بنویسه مفید خواهد بود.
فهرست نوشتههای مرتبط (بخاطر ایراد در ادیتور ویرگول نشد لینکها رو درست قرار بدم)
۰ - کلیات (همین پست)
۱ - انتخاب زبان برنامهنویسی (لینک)
۲ - ماتریس خلوت (لینک)
۳- تحلیل شیگرایی: قسمت اول (لینک)
۴- تحلیل شیگرایی: قسمت دوم (لینک)
برای نوشتن نرم افزارهای محاسباتی مثل نرم افزارهای المان محدود معمولا از زبانهای برنامه نویسی که نزدیک تر به سطح متوسط (Mid Level) هستن، مثل C و Fortran و ++C استفاده میشه و دلیلش هم اینه که سرعت بالاتری دارن و دست برنامه نویس رو بازتر میگذارن تا از تمام قابلیت های سخت افزار استفاده کنه. بعنوان مثال برنامههای OpenSees، Elmer، DealII، OOFEM و ... بیشتر از این گروه زبانها استفاده میکنن (لیست بزرگتر را از اینجا ببینید: https://en.wikipedia.org/wiki/List_of_finite_element_software_packages)
کار کردن با این زبانها پیچیدگی خاص خودش رو داره، یعنی اگر چه سرعت بالاتری دارند ولی از طرف دیگه هزینه هایی هم دارند، علی الخصوص برای یک مهندس عمران :) یعنی برای استفاده کامل باید با یک سری مفاهیم سخت افزاری هم آشنا باشیم. مثلا Pointer در ++C که به مفهوم آدرس حافظه و این چیزها مربوط میشه، یا SIMD برای افزایش سرعت محاسبات یا چیزهایی از این قبیل. از طرف دیگه سرعت برنامه های محاسباتی ملاحظات دیگری هم داره، که با اون ملاحظات میشه مثلا برنامه هایی که با زبان #C یا پایتون نوشته میشن رو به سرعت برنامه های ++C نزدیکتر کرد. مهمترین این ملاحظات استفاده از الگوریتمها و روشهای متناسب مشکل هست که در پست مربوطه بیشتر بهش پرداخته شده.
بعضی نکات هست که بعنوان ملاحظات کلی، در همه ی قسمتها باید رعایت بشن تا برنامه بتونه سرعت بالایی داشته باشه. با استفاده از این نکات به طور کلی به پیچیدگی برنامه اضافه میشه ولی مشکلات و محدودیتهای اصلی ای که بهشون بر میخوریم رو حل میکنیم. البته با پیشرفت روز افزون صنعت سخت افزار رایانه میشه پیش بینی کرد بعضی چیزهایی که الان برای ما محدودیت هستند، در چند سال یا چند ده سال آینده محدودیت نخواهند بود. مثلا سرعت کامپیوترهای در دسترس عموم از 20 سال پیش تابحال چیزی حدود صدهزار برابر شده. یعنی رایانه ای که الان میخریم 500 دلار، صد هزار برابر رایانه ی 500 دلاری 20 سال پیش محاسبات بیشتری انجام میده (منبع). پس ممکنه خیلی چیزهایی که الان برای ما محدودیت هست، تا 20 سال آینده دیگه محدودیت نباشه. مثلا شاید 100 ترابایت رم خیلی معمول باشه و ما (نسل بعدی ما) دیگه مجبور نباشیم الکی به پیچیدگیهای برناممون اضافه کنیم.
خوب روش اجزا محدود از ماتریسها خیلی استفاده میکنه. تغریبا عضو ناگسستنی یک پکیج اجزامحدود، یک کتابخانهی ماتریس خوب هست. از ساخت ماتریس سختی کل تا ماتریس سختی تکتک اجزا همه در قالب ماتریس هستن. ماتریس ها رو میشه به دو دسته تقسیم کرد: ماتریس خلوت و ماتریس ثقیل. هرکدوم برای مقصد خاصی استفاده میشن و تفاوت بین کاربرد این دو ماتریس تعداد درایههای صفر و غیر صفرشون هست. ماتریس سختی یک مدل اجزا محدود یک ماتریس مربعی هست (ماتریس مربعی: تعداد سطرهاش و ستونهاش برابره مثل مربع). ابعاد این ماتریس برابر تعداد درجات آزادیمون هست. فرضا یک مدل با ۱میلیون درجهی آزادی ماتریس سختی خیلی بزرگی خواهد داشت که تعداد درایههاش برابر یک میلیون به توان دو هست. ما باید این ماتریس رو توی حافظهی فرّار رایانه (یا همون RAM) نگه داری کنیم. چندین سال پیش که مقدار RAM در دسترس کمتر بود این رو توی هارد نگه داری میکردند چون ممکنه حجم زیادی نیاز داشته باشه. چون اکثر درایههای ماتریس سختی مون معمولا برابر صفر هستن، ما بجای اینکه همه درایهها رو نگه داری کنیم فقط اونهاییش که غیر صفر هستن رو نگه میداریم. گام بعدی حل دستگاه معادلات خلوت هست که پیچیدگیهای خودش رو داره که در پست مربوطه بهش مفصل تر پرداخته میشه.
این مرحله قابل مقایسه با طراحی معماری یک خونه هست. یعنی قبل از ساخت، کلیات نقشه پلان طبقات و برخی جزییاتش کشیده میشه. توی تحلیل شی گرا هم همینطور. اول بهتره کلیت ورودی و خروجی و کاری که برنامه قراره انجام بده رو برای خودمون تشریح کنیم.
بطور کلی میشه کلاسهامون رو به دو قسمت تقسیم کنیم. کلاسهایی که اطلاعات رو نگه داری میکنن، مانند مدول الاستیسیتهی یک عضو، یا مکان یک گره در سه بعد. و کلاسهایی که برامون محاسبات رو انجام میدن. مثل محاسبات ماتریس سختی و سوار کردن ماتریس سختی کل یا حذف سطر و ستونهای متناظر با درجات مقید و غیره. یک برنامهی المان محدود مقدار قابل توجهی کدهای محاسباتی داره و باید در سازماندهی این کدها دقت کنیم وگرنه برای دیباگ کردن و نگه داری کد با مشکل مواجه خواهیم شد.