# شيفرة برنامج بسيط لحل الجوائز الشبكية المستوية Truss



## عبد الجواد (6 ديسمبر 2009)

السلام عليكم:

بناءً على رسالة من أحد الإخوة، تذكرت أني كنت قد كتبت برنامجاً -منذ عشر سنوات تقريباً- لحل الجوائز الشبكية المستوية بأسلوب بسيط، الهدف منه ليس حل الجوائز وإنما ليكون مرجعاً لاستخدام طريقة الصلابة (طريقة القساوة) في برنامج حاسوبي، وقد تم نشر هذا البرنامج كجزء من مشروع التخرج عام 2000.

واليوم عدت إلى أوراقي أقصد ملفاتي القديمة وبحثت عن هذا البرنامج وأضعه الآن بين أيديكم، راجياً من الله أن يكون فيه الفائدة.

البرنامج مكتوب بلغة QBasic ويمكن تحويله بسهولة إلى أي لغة برمجة أخرى خاصة لغة Visual Basic، وأنشره هنا بصيغة PDF لأني لم أجد ملف البرنامج الأصلي! وهو في المرفقات.

لأي استفسار عن أي نقطة منه أنا في الخدمة، وكما قلت، تم كتابة البرنامج بأبسط أسلوب ممكن لفهم الطريقة.


----------



## محمود الصقار (4 مايو 2010)

السلام عليكم

تسلم إيدك يا بشمهندس عبد الجواد

سوف أحاول قرأته

و حبذا لو ترفقه بخوارزم أو فكرة البرنامج

محمود الصقار


----------



## عبد الجواد (5 مايو 2010)

السلام عليكم:

سأحاول شرح البرنامج قدر الإمكان، وقد تساعدني عن طريق بعض الأسئلة إن كان فيه غموض.


----------



## محمود الصقار (5 مايو 2010)

السلام عليكم 

أنا أقوم اليوم بقرأة البرنامج و إن شاء الله سأتابع معك

غير أنه فى ال qb كنا ندخل البيانات رقم رقم (و بالتالى تحتاج من البداية معرفة أبعاد المصفوفة ) 

ما هى أفضل الأدوات فى ال visual basic لقرأة هذه الخانات

هل ال flex grid أم ماذا ؟

و كيف يمكن ربطها برسم معين ؟

لو سمحت أستاذنا مهندس عبد الجواد التوضيح

محمود الصقار


----------



## عبد الجواد (5 مايو 2010)

السلام عليكم:

إن كل برنامج هندسي يتألف من جزئين رئيسيين:
الأول هو خوارزمية حل المشكلة مثل خوارزمية طريقة الصلابة المذكورة أعلاه، والتي بدورها تتألف من خوارزميات أخرى مثل حل مجموعة معادلات أو ضرب مصفوفات...
الثاني: كيفية إدخال المعلومات اللازمة.

الجزء الأول تقريباً ثابت في كل البرامج الموجهة لحل مثل هذا النوع من المسائل.
الجزء الثاني هو فن بحد ذاته، وتتميز البرامج عن بعضها بهذا الجزء، وقد قمت أنت مشكوراً بطرح موضوع نقاش حول هذا الجزء على الرابط:
http://www.arab-eng.org/vb/t196141.html

من طرق إدخال المعطيات في فيجيوال بيسيك:
1- عن طريق مجموعة من أدوات النصوص TextBox، وهي الطريقة الأسهل للمبرمج، ولكنها الأكثر مللاً للمستخدم لأن أسلوب الإدخال صعب ويكون التعامل هنا مع أرقام فقط وليس مع رسومات.
2- أسلوب آخر هو التعامل جدول FlexGrid، وهو أفضل من الأسلوب السابق ولكن لا يختلف عنه كثيراً.
3- الأسلوب الأفضل وهو الذي تتبعه معظم البرامج العالمية، هو عن طريق الرسم، وهو الأصعب بالنسبة للمبرمج، وهنا يقوم البرنامج بتحديد حجم مصفوفة الصلابة وعدد العناصر بشكل ديناميكي بحسب معطيات المستخدم.

فمن أجل برنامج لحساب الجوائز الشبكية فإن الأسلوب الأفضل هو الرسم، مع ضرورة اللجوء أحياناً إلى الوسيلتين السابقتين من أجل تعديل بعض الأرقام.

أما من أجل الجوائز المستمرة مثلاً، فقد وجدت وحسب خبرتي أن الإدخال اليدوي أسرع من الرسم، لأنه لن أحتاج إلى أكثر من رقم واحد لإدخال طول الفتحة ثم رقم آخر للفتحة التي تليها وهكذا.
تخيل مثلاً أنك تريد رسم جائز مستمر في برنامج مثل Sap بدون مساعدة معالج إدخال Wizard، أو أنك تريد تعديل طول فتحة ما!

ولكن الأمر مختلف مع الجوائز الشبكية والإطارات، لأنك تحتاج لإدخال عقد في المستوي (أو في الفراغ) وعملية إدخال الإحداثيات تكون مزعجة وبطيئة جداً إن تمت بشكل يدوي، لذلك فإن الرسم في هذه الحالة أفضل.

إن هذا الجزء الثاني الذي أتحدث عنه يأخذ مني معظم وقتي عند عمل البرامج، وكمثال على ذلك، أقوم الآن بتطوير برنامج لتصميم الأعمدة (مبدئياً على الضغط البسيط، مع إدخال بعض العوامل لأخذ تأثير اللامركزية الطارئة حسب الكود).

إن خوارزمية حساب تسليح العمود، لا تزيد عن 30 سطر في أقصى الحالات، ولا تأخذ من المبرمج أكثر من نصف ساعة، ولكن حتى اليوم كتبت بضعة آلاف من الأسطر وأخذ البرنامج من وقتي أكثر من شهر عمل متواصل مع أني أعتمد على تصاميم سابقة لبرنامج التصميم الزلزالي!! (قريباً سأنتهي من الإصدار التجريبي الأول إن شاء الله).

على كل حال، الفكرة من طرحي للبرنامج السابق هي توضيح الجزء الأول من البرنامج، وهو شرح خوارزمية تحليل الجوائز الشبكية بحسب طريقة الصلابة (وهي أبسط أشكال طريقة الصلابة) بغض النظر عن أسلوب الإدخال (لذلك استخدمت أبسط أسلوب)، ويمكن تطويره بسهولة لأي لغة برمجة ولأي حالة من حالات طريقة الصلابة كتصميم الجوائز المستمرة أو الإطارات.

وسأقوم إن شاء الله بالإجابة عن أي سؤال يخص هذا البرنامج.​


----------



## م عبد الحكيم مواس (5 مايو 2010)

تسلم أخ عبد الجواد فكل ما يرد منك مفيد 
جزاك الله خير 
و السلام عليكم و رحمة الله و بركاته


----------



## محمود الصقار (6 مايو 2010)

السلام عليكم أخى المهندس عبد الجواد

لا أملك سوى أن أحيك على هذا البرنامج الرائع , و المنظم, و لى بعض التعليقات , و الأسئلة:

1- لو تم تغير بعض التسميات لكان أفضل 

* مثال input settlement بدلا من input deflection
* أيضا مصفوفة القوى لو تم تسميتها ب F بدلا من إستخدام ال K - لدرجة أفقدتنى التركيز عندما كنت أقرأ ال subrotune الخاص ب equations

2- لا يوجد هذا ال subrotuine باسم printmat 

3- لم أفهم برمجة كيف يكتشف ال unstability , ماهى فلسفتها؟

4- لم أفهم عمل الثابت inf 

5- لو يوجد لديك ملف ترفقه يوجد فيه كل ال local و ال global stifness ب 2D,3D , و فلسفة إيجاد ال global من الlocal , حيث أننى أستنتجتها من هذا البرنامج أمس مصفوفة 4*4 تحتوى على ال E,A,L,COS,SIN و أنا بالفعل لا يوجد معى هنا فى الأمارات هذه المصفوفات - تركتها فى مصر-

و أستنتجت أيضا ال global غير أنى لا أتذكر فلسفتها


أما البرنامج بصفة عامة فهو رائع بمعنى الكلمة

أعتقد يأستاذنا العظيم , أن لديك برامج الخاصة بهذا ال truss و ال frames فى ال 2D AND 3D
و أنك لا تعيد كتابتها كل برنامج جديد أليس كذلك؟

جزاك الله خيرا

محمود الصقار


----------



## MOHD9119 (6 مايو 2010)

جزاكم الله خيرا


----------



## عبد الجواد (8 مايو 2010)

السلام عليكم:

أهلاً أخ محمود، سأحاول الإجابة على تساؤلاتك قريباً جداً إن شاء الله على شكل دروس بسيطة تشرح عمل البرنامج بالتفصيل.


----------



## محمود الصقار (8 مايو 2010)

جزاك الله خيرا أخى و أستاذى مهندس عبد الجواد 

و أنا أيضا , راجعت ال stiffness method كاملة لكل أنواع المنشاءات , و كيفية إيجاد ال over all stiffness لكل نوع 

و أجد أنه من المناسب أن أساعدك فى الشرح قدر ما أستطيع , فأنا أعد الأن شرح لبرمجة المصفوفات بطريقة مبسطة قد يستفيد منها أخواننا الذين يريدون أن يتعاملوا مع البرامج الهندسية بصورة إحترافية

و أنتظر مشاركاتك , و أتعلم منك

محمود الصقار


----------



## عبد الجواد (9 مايو 2010)

أخ محمود شكراً لك مرة أخرى، وأنت سباق في المجال التعليمي، وقد يكون عندك القدرة على الشرح أفضل مني، لذلك يسعدني أن تساعدني بتوضيح ما تراه غير واضح.
سأقوم بالشرح على عدة مشاركات إن شاء الله، وحتى تكون المتابعة أسهل سأجعل بينها يوماً تقريباً لشرح ما قد يكون غامضاً في كل جزء.

وقبل أن أبدأ بشرح البرنامج يجب أن أوضح الأمور التالية:
1- أساس عمل البرنامج هو توضيح برمجة طريقة مصفوفة الصلابة المباشرة، عن طريق مناقشة الحالة الخاصة وهي دراسة الجوائز الشبكية المستوية Truss.

2- البرنامج لم يركز على أسلوب الإدخال واستخدمت فيه أبسط أسلوب حتى يتم التركيز على الفكرة النظرية.

3- استخدمت فيه لغة Quick Basic، لبساطتها.

4- يمكن توسيع البرنامج بسهولة ليشمل حالات أعم مثل دراسة العناصر الإطارية المستوية أو الفراغية، أو حتى توسيعه أكثر ليصبح نواة لبرنامج حل عناصر محدودة Finite Element، فكما هو معلوم فإن طريقة الصلابة المباشرة هي الأساس لطريقة العناصر المحدودة.

5- يجب أن يكون القارئ ملماً قليلاً بطريقة مصفوفة الصلابة المباشرة.

وبسم الله أبدأ.

*شرح لبعض أوامر QBasic المستخدمة:*
أيضاً أفترض أن القارئ له إلمام بإحدى لغات البرمجة، وسأقوم بشرح هذه الأوامر بشكل مبسط ليطابقها مع مقابلاتها من اللغة التي يعرفها، وفي حال غموض أي نقطة سأقوم بشرحها بناءً على الطلب.

- الأمر DECLARE يستخدم لتعريف تابع Function أو إجراء Sub حيث نضيف اسم التابع أو الإجراء بعد هذه الكلمة، مع ملاحظة أننا لا نحتاج إلى هذا الأمر في فيجيوال بيسيك.
فلتعريف إجراء يقوم بطباعة ترويسة في بداية الصفحة، نعطيه اسماً مميزاً وليكن Header ثم نقوم بتعريفه بالشكل:


```
DECLARE SUB Header ()
```

ثم نضيف الإجراء كما يلي:


```
SUB Header
...
END SUB
```

أي نكتب SUB ثم اسم الإجراء، وفي السطر التالي نكتب END SUB للدلالة على انتهاء الإجراء، وبين السطرين السابقين نضع الأسطر البرمجية التي نريد تنفيذها في حال استدعينا هذا الإجراء.
ولاستدعاء الإجراء السابق نكتب اسمه فقط.

- الأمر CLS: يستخدم لمسح الشاشة.

- الأمر DIM: لتعريف متحول ما أو مصفوفة، وكلمة SHARED بعدها تفيد بأن المتحول يمكن استخدامه في أي إجراء.

- الأمر CONST: لتعريف ثابت، والفرق بين الثابت والمتحول أن الأول لا يمكن تغييره ضمن البرنامج لاحقاً.

- الأمر FOR...NEXT: حلقة.

- IF...END IF: شرط.

- الأمر COLOR: لتغيير اللون.


*طريقة عمل البرنامج:*
إن أي برنامج للعناصر المحدودة أو طريقة الصلابة المباشرة يمر بالمراحل التالية:
1- إدخال المعطيات.
2- تشكيل مصفوفات الصلابة العنصرية، وتجميعها في مصفوفة الصلابة الكلية للنموذج.
3- إزالة شذوذ مصفوفة الصلابة عن طريق وضع شروط الاستناد.
4- حل جملة المعادلات الخطية صلابة × انتقالات عقدية = قوى خارجية.
5- من المعادلات السابقة نحصل على انتقالات العقد، ومنها نحصل على القوى الداخلية.
6- إخراج النتائج.​

يتبع، إن شاء الله...


----------



## محمود الصقار (9 مايو 2010)

ربنا يبارك فيك

شرح ممتاز 

محمود الصقار


----------



## خالد الأزهري (9 مايو 2010)

السلام عليكم ورحمة الله وبركاته
متابعة للشرح الذي كنا نتمناه منذ زمن....



> طريقة عمل البرنامج:
> إن أي برنامج للعناصر المحدودة أو طريقة الصلابة المباشرة يمر بالمراحل التالية:
> 1- إدخال المعطيات.
> -اختيار العنصر المناسب
> ...


----------



## إقرأ و إرتقي (10 مايو 2010)

بارك الله فيكم اجمعين ووفقكم لنشر العلم فالمنشئات المعدنية شحيحة المعلومات و نحن ننتظر منكم المفيد
جزاكم الله خيرا م محمود م عبد الجواد م خالد جميعا مشكورين


----------



## عبد الجواد (10 مايو 2010)

السلام عليكم:

شكراً أخ "إقرأ و إرتقي" أو "اقرأ وارتق" على كلماتك، ولكن البرنامج هو عن التحليل الإنشائي فقط للجوائز الشبكية Truss، وأرجو أن تجد فيه الفائدة.

أهلاً أستاذ خالد، ويسعدني انضمامك، وشكراً لزيادة التوضيح.
يمكنك مع الأستاذ محمود أن تضيف إلى الشرح ما تراه مناسباً متى أردت.

وجواباً على كلامك:


> متابعة للشرح الذي كنا نتمناه منذ زمن....



أنا لم أشرح البرنامج، لأنه لم يطلب مني ذلك، فافترضت أنه إما واضح أو أنه غير مهم.

متابعة للشرح:

البرنامج مقسم إلى مجموعة من البرامج الجزئية والتوابع التي تبدأ بالكلمة SUB أو FUNCTION وتنتهي ب END SUB أو END FUNCTION وقد فصلت بين هذه البرامج بخطوط أفقية.
البرامج السابقة كما قلنا يتم تنفيذها عند طلبها فقط، أما الجزء الذي يتم البدء بتنفيذه بمجرد تشغيل البرنامج فهو الجزء الأول في بداية البرنامج، وها هو:


```
[FONT="Courier New"]DECLARE SUB PrintForces ()
DECLARE SUB CalcForces ()
DECLARE SUB Equations ()
DECLARE SUB InputForces ()
DECLARE SUB InputDeflections ()
DECLARE SUB PressAkey ()
DECLARE SUB InputMembers ()
DECLARE SUB InputJoints ()
DECLARE FUNCTION jInput! (qst$)
DECLARE SUB Header ()
DECLARE SUB PrintMid (msg$)

CLS
Header
DIM SHARED noj AS INTEGER, nom AS INTEGER, nos AS INTEGER, nof AS INTEGER
noj = jInput("Number of JOINTS :")
nom = jInput("Number of MEMBERS :")
nof = jInput("Number of FORCES :")
nos = jInput("Number of SUPPORTS :")
DIM SHARED xj(noj) AS SINGLE, yj(noj) AS SINGLE
DIM SHARED mem(nom, 2) AS INTEGER
DIM SHARED MA(nom) AS SINGLE, ME(nom) AS SINGLE
DIM SHARED MC(nom) AS SINGLE, MS(nom) AS SINGLE
DIM SHARED ML(nom) AS SINGLE
DIM SHARED defl(2 * noj) AS SINGLE, f(nom) AS SINGLE
DIM SHARED ks(4, 4) AS SINGLE, k(2 * noj, 2 * noj + 1) AS DOUBLE
CONST inf = 1E+30

InputJoints
InputMembers
InputForces
InputDeflections
Equations
CalcForces
PrintForces[/FONT]
```

إذاً يبدأ البرنامج بتعريف أسماء البرامج الجزئية (الأسطر التي تبدأ بكلمة Declare) والتي سيتم شرحها (أي البرامج) في وقتها.
ثم يقوم بمسح الشاشة CLS.
ثم يقوم بتنفيذ البرنامج الجزئي الذي اسمه Header، وهذا البرنامج هو لطباعة ترويسة الصفحة، وهو ليس ذو أهمية ويمكن تجاوز شرحه، وهذا هو كود برنامج Header.


```
[FONT="Courier New"]SUB Header
    COLOR 6
    PrintMid "ALBAATH UNIVERSITY"
    PrintMid "FACULTY OF CIVIL ENGINEERING"
    PrintMid "PROGRAM FOR DESIGN PLAN HINGED TRUSSES"
    PrintMid "ABDULJAWAD AL-HAJYOUNESS"
    PRINT STRING$(80, "-")
    VIEW PRINT 7 TO 23
END SUB[/FONT]
```

ثم نقوم بتعريف المتحولات noj,nom,nos,nof على أنها أعداد صحيحة INTEGER.
وهذه المتحولات تدل على:
noj عدد العقد، nom عدد العناصر، nos عدد المساند، nof عدد القوى

ثم نقوم بسؤال المستخدم عن قيمة كل متحول عن طريق استخدام التابع jInput:

```
[FONT="Courier New"]FUNCTION jInput (qst$)
    COLOR 9: PRINT qst$;
    COLOR 10: INPUT " ", i
    jInput = i
END FUNCTION[/FONT]
```

أيضاً شرح هذا التابع ليس ذو أهمية، ولكن الغرض منه هو إيقاف البرنامج مؤقتاً للحصول على قيمة من المستخدم (وهذا هو أسلوب عمل برامج DOS بشكل عام، على عكس برامج ويندوز).

ثم نقوم بحجز المصفوفات والأشعة اللازمة لتخزين إحداثيات العقد xj, yj، وتخزين أرقام عقد بداية ونهاية العناصر mem ومواصفات مقاطع العناصر كالمساحة MA وعامل المرونة ME، ويقوم البرنامج تلقائياً بحساب جيب وتجيب زاوية العنصر بالنسبة للأفق ويقوم بتخزينها في الشعاعين MC و MS، كما يحسب طول العنصر ويخزنه في ML.
أيضاً نقوم بحجز الشعاع defl وهو يمثل شعاع الانتقالات العقدية الذي سينتج عن حل المعادلات، ونقوم بحجز الشعاع f وهو يمثل شعاع القوى الداخلية في العناصر والذي يحسب من شعاع الانتقالات السابق.
ونحجز المصفوفة ks والتي تمثل مصفوفة الصلابة العنصرية، وحجمها 4*4، والمصفوفة k وهي مصفوفة الصلابة الكلية للجملة وحجمها (2*عدد العقد،2*عدد العقد) حيث 2 هو عدد درجات الحرية لكل عقدة، وقمنا بإضافة عمود لهذه المصفوفة لتخزين القوى الخارجية.

ثم نحجز ثابتاً اسمه inf ذو قيمة كبيرة جداً (infinity) وسنأتي على فائدته لاحقاً.

هنا تنتهي مرحلة حجز الأشعة والمصفوفات وتبدأ عملية الإدخال والتحليل، والتي سأتابعها لاحقاً إن شاء الله.

وهنا أود أن أجيب على بعض استفسارات أو فلنقل اقتراحات الأخ محمود، وهو:



> 1- لو تم تغير بعض التسميات لكان أفضل
> 
> * مثال input settlement بدلا من input deflection
> * أيضا مصفوفة القوى لو تم تسميتها ب F بدلا من إستخدام ال K - لدرجة أفقدتنى التركيز عندما كنت أقرأ ال subrotune الخاص ب equations


معك حق، ففي وقتها لم تكن لغتي الإنكليزية جيدة، وكنت أبحث عن المصطلحات في القاموس.



> 2- لا يوجد هذا ال subrotuine باسم printmat


كما أذكر فإن هذا البرنامج هو لطباعة المصفوفات من أجل تدقيقها، وقد حذفته لأنه ليس من صلب البرنامج، وربما نسيت أن أحذف تعريفه.
أما بقية الاستفسارات فسأحاول الإجابة عنها في وقتها إن شاء الله.


----------



## محمود الصقار (11 مايو 2010)

السلام عليكم

جزاك الله خيرا , أستمر وفقاك الله

محمود الصقار


----------



## محمود الصقار (15 مايو 2010)

السلام عليكم

نرجو أن تكون بخير أستاذنا العظيم

محمود الصقار


----------



## عبد الجواد (15 مايو 2010)

السلام عليكم:

شكراً أخ محمود على سؤالك عني، أنا بخير والحمد لله، ولكنه الكسل.

على كل حال قبل المتابعة أرى من الضروري قراءة طريقة الصلابة المباشرة للذي ليس عنده اطلاع عليها، وأرفق هنا فصلاً يشرح تطبيق هذه الطريقة على الجوائز الشبكية (Truss).


----------



## عبد الجواد (16 مايو 2010)

السلام عليكم:

وصلنا الآن إلى الأسطر التالية:


```
[FONT="Courier New"]InputJoints
InputMembers
InputForces
InputDeflections
Equations
CalcForces
PrintForces[/FONT]
```

وهي أسماء لبرامج جزئية يستدعيها البرنامج بالترتيب.
فبعد أن قمنا بتعريف المتحولات وتعريف المصفوفات وأحجامها، نقوم بسؤال المستخدم أن يقوم بإدخال المعطيات:

البرنامج InputJoints: يسأله أن يقوم بإدخال إحداثيات العقد.
InputMembers: يسأله أن يقوم بإدخال بداية ونهاية ومواصفات مقطع كل عنصر.
InputForces: يسأله أن يقوم بإدخال القوى الخارجية.
InputDeflection: يسأله أن يقوم بإدخال المساند، أو الانتقالات المعلومة للمساند.

أثناء عملية الإدخال يقوم البرنامج بتشكيل مصفوفات الصلابة العنصرية، ويقوم بتجميعها في مصفوفة الصلابة الكلية، ثم يقوم بتعديل هذه المصفوفة بناءً على شروط الاستناد، كما يقوم بتشكيل شعاع الحمولات الخارجية.

ملاحظة: في البرامج العملية، لا يفضل تشكيل مصفوفة الصلابة والمصفوفات الأخرى أثناء عملية الإدخال، وإنما أن تتم قبيل عملية التحليل، ولكن للتسهيل هنا فقد اعتمدنا أن نقوم بتشكيل المصفوفات أثناء عملية إدخال العناصر والمساند والقوى، فالهدف تعليمي.
ولو قدر لي أن أعيد كتابة هذا البرنامج الآن لكتبته بأسلوب آخر.

البرنامج Equations: يقوم بحل جملة المعادلات الخطية والناتج هو انتقالات العقد.
البرنامج CalcForces: يحسب القوى الداخلية في العناصر بناء على انتقالات العقد الناتجة من الخطوة السابقة.
البرنامج PrintForces: يقوم بطباعة القوى الناتجة في الخطوة السابقة.

ملاحظة: قد تكون ترجمة بعض الكلمات غير مناسبة كما أشار الأخ محمود، ولكن فضلت أن لا أعدل أي كلمة على البرنامج أو أعدل ترتيب البرنامج من أجل تطابقه مع الأصل.

وسنأتي على شرح كل برنامج على حدة، إن شاء الله.


----------



## عبد الجواد (16 مايو 2010)

البرنامج InputJoints:


```
[FONT="Courier New"]SUB InputJoints
    CLS
    FOR i = 1 TO noj
        i$ = "(" + STR$(i) + ") :"
        xj(i) = jInput("X of joint " + i$)
        yj(i) = jInput("Y of joint " + i$)
        PRINT STRING$(80, "-")
    NEXT
    PressAkey
END SUB[/FONT]
```

كما قلنا سابقاً، فإن وظيفة هذا البرنامج هي سؤال المستخدم عن إحداثيات العقد.
يبدأ البرنامج بعبارة CLS لمسح الشاشة.

ثم يفتح حلقة FOR...NEXT لتكرار الأوامر التي بين هاتين العبارتين بعدد مرات noj (وهو عدد العقد).
في المرة الأولى يأخذ المتحول i القيمة 1 وعندما يصل البرنامج إلى NEXT يعود إلى عبارة FOR ويزيد قيمة i بمقدار 1 وينفذ الأسطر وعندما يصل إلى NEXT مرة أخرى يعود إلى FOR ويزيد قيمة i بمقدار 1، هكذا حتى تصبح i أكبر من noj، عندها يخرج البرنامج من الحلقة.

أما الأوامر الموجودة ضمن الحلقة فهي:

```
[FONT="Courier New"]i$ = "(" + STR$(i) + ")[/FONT]
```
نقوم بتشكيل متحول $i وإشارة $ تفيد بأن المتحول نصي، فإذا كانت قيمة i تساوي 3 مثلاً فإن قيمة $i ستساوي (3) (أي 3 بين قوسين)، وهي في الحقيقة لا تفيد شيئاً إلا بعملية إظهار السؤال في الأسطر التالية.

نقوم بعدها بسؤال المستخدم عن x النقطة i، ثم y النقطة i، ونقوم بتخزينها في الشعاعين xj و yj.
ويتم السؤال عن طريق التابع jInput الذي تم شرحه سابقاً.


```
[FONT="Courier New"]
xj(i) = jInput("X of joint " + i$)
yj(i) = jInput("Y of joint " + i$)
[/FONT]
```

بعد ذلك نطبع خطاً فاصلاً بعد هذه العملية لفصلها عن عملية الإدخال التالية.

```
[FONT="Courier New"]
PRINT STRING$(80, "-")
[/FONT]
```

بعد الخروج من الحلقة ينتظر البرنامج من المستخدم أن يضغط أي زر للمتابعة عن طريق استدعاء البرنامج PressAkey، وهذا هو نصه:


```
[FONT="Courier New"]
SUB PressAkey
    PRINT "Press any key to continue..."
    DO WHILE INKEY$ = "": LOOP
END SUB
[/FONT]
```

ملاحظة: في البرامج العملية تتم عملية الإدخال عن طريق الرسم، أو عن طريق الاستيراد من أوتوكاد، وتتم قراءة عدد وإحداثيات العقد من لوحة الرسم أو من إحداثيات كائنات الأوتوكاد.

وأخيراً هذا مثال خلبي (يعني أرقام عشوائية) لعملية الإدخال (في المرفقات):




​
يتبع إن شاء الله...


----------



## محمود الصقار (17 مايو 2010)

السلام عليكم

جزاكم الله خيرا

و قد وفقت فى وضع صورة مايتم إظهاره فى ال q basic

أستمر على بركة الله

محمود الصقار


----------



## محمود الصقار (22 مايو 2010)

السلام عليكم 
ننتظر شرحك المميز يا بشمهندس عبد الجواد

محمود الصقار


----------



## عبد الجواد (22 مايو 2010)

السلام عليكم:

شكراً أخ محمود على متابعتك وهي ما يشجعني على متابعة الشرح.

وصلنا الآن إلى عملية إدخال العناصر، ويمكن القول أنه من هذه النقطة يبدأ البرنامج في دخول المرحلة النظرية، فكل ما سبق هو خطوات تأهيلية ولكن ضرورية للدخول إلى هذه المرحلة.

في هذه المشاركة سأقوم بشرح البرنامج InputMembers، وفيه يتم إدخال العناصر، بداية كل واحد ونهايته ومساحة مقطعه العرضي، وقيمة معامل يونغ (معامل المرونة).
وسنلاحظ أنه أثناء الإدخال يقوم البرنامج بتشكيل مصفوفات الصلابة العنصرية ثم تجميعها في مصفوفة الصلابة الكلية، وهذه الطريقة غير جيدة في البرامج العملية، ولكن كما قلت الغاية هنا تعليمية، ففي البرامج العملية نقوم بإدخال العناصر وتخزينها في متحولات خاصة. ثم أثناء عملية التحليل نقوم بتشكيل المصفوفات.

ومن الضروري أن أنبه إلى الرجوع إلى دراسة طريقة الصلابة في العناصر الشبكية لفهم البرنامج، وربما الأخ محمود أو الأخ خالد يشرحان هذه الطريقة بأسلوبهما السهل والممتع.

أما البرنامج كاملاً (أقصد برنامج إدخال العناصر) فهو:






ملاحظة: لا أدري لماذا لم يسمح لي السيرفر بإضافة هذا الكود، لذلك أدرجته كصورة.

يبدأ البرنامج بتعريف شعاع z من أربع عناصر، هذا الشعاع سيحوي قيم درجات الحرية العامة لبداية ونهاية العنصر، فلكل عنصر شبكي في المستوي أربع درجات حرية محلية (ترقم من 1 إلى 4) ويقابلها 4 درجات حرية عامة، تحسب أرقامها كما سيأتي لا حقاً.
ثم نمسح الشاشة بالأمر CLS.
ونبدأ حلقة تكرارية تبدأ من القيمة 1 وتنتهي بالقيمة nom وهي عدد العناصر، والمتحول الخاص بهذه الحلقة هو i فإذا ورد المتحول i ضمن الحلقة فإنه يدل على رقم العنصر المدروس.
ثم نقوم بسؤال المستخدم عن بداية العنصر ونهايته ومعامل مرونة مادته ومساحة مقطعه، بنفس طريقة إدخال إحداثيات العقد.

يتم تخزين رقم عقدة البداية ورقم عقدة النهاية في المصفوفة mem وهي عبارة عن مصفوفة عدد أسطرها هو عدد العناصر، وعدد أعمدتها 2، العمود الأول نخزن فيه رقم عقدة البداية والثاني رقم عقدة النهاية، فإن ذكر التعبير:


```
mem(5,2)
```

فإننا نقصد رقم عقدة النهاية للعنصر رقم 5.

ويتم تخزين معامل المرونة في الشعاع ME ومساحة المقطع في الشعاع MA.

بعد إدخال هذه المعلومات للعنصر رقم i، نقوم بحساب طوله وحساب جيب وتجيب (Sin and Cos) الزاوية بينه وبين المحور x، لأنهما يلزمان في تدوير محاوره الخاصة المنطبقة عليه لتصبح موازية للمحاور العامة.

وتحسب كما يلي:


```
[FONT="Courier New"]
d1 = xj(mem(i, 2)) - xj(mem(i, 1)): d2 = yj(mem(i, 2)) - yj(mem(i, 1))
ML(i) = SQR(d1 ^ 2 + d2 ^ 2)
MC(i) = d1 / ML(i): MS(i) = d2 / ML(i)
[/FONT]
```

حيث أن d1 يمثل dx و d2 يمثل dy لبداية ونهاية العنصر وربما كان الأفضل أن يتم تسميتهما هكذا dx,dy.

ثم يتم تشكيل مصفوفة الصلابة العنصرية للعنصر i، وهنا يلاحظ أنه تم تشكيل مصفوفة الصلابة العنصرية وفق المحاور العامة مباشرة، وهذه الطريقة أسرع من كتابتها وفق المحاور الخاصة ثم ضربها بمصفوفة التدوير وبمقلوب مصفوفة التدوير.





ملاحظة: أيضاً لم أستطع إضافة الكود السابق

يلاحظ من البرنامج أعلاه أنه تم إدخال نصف المصفوفة فقط ثم عن طريق حلقتين متداخلتين تم إدخال النصف الثاني على اعتبار أن المصفوفة متناظرة.

بعد أن قمنا بتشكيل مصفوفة الصلابة العنصرية ks والتي أبعادها 4*4 فكما قلنا أن للعنصر الشبكي 4 درجات حرية في المستوي، سنقوم الآن بجمع هذه المصفوفة إلى مصفوفة الصلابة الكلية k، أو ما سأسميه تجميع مصفوفات الصلابة العنصرية.

إن مصفوفة الصلابة الكلية هي بحجم (2*عدد العقد،2*عدد العقد) أو بمعنى آخر هي بحجم (عدد درجات الحرية،عدد درجات الحرية) من خواصها أنها متناظرة وعناصر القطر الرئيسي أكبر من الصفر دائماً، وهذه المصفوفة شاذة.
إن درجة الحرية تعبر عن انتقال، وبما أن كل عقدة من عقد الجائز لها حرية الانتقال أفقياً وشاقولياً فإن كل عقدة تعبر عن درجتي حرية، إذاً عدد درجات الحرية للجائز الشبكي كاملاً يساوي عدد العقد مضروباً في 2، أما بالنسبة للإطارات المستوية يكون مضروباً في 3 (انتقالين ودوران)

وسنرى لاحقاً كيف يمكن تقييد المنشأ عن طريق إدخال المساند، في مصفوفة الصلابة.

نعود إلى تجميع مصفوفات الصلابة العنصرية.
قلنا أن لكل عنصر 4 درجات حرية وفق محاوره المحلية، درجة الحرية رقم 1 تعبر عن الانتقال وفق محور العنصر لعقدة البداية، ورقم 2 تعبر عن الانتقال وفق محور عمودي على العنصر لعقدة البداية، و 3 و 4 لانتقال عقدة النهاية وفق محور مواز وعمودي على العنصر على الترتيب، وبعد تدوير مصفوفة الصلابة العنصرية (وفق المحاور المحلية) بزاوية تساوي زاوية العنصر مع المحور العام x نحصل على المصفوفة ks السابقة وهي مصفوفة الصلابة العنصرية وفق المحاور العامة، وفيها أيضاً للعنصر 4 درجات حرية مرقمة من 1 حتى 4، ولكن 1 تمثل انتقال عقدة البداية وفق المحور العام x و 2 وفق المحور العام y و 3 و 4 مثل السابقة ولكن لعقدة النهاية.

الآن نريد حساب رقم درجات الحرية العامة الموافقة لدرجات الحرية المحلية (بعد التدوير)، فلو فرضنا أن عنصراً بدايته هي العقدة رقم 1، فهذا يعني أن أرقام درجات حرية بدايته هي 1 و 2، ولو كانت بدايته هي العقدة رقم 2 فإن أرقام درجات حرية بدايته تصبح 3 و 4 وهكذا...
فإذا كان رقم عقدة بدايته هي h مثلاً فإن أرقام درجات حرية بدايته ستكون:


```
رقم درجة الحرية الموازية ل x = 2*h-1
رقم درجة الحرية الموازية ل y = 2*h
```

وكذلك الأمر بالنسبة لعقدة النهاية.

لذلك نقوم بجمع مصفوفة الصلابة للعنصر i إلى مصفوفة الصلابة الكلية وفق البرنامج التالي:




ملاحظة: أيضاً لم أستطع إضافة الكود السابق.

وجدير بالذكر أنه في المنشآت الضخمة تكون مصفوفة الصلابة الكلية كبيرة الحجم وتستهلك قدراً كبيراً من الذاكرة، وكما قلنا فإن هذه المصفوفة متناظرة، ويمكن الاستفادة من هذه الخاصية عن طريق تخزين نصف المصفوفة فقط.
كما أن معظم عناصر هذه المصفوفة قيمتها صفر ويمكن الاستفادة من هذه الخاصية أيضاً في ضغط مصفوفة الصلابة، وهناك تقنيات للتخزين الأمثل لمصفوفة الصلابة ولكنها ليست مجال بحثنا.

أرجو أن يكون الشرح واضحاً، والتتمة لاحقاً إن شاء الله.


----------



## عبد الجواد (22 مايو 2010)

في المشاركة السابقة لم أستطع إضافة بعض الأكواد ولاحظت أنني عندما أكتب السطرين التاليين (ولو كانا لوحدهما) مثلاً:






تظهر لي الرسالة التالية عند طلب المعاينة أو إضافة المشاركة:





لذلك قمت بإدراج بعض الأكواد كصور في المشاركة السابقة.


----------



## محمود الصقار (22 مايو 2010)

السلام عليكم مهندس عبد الجواد

بالفعل أتابعك كلما دخلت النت , و أتشرف بقرأة ما تكتبه

جزاك الله خيرا على الشرح الرائع , و أنا أدعوك للتكملة الرائعة 

أنت تعلم أن مجال البرمجة لا يدخله إلا النخبة فلا تعبأ بقلة المشاركات 

و هذا يجعلك تثق أن ما تعطيه من علم لن يأخذه إلا من يستحقه - لأن هذا العلم يحتاج إلى تعب و مثابرة -

توكل على بركة الله 

محمود الصقار


----------



## محمود الصقار (24 مايو 2010)

السلام عليكم مهندس عبد الجواد

أنتظر بفارغ الصبر مشاركاتك , و خصوصا فيما يخص ال subrotine الخاص ب equations 

و جزاك الله خيرا

محمود الصقار


----------



## عبد الجواد (24 مايو 2010)

السلام عليكم:

شكراً أخ محمود على المتابعة...

وصلنا الآن إلى مرحلة إدخال القوى الخارجية، أو البرنامج الجزئي InputForces

إن نص البرنامج هو:


```
[FONT="Courier New"]
SUB InputForces
    CLS
    FOR i = 1 TO nof
        i$ = "(" + STR$(i) + ") :"
        i1 = jInput("Joint for force " + i$)
        i2 = jInput("Direction of this force (0-Vertical , 1-Horizontal) :")
        i3 = jInput("Value of force " + i$)
        PRINT STRING$(80, "-")

        IF i2 <> 0 THEN i2 = 1
        z = 2 * i1 - i2
        k(z, 2 * noj + 1) = i3
    NEXT
    PressAkey
END SUB
[/FONT]
```

قبل شرح البرنامج، سأشرح عملية إدخال القوى نظرياً.
نسأل المستخدم عن قيمة القوة وفي أي عقدة وعن اتجاه القوة، ومن رقم العقدة ومن الاتجاه نستطيع تحديد رقم درجة الحرية التي قمنا بتطبيق القوة وفقاً لها.

يبدأ البرنامج بمسح الصفحة ثم فتح حلقة متحولها i تبدأ من الواحد وتنتهي بالقيمة nof والتي تمثل عدد القوى (أدخلنا قيمتها في بداية البرنامج)، فإذا ورد المتحول i ضمن الحلقة فإنه يدل على رقم القوة.

نسأل المستخدم عن رقم العقدة ونخزن القيمة في المتحول المؤقت i1، ثم نسأله عن اتجاه القوة ونخزن القيمة في المتحول المؤقت i2 حيث ندخل القيمة 0 إذا كانت القوة موازية للمحور العام y و 1 إذا كانت موازية للمحور x.
ثم نسأله عن قيمة القوة ونخزن القيمة في المتحول المؤقت i3، والقيمة تكون موجبة إذا كانت باتجاه المحاور وسالبة بالعكس.

نقوم الآن بتخزين القوة في مكانها الصحيح بحسب درجة حريتها، وفي هذا البرنامج قمت بتخزين القوة في عمود إضافي ضمن مصفوفة الصلابة، (وقد تم ذكر ذلك سابقاً عندما قمنا بحجز مصفوفة الصلابة)، وكان من الممكن أن نخزن هذه القوى ضمن شعاع لوحدها، ولن يختلف الحل، ولكن دمج شعاع القوى مع مصفوفة الصلابة يخفف من الأسطر البرمجية عند حل المعادلات (التي سنأتي على ذكرها لاحقاً)، وإن كنت الآن أفضل الفصل.

نعود إلى حساب درجة الحرية التي قمنا بتطبيق القوة باتجاهها.
قلنا أن رقم العقدة هو i1 ودرجتا الحرية للعقدة i1 هما:

```
2*i1-1 , 2*i1
```
كما تم ذكره سابقاً.

أي أننا نضرب رقم العقدة في 2 فنحصل على درجة الحرية الموازية ل y أو نطرح من ناتج الضرب 1 لنحصل على رقم درجة الحرية الموازية ل x أي كأننا نقول:


```
z = 2*i1-i2
```

لأن i2 ستأخذ القيمة 1 إذا كانت القوة موازية ل x وستأخذ القيمة 0 إذا كانت موازية ل y، وحيث z هو رقم درجة الحرية.

الآن نخزن قيمة القوة i3 في السطر رقم z في العمود الأخير من مصفوفة الصلابة (نذكر أننا حجزنا عموداً إضافياً في مصفوفة الصلابة لتخزين القوى فيه).
لذلك نكتب:


```
k(z, 2 * noj + 1) = i3
```

يتبع إن شاء الله...​


----------



## خالد الأزهري (24 مايو 2010)

السلام عليكم ورحمة الله وبركاته
جزاكم الله خير اساتذتنا عبد الجواد والصقار..الحقيقة شرح تحفة..يا ريت لو يستفيد منه الجميع وخصوصا الطلاب....

لي سؤال في الجزء الاخير
هذه الجملة


> i2 = jInput("Direction of this force (0-Vertical , 1-Horizontal) :")


تعطي المتغير i2 قيمة واحد او صفر فقط ...ثم تاتي هذه بعدها


> IF i2 <> 0 THEN i2 = 1


لتجعل غير الصفر واحد وهو كذلك بطبيعة الحال...اذن ما الفائدة من الجملة الاخيرة؟


----------



## عبد الجواد (24 مايو 2010)

وصلنا الآن إلى مرحلة إدخال المساند أو الشروط الطرفية في البرنامج الجزئي InputDeflections

قلنا سابقاً أن مصفوفة الصلابة الكلية للجملة هي مصفوفة شاذة، أي أن معينها (محددها) يساوي الصفر، لذلك فإن جملة المعادلات K.D=F لا يمكن حلها.
إن شذوذ مصفوفة الصلابة يدل على عدم استقرار الجملة، ونزيل شذوذها عن طريق إدخال الشروط الطرفية.
إذا تم إدخال شروط طرفية لا تؤدي إلى استقرار الجملة، كأن ندخل ثلاثة مساند أحادية تلتقي في نقطة واحدة، أو مسندين أحاديين فقط، فإن هذه المساند لن تلغي شذوذ مصفوفة الصلابة، وهكذا يمكننا اكتشاف أن الجملة غير مستقرة، وهذا جواب على سؤال الأخ محمود سابقاً:



> 3- لم أفهم برمجة كيف يكتشف ال unstability , ماهى فلسفتها؟



نعود إلى إدخال الشروط الطرفية، نقوم في هذا البرنامج بإدخال المساند عن طريق إدخال انتقالات معلومة للعقد التي فيها هذه المساند وفق درجة الحرية المطلوبة:
أي إذا قلنا أنه في العقدة 3 يوجد مسند يوازي y فإن هذا يعني برمجياً أنه وفق درجة الحرية 2*3=6 فإن الانتقال يساوي الصفر، وإذا قلنا أنه في العقدة 2 يوجد مسند أفقي انتقل لسبب ما (كانتفاخ تربة أو هبوط مساند...) بقيمة 0.1 فإن هذا يعني أنه وفق درجة الحرية 2*2-1=3 فإن الانتقال يساوي 0.1

إن توضحت هذه الفكرة نتابع إلى نص البرنامج:


```
[FONT="Courier New"]
SUB InputDeflections
    CLS
    FOR i = 1 TO nos
        i$ = "(" + STR$(i) + ") :"
        i1 = jInput("Joint for support " + i$)
        i2 = jInput("Direction of this support (0-Vertical , 1-Horizontal) :")
        i3 = jInput("Deflection of support " + i$)
        PRINT STRING$(80, "-")

        IF i2 <> 0 THEN i2 = 1
        z = 2 * i1 - i2
        k(z, z) = inf: k(z, 2 * noj + 1) = i3 * inf
    NEXT
    PressAkey
END SUB
[/FONT]
```
ملاحظة: أشار الأخ محمود إلى أنه كان من الأفضل تسمية البرنامج InputSettlement

إن هذا البرنامج يشابه تقريباً برنامج إدخال القوى السابق ويختلف عنه في سطر واحد فقط هو:


```
[FONT="Courier New"]k(z, z) = inf: k(z, 2 * noj + 1) = i3 * inf[/FONT]
```

أي يختلف عنه في السطر الذي نقوم فيه بتخزين قيمة الانتقال، لذلك سأقوم بشرح هذا السطر فقط.

كما قلنا سابقاً فإن مصفوفة الصلابة شاذة أي المنشأ غير مستقر، ولإزالة الشذوذ يجب تأمين استقرار المنشأ عن طريق وضع القيود أو المساند، أما رياضياً فهناك عدة طرق منها الطريقة المستخدمة في هذا البرنامج.
هذه الطريقة تقول أنه نقوم بتغيير قيمة العنصر القطري في مصفوفة الصلابة المقابل لدرجة حرية الانتقال المعلوم إلى قيمة كبيرة جداً (هنا استخدمنا المتحول inf من infinity) وأن نغير قيمة الحمولة الموافقة لنفس درجة الحرية إلى قيمة الانتقال مضروباً بنفس هذه القيمة الكبيرة جداً inf، وهو ما تم في السطر السابق، ولكن ما هو السبب؟! وما هي فلسفة هذه الطريقة؟!

لنفرض أنه لدينا المعادلات التالية:


```
[FONT="Courier New"]3x1 + 2x2 + 4x3 = 19
x1 + x2 - x3 = 0
-x1 + 4x2 + 6x3 = 25[/FONT]
```

إن حل جملة المعادلات هذه هو x1=1,x2=2,x3=3
إذا أردنا أن تكون قيمة x3 تساوي 5 مثلاً سنقوم بتكبير أمثال x3 مثلاً في المعادلة الثالثة ليصبح مليون مثلاً، ثم جعل القيمة في الطرف الثاني خمسة ملايين (أي 5 * مليون)، لتصبح المعادلة الثالثة:


```
[FONT="Courier New"]-x1 + 4x2 + 1000000x3 = 5000000[/FONT]
```

فإن x3 يمكن حسابها كما يلي:

```
[FONT="Courier New"]x3 = (5000000 - (-x1 + 4x2))/1000000
x3 = 5 - (-x1 + 4x2)/1000000[/FONT]
```

من الواضح أن الحد الثاني صغير جداً لأن x1 و x2 هي انتقالات أصغر بكثير من مليون لذلك فإن قيمة x3 ستساوي تقريباً 5 وهي القيمة التي نريدها، وهذه فلسفة هذه الطريقة.
ملاحظة: طبعاً ستتغير قيم x1 وx2 عن القيم التي أشرنا إليها أعلاه، وهذا أمر طبيعي، فلكل حالة استناد نحصل على انتقالات عقدية مختلفة.

كما قلت هناك طرق أخرى قد تكون أفضل، كأن نجعل أمثال x3 في المعادلة الثالثة تساوي 1 وأمثال المتحولات الأخرى في السطر والعمود الثالث تساوي الصفر، أما القيمة في الطرف الثاني في السطر الثالث تساوي قيمة الانتقال المعلوم، وأنا أفضل هذه الطريقة.
وطرق رياضية أخرى، إذاً هذه الطرق رياضية بحتة.

إلى حل جملة المعادلات لاحقاً إن شاء الله...​


----------



## عبد الجواد (24 مايو 2010)

خالد الأزهري قال:


> السلام عليكم ورحمة الله وبركاته
> جزاكم الله خير اساتذتنا عبد الجواد والصقار..الحقيقة شرح تحفة..يا ريت لو يستفيد منه الجميع وخصوصا الطلاب....
> 
> لي سؤال في الجزء الاخير
> ...



أهلاً أخ خالد، لم أنتبه إلى سؤالك لأني كنت أكتب بقية الشرح،

أولاً شكراً على سؤالك، وهو سؤال وجيه والإجابة عليه كالتالي:
قمت بعمل هذا الشرط لضمان أن تكون قيمة i2 تساوي إما صفر أو واحد، حيث أن المستخدم يستطيع إدخال أي رقم، فإذا أدخل رقماً مغايراً للصفر اعتبرته واحد.

طبعاً قد تقول لي، ولكنه قد يدخل أيضاً رقم عقدة أكبر من عدد العقد، فلم لم تتحقق في هذه الحالة، وتحققت من تلك؟

الحقيقة لا أدري :18: ، وبما أن البرنامج هدفه تعليم خوارزمية فقط، فإنه لا يشترط فيه إدخال شروط تحقق حتى لا يتم تعقيد البرنامج، لذلك يمكن الاستغناء عن السطر السابق، ويتم فرض أن إدخالات المستخدم صحيحة. ولا أبالغ إن قلت لك أن كتابة نص البرنامج تتبع إلى الحالة النفسية للمبرمج!!!

ولكن في البرامج العملية، تستغرق مني عمليات التحقق من الإدخال والإخراج أضعاف الوقت اللازم لكتابة الخوارزمية الرئيسية، ومن الأسطر أضعافاً مضاعفة!!! ومع هذا قد أغفل عن بعض عمليات التحقق أحياناً، مما يؤدي إلى توقف عمل البرنامج.


----------



## خالد الأزهري (24 مايو 2010)

عبد الجواد قال:


> أهلاً أخ خالد، لم أنتبه إلى سؤالك لأني كنت أكتب بقية الشرح،
> 
> أولاً شكراً على سؤالك، وهو سؤال وجيه والإجابة عليه كالتالي:
> قمت بعمل هذا الشرط لضمان أن تكون قيمة i2 تساوي إما صفر أو واحد، حيث أن المستخدم يستطيع إدخال أي رقم، فإذا أدخل رقماً مغايراً للصفر اعتبرته واحد.
> ...



الحمد لله ..يعني هناك فهم حاصل...
وبالفعل ..التحقق يحتاج لسطور قد تتجاوز الاسطر الاساسية للبرنامج....
أعتقد أن التحقق من الادخال يمكن ان يكون عقبه مباشرة..كالتالي

```
i2 = jInput("Direction of this force (0-Vertical , 1-Horizontal) :")
```
if i2 <>1 or i2<>0 then "error"
go to......ومن ثم نقوم باعادة الادخال

أعلاه ليست برمجة لعدم معرفتي بالكويك بيسك

متابعين...


----------



## خالد الأزهري (24 مايو 2010)

اسف على قطع التتابع لكن ذكرتم ان هناك طرق لتوفير الذاكرة بالتخلص من الاصفار في المصفوفة والاحتفاظ بالقيم غير الصفرية فقط..أتمنى لو مررتم عليها بعد الانتهاء من البرنامج او في الوقت المناسب...


----------



## عبد الجواد (24 مايو 2010)

بالنسبة لعمليات التحقق، هناك العديد منها:
1- منها منع المستخدم من إدخال قيم غير منطقية، ففي الحالة السابقة مثلاً نختبر القيمة المدخلة من المستخدم قبل قبولها، فإن كانت صفراً أو واحد قبلناها وإلا فلا.
2- إظهار رسالة كما تفضلت.
3- اعتبار أي قيمة مخالفة للصفر تساوي واحد، كما في البرنامج.
4- طرق أخرى...

إن أفضل الطرق هي التي لا تجبر المستخدم على سماع صوت رسائل الخطأ، فإذا أمكننا معالجة الخطأ عن طريق تحويل القيمة التي أدخلها إلى قيمة منطقية دون أن يؤدي ذلك إلى إدخالات غير متوقعة من المستخدم قمنا بذلك.
لذلك أنا أفضل في الحالة السابقة الطريقة التي في البرنامج.

والطريقة التي ذكرتها أنت أيضاً صحيحة.

بالنسبة لضغط المصفوفة هو موضوع رياضي بحت تمت معالجته في كتب العناصر المحدودة، فإذا وجدت وقتاً شرحته إن شاء الله.


----------



## محمود الصقار (25 مايو 2010)

السلام عليكم و رحمة الله

أولا أود أن أعبر عن مدى إعجابى بطريقة شرحك, و مدى إجتهادك و مقدار مشاركاتك الرائعة
و أدعو أخينا أبو الحلول لتثبيت الموضوع ضمن موضوعه شروحات و إستفسارات

و من الجميل أن نتلقى هذا العلم على يد شيوخنا -إن جاز التعبير-

فأنا أقر أن شيوخى فى هذا العلم
1- د/ثروت صقر الذى درسه لى فى مشروع advanced structures with computer
2-د/عاطف العراقى الذى سمعت محاضراته الرائعة فى شرح ال q basic و ال fortran 
3-مهندس/عبد الجواد الحاج يونس الذى مازال يتحفنا بشرحه الأكثر من رائع و الذى بدأ من حيث أنتهى الأخرون

فجزاهم الله عنا خيرا 

و مازلنا ننتظر الشرح الأكثر من رائع لمهندسنا العظيم المهندس / عبد الجواد

و أنا أرى أنه حتى يتقدم الإسلام , فلابد ألا يبدأ كلا منا من البداية كمجهود فردى , بل من حيث أنتهى الأخرون , حتى لا نظل نعيد نفس المعاناة لنصل لنفس النتيجة, فحمدا لله أستاذتنا يتحفونا بما وصلوا إليه , ليستفيد بعضهم من بعض , و لا يعيدوا المعاناة فى طلب مبادىء العلم , فتتقدم الأمة 


محمود الصقار


----------



## خالد الأزهري (25 مايو 2010)

محمود الصقار قال:


> السلام عليكم و رحمة الله
> 
> أولا أود أن أعبر عن مدى إعجابى بطريقة شرحك, و مدى إجتهادك و مقدار مشاركاتك الرائعة
> و أدعو أخينا أبو الحلول لتثبيت الموضوع ضمن موضوعه شروحات و إستفسارات
> ...


اسمح لي باقتباس الجملة الاخيرة كتوقيع...


----------



## محمود الصقار (25 مايو 2010)

السلام عليكم
مهندس خالد

جزاك الله خيرا

طبعا , بل و أشكرك على ذلك , و أتمنى أن نعيش كلنا لتنهض أمتنا,فنرضى ربنا , و نلقى نبينا و يفرح بنا

محمود الصقار


----------



## Abo Fares (25 مايو 2010)

محمود الصقار قال:


> و أدعو أخينا أبو الحلول لتثبيت الموضوع ضمن موضوعه شروحات و إستفسارات



السلام عليكم ورحمة الله.. 

تم تثبيت الموضوع.. 

أشكر أخينا المهندس عبد الجواد على مجهوده الكبير الواضح.. كما أشكر جميع الأخوة المتابعين المشجعين للموضوع.. 

متابع معكم للاستفادة.. 

خالص التحيــــــات..​


----------



## عبد الجواد (26 مايو 2010)

السلام عليكم:

شكراً لكم جميعاً على كلامكم هذا وأرجو أن أكون عند حسن ظنكم، وسأتابع قريباً إن شاء الله.


----------



## محمود الصقار (26 مايو 2010)

السلام عليكم مهندس عبد الجواد 

جزاك الله خيرا ,أنت عند حسن الظن

محمود الصقار


----------



## محمود الصقار (27 مايو 2010)

السلام عليكم

ننتظر مشاركاتك الرائعة مهندسنا العظيم عبد الجواد, بكل إشتياق

محمود الصقار


----------



## عبد الجواد (27 مايو 2010)

أهلاً أستاذ محمود، أنا الآن أقوم بكتابة شرح خوارزمية حل جملة معادلات خطية مع مثال يدوي وبرنامج حاسوبي، ولا أدري إن كان بمقدوري إضافتها اليوم أو يوم السبت، لأنني أتعذب بكتابة المصفوفات والمعادلات، وسأضعها في موضوع مستقل إن شاء الله وسأشير إليه هنا.


----------



## عبد الجواد (30 مايو 2010)

السلام عليكم:

قمت بإضافة شرح خوارزمية حل مجموعة معادلات خطية بطريقة غوص على هذا الرابط:
http://www.arab-eng.org/vb/t201585.html

وتم إرفاق مثال يدوي مع برنامج بلغة VB6 في تلك المشاركة.
وسأقوم الآن بشرح الاختلاف البسيط بين ذلك البرنامج والبرنامج الجزئي المدمج مع برنامج الجوائز الشبكية وهو موضوع دراستنا.

إن كلي البرنامجين يستخدم طريقة غوص، لذلك فإن هناك تشابهاً كبيراً بينهما، وأهم الفروق:

1- اسم البرنامج هناك EquationsGauss وهنا Equations وهذا فرق غير مهم.

2- هناك برنامج EquationsGauss هو تابع مغلق على نفسه، نمرر له مصفوفة الأمثال كبارامتر فيعيد لنا قيمة المجاهيل كشعاع، أما هنا فإن برنامج Equations هو برنامج جزئي (Sub) لا نمرر له شيئاً إنما يقوم بالعمليات الحسابية على مصفوفة الصلابة المعدلة K المعرفة تعريفاً عاماً، ويضع الناتج في الشعاع defl أيضاً المعرف تعريفاً عاماً، على اعتبار أن نتيجة حل المعادلات هي الانتقالات العقدية وفق درجات الحرية.

3- تم تغيير أسماء بعض المتحولات، وهذا أيضاً فرق غير مهم لكن أشرت إلى هذا الفرق للانتباه فقط.

هذه أهم الفروق، والمهم هنا أن نعلم أنه بعد حل جملة المعادلات نحصل على النتيجة وهي الانتقالات العقدية في الشعاع defl.

ملاحظة هامة:
أشرت سابقاً إلى أنه يمكننا ضغط مصفوفة الصلابة عن طريق تخزين نصفها فقط بسبب التناظر، أو ضغطها أكثر عن طريق تخزين مصفوفة شريطية، وفي هذه الحالة فإنه يجب تعديل خوارزمية حل جملة المعادلات المشروحة، لتتوافق مع التغييرات على تخزين مصفوفة الصلابة.

بعد أن حصلنا على الانتقالات العقدية يبقى علينا حساب القوى الداخلية في العناصر، قريباً إن شاء الله.


----------



## محمود الصقار (31 مايو 2010)

السلام عليكم و رحمة الله و بركاته

جزاك الله خيرا أخى و أستاذى مهندس عبد الجواد , و أدعو الله أن يوفقك فى الدارين

و أن يزيدك علما و عملا

و فى إنتظار مشاركاتك دائما

محمود الصقار


----------



## محمود الصقار (1 يونيو 2010)

السلام عليكم و رحمة الله و بركاته

أخينا و أستاذنا عبد الجواد ننتظر دائما شرحك الجميل

محمود الصقار


----------



## عبد الجواد (1 يونيو 2010)

السلام عليكم:

وصلنا الآن إلى البرنامج الجزئي CalcForces، وهو لحساب القوى الداخلية.

بعد أن حسبنا الانتقالات العقدية وفق المحاور العامة، نحول هذه الانتقالات لكل عنصر وفق محاوره الخاصة.

بما أن العنصر شبكي أي يخضع لحمولة ناظمية فقط، فإن الانتقال المهم هو الانتقال وفق محوره، ويمكن حسابها كما في الشكل:







في الشكل u1,v1 هي انتقالات عقدة البداية وفق جملة المحاور العامة، و u2,v2 لعقدة النهاية.

وحسب برنامجنا فإن درجة الحرية المرتبطة ب u1 هي:


```
DOF for u1 = 2 * mem(i, 1) - 1     DOF = degree of freedom
DOF for v1 = 2 * mem(i, 1)
DOF for u2 = 2 * mem(i, 2) - 1
DOF for v2 = 2 * mem(i, 2)
```

حيث i هو رقم العنصر.

لذلك فإن:

```
u1 = defl(2 * mem(i, 1) - 1)
v1 = defl(2 * mem(i, 1)
u2 = defl(2 * mem(i, 2) - 1)
v2 = defl(2 * mem(i, 2)
```

فإذا فرضنا أن d1 هو انتقال عقدة البداية وفق محور العنصر، وd2 انتقال عقدة النهاية فإن:


```
d1 = u1 * cos(theta) + v1 * sin(theta)
d2 = u2 * cos(theta) + v2 * sin(theta)
```

ويكون تطاول العنصر يساوي:


```
d = d2 - d1
```

فإذا علم التطاول (أو التقاصر إذا كان سالباً) علمت القوة الداخلية:


```
F = d.E.A/L
```

وكود البرنامج هو:


```
SUB CalcForces
    FOR i = 1 TO nom
        d1 = defl(2 * mem(i, 1) - 1) * MC(i) + defl(2 * mem(i, 1)) * MS(i)
        d2 = defl(2 * mem(i, 2) - 1) * MC(i) + defl(2 * mem(i, 2)) * MS(i)
        d = d2 - d1
        f(i) = d * ME(i) * MA(i) / ML(i)
    NEXT
END SUB
```

تذكر أننا حسبنا MC و MS في خطوة سابقة وهما يعبران عن تجيب وجيب الزاوية بين العنصر والمحور x.

بقي أن نطبع هذه القوى عن طريق البرنامج الجزئي PrintForces وهو:






كما قلت هذا البرنامج للطباعة فقط، وليس من المهم شرحه برمجياً (خاصة أن لغة QB قد تم تنسيقها)، وهو سيقوم بطباعة صفحة فيها رقم العنصر والقوة فيه وينتظر تدخل المستخدم، فإن ضغط H ينتقل إلى صفحة سابقة، وإذا ضغط P ينتقل إلى الصفحة التالية وإذا ضغط Esc يخرج من البرنامج.
وفي الحقيقة لا أذكر لماذا اخترت هذه الأحرف، فهي بالنسبة لي الآن غير معبرة!!!

أخيراً أرجو أن أكون قد وفقت في شرح البرنامج، وسأحاول أن أؤمن ملف البرنامج بلغة QB حتى لو أعدت كتابته، فكما قلت سابقاً، لم أجده عندي!!!


----------



## محمود الصقار (2 يونيو 2010)

السلام عليكم و رحمة الله و بركاته

جزاك الله خيرا أخى و أستاذى المهندس عبد الجواد , وفيت و كفيت , نحن نعرف لأهل الفضل فضله

ننتظر منك البرنامج

و ننتظر فتح موضوع جديد تحب أن تشرحه أنت فى هذه السلسلة التى تعود على الأمة بالخير الكثير

لا أنسى أن أذكر أخوانى الأعزاء بالدعاء للمهندس عبد الجواد بظهر الغيب فهو يستحق كل خير

فجزاك الله خيرا عن كل من تابع أو من سيتابع هذه السلسة فى المستقبل 

كنت أأمل من أخينا المهندس أبو الحلول - و جزاه الله خيرا على سرعة الأستجابة- أن يضع هذا الموضوع داخل موضوعه شروحات حتى يبقى محفوظا 

محمود الصقار


----------



## عبد الجواد (2 يونيو 2010)

السلام عليكم:

أعدت إنشاء ملف البرنامج على QBasic وهو في الملف المضغوط في المرفقات.
ضمن الملف أيضاً، مثال لجائز شبكي مع الحل عن طريق البرنامج في ملف فيديو (فلاش).
لتشغيل ملف الفيديو، يمكنك تشغيل الملف Truss2DSample.swf مباشرة باستخدام أي برنامج يدعم تشغيل ملفات فلاش، أو عن طريق تشغيل الملف Truss2DSample.htm بشرط وضع الملفين معاً في مكان واحد.

أما المثال فهو:
المطلوب تحليل الجائز الشبكي التالي باستخدام البرنامج السابق، مع العلم أن الجائز مقرر (لتسهيل مقارنته مع الحل اليدوي)






إن المعطيات التي سيتم إدخالها مبينة في الجدول التالي (مع العلم أن القوى الداخلية في العناصر تم حسابها يدوياً، وكانت مطابقة للبرنامج كما هو مبين في ملف الفيديو المرفق ضمن الملف المضغوط):






أخيراً، أرجو ممن جرب البرنامج ووجد فيه خطأً حسابياً ما، أن ينبهنا إلى هذا الخطأ هنا لنقوم بتصحيحه.

وأذكّر أنني قد كتبت البرنامج السابق منذ عشر سنوات أو أكثر، ولو قدّر لي أن أعيد كتابة هذا البرنامج الآن لكتبته بأسلوب مختلف.

والحمد لله رب العالمين​


----------



## محمود الصقار (3 يونيو 2010)

السلام عليكم و رحمة الله و بركاته

أستاذنا و أخينا المهندس عبد الجواد , جزاك الله خير الجزاء , و عفا عنك 

و الله لا نملك إلا أن نمد يدنا لندعو لك 

و ما أعجبنى فى شرحك : العلم و الطريقة الجميلة و السهلة لتوصيل المعلومة و إتقان العمل 

أرجو أن نتوصل معك فى شروحات أخرى , فقد تعودت أن أفتح النت لأبحث عن علمك يوميا , فلا تحرمنا ذلك

و أنا سأحاول كما أخبرتك فى البداية أن أسجل فيديو له علاقة بهذا الموضوع , عسى الله أن ينفع به نفسا ميتا , و أن نحى أمتنا

محمود الصقار


----------



## عبد الجواد (3 يونيو 2010)

شكراً أخ محمود على كلامك هذا، وبانتظار الفيديو...


----------



## Abo Fares (5 يونيو 2010)

محمود الصقار قال:


> السلام عليكم و رحمة الله و بركاته
> 
> جزاك الله خيرا أخى و أستاذى المهندس عبد الجواد , وفيت و كفيت , نحن نعرف لأهل الفضل فضله
> 
> ...



بارك الله بكم م. محمود.. 

تم تثبيت الموضوع في الرابط التالي: 

http://www.arab-eng.org/vb/t165572.html

نشكر جميعاً الأخ عبد الجواد جزيل الشكر على موضوعه الأكثر من رائع، بارك الله به، ووفقنا وإياه لما يحب ويرضى من القول والعمل الصالح.. 

خالص التحيــــــــات..​


----------



## samer kamel ali (8 يونيو 2010)

جزاك الله يا بشمهندس


----------



## mohy_y2003 (8 يونيو 2010)

جزاكم الله خيراً علي هذا الموضوع الرائع - واحنا كل يوم في المنتدي بنتكشف قامات عربيه في امتنا - ونسال الله ان ينفع الامه بهم ونسال الله لك التوفيق والسداد يا اخ عبد الجواد وان يجعله في ميزان حسناتك


----------



## عبد الجواد (9 يونيو 2010)

أشكر جميع الإخوة على دعائهم، وأطلب منهم أن يزيدوا منه في سرهم فأنا بأمس الحاجة إليه، وأرجو الله أن يعينني على السير في نفس الطريق.


----------



## Hussein.Rida (10 يونيو 2010)

الأخ الغالي عبد الجواد,

بارك الله فيك وفي مجهودك الكبير ونفع بك

هذه مجموعة من الصور لبرنامج بسيط لحل الجوائز الشبكية مكتوب بلغة الفيجول بيسك وهو متاح مع السورس كود مجاناً لمن يريد الاستفادة منه والتعديل عليه






















رابط تحميل البرنامج مع الخوارزمية:

http://www.4shared.com/file/J35VNcVL/2D_Truss_Solver_-_Stiffness_Ma.html


----------



## Hussein.Rida (11 يونيو 2010)

كلمة سر فك الملف المضغوط المشار إليه في الرد السابق هي:

engineering-gate


----------



## عبد الجواد (11 يونيو 2010)

السلام عليكم:

شكراً أخ حسين على هذه المساهمة، وسأطلع على البرنامج قريباً إن شاء الله


----------



## محمود الصقار (11 يونيو 2010)

السلام عليكم و رحمة الله و بركاته

ما أجمل أن نرى المتميزين فى هذا المجال هم من يتكلمون فقط

رائع مهندس عبد الجواد و رائع مهندس حسين رضا 

و فى ذلك فليتنافس المتنافسون

إن شاء الله سأقوم بقرأة البرنامج مع أستاذنا المهندس عبد الجواد لنتعلم منكما

ننتظر منكما المزيد

ربنا يعزكم و يعز بكما الأسلام

محمود الصقار


----------



## Hussein.Rida (12 يونيو 2010)

هذه مجموعة من الصور لبرنامج أكثر تقدمأ من البرنامج الذي ذكرته في مداخلتي السابقة
وهو يقوم بتحليل الجوائز الشبكية والإطارات بشكلها المبسط
الشيئ المهم في هذا البرنامج هو بيئة الرسم التفاعلية والتي تتيح فاعلية أكبر للمستخدم يستطيع عن طريقها إدخال بياناته رسوميا وهي طريقة ممتعة أكثر من إدخال البيانات باستعمال الكائنات النصية
البيئة الرسومية في هذا البرنامج تمت برمجتها وإعدادها من الصفر بدون استخدام أي مكتبة رسومية جاهزة
أعرف أن جميع الأخوة هم على ألفة تامة بلغة الفيجول بيسك 6 أو الكيو بيسك, لكن أعذروني لأن البرنامج مكتوب بلغة السي شارب
سأقوم بسرد الشيفرة البرمجية تباعا ولكن بدون شرح وذلك لضيق الوقت أولاً وحتى لا أكرر الشرح المسهب والرائع الذي قدمه لنا أستاذنا عبد الجواد




































الشيفرة البرمجية الكاملة لحل الجائز الشبكي

```
private void Analysis2DTruss()
{
lstReport.Items.Add("Begin Analysis at : " + DateTime.Now.ToLongTimeString());
lstReport.Items.Add("");
lstReport.Items.Add("Type of structure :\t2D Truss");
lstReport.Items.Add("Number of Degrees of Freedom per Joint NDFJ = 2");
lstReport.Items.Add("");
// Output geometry Data 
lstReport.Items.Add("Geometry");
//Read Joints data
lstReport.Items.Add("\tJoints Data :");
lstReport.Items.Add("\tNumber of Joints = " + frmMain.frmgeometry.DrawArea.Nodes.Count.ToString());
lstReport.Items.Add("\tJoint\tX-Coor\tY-Coor\tRestraints\tLoad-Fx\tLoad-Fy");
for(int i=0; i<frmMain.frmgeometry.DrawArea.Nodes.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].X.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].Y.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].UX.ToString()+" - "+frmMain.frmgeometry.DrawArea.Nodes[i].UY.ToString()+"\t\t"+frmMain.frmgeometry.DrawArea.Nodes[i].FX.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].FY.ToString());
}

//Read Memebers Data
lstReport.Items.Add("");
lstReport.Items.Add("\tMemebers Data :");
lstReport.Items.Add("\tNumber of Memebers = " + frmMain.frmgeometry.DrawArea.Elements.Count.ToString());
lstReport.Items.Add("\tMemebers\tI-Begin\tJ-End\tSection");
for(int i=0; i<frmMain.frmgeometry.DrawArea.Elements.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString()+"\t\t"+frmMain.frmgeometry.DrawArea.Elements[i].StartNode.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Elements[i].EndNode.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Elements[i].SectionName.ToString());
} 

//Number of Equations
lstReport.Items.Add("");
int NumberOfEquations = 2*frmMain.frmgeometry.DrawArea.Nodes.Count;
lstReport.Items.Add("Number of Equations = " + NumberOfEquations);
//---------------------------------------------------------------
//Begin Analysis
//---------------------------------------------------------------
Geometry.NodeCollections Joints = new Geometry.NodeCollections();
Joints = frmMain.frmgeometry.DrawArea.Nodes;
Geometry.ElementCollections Members = new Geometry.ElementCollections();
Members = frmMain.frmgeometry.DrawArea.Elements;

int NumberofJoints = Joints.Count;
int NumberofElements = Members.Count;
double[] LoadsVector = new double[NumberOfEquations];
double[,] Reactions = new double [NumberofJoints,2];
//---------------------------
//Initialize Reactions Matrix & Loads Vector
//---------------------------
for(int i=0; i<NumberofJoints; i++)
{
LoadsVector[2*i] = Joints[i].FX;
LoadsVector[2*i+1] = Joints[i].FY;
if(Joints[i].UX == 1 && Joints[i].FX != 0)
Reactions[i,0] = -1*Joints[i].FX;
if(Joints[i].UY == 1 && Joints[i].FY != 0)
Reactions[i,1] = -1*Joints[i].FY;
}

//--------------------------------
//Generate UnRestrained Global Stiffness Matrix
//--------------------------------
double[,] EK = new double[4,4]; //Member Stiffness Matrix
double[,] GK = new double[NumberOfEquations,NumberOfEquations]; // Global Stiffness Matrix
double MemberLength =0; //Length of Member
double CX =0; // Cosine of Member Direction
double CY =0; // Sine of Member Direction
double XL =0; // Projection of length on X Direction
double YL =0; // Projection of length on Y Direction 
double AEOL =0; //AE/L
double CXX =0; //(AE/L) * Cos^2
double CYY =0; //(AE/L) * Sin^2
double CXY =0; //(AE/L) * Cos * Sin
int i0=0,i1=0,j0=0,j1=0; //Position Of Member Stiffness Matrix in Global Stiffness Matrix
int c1 =0;
for(int i=0; i<NumberofElements; i++)
{
XL = Joints[Members[i].EndNode].X - Joints[Members[i].StartNode].X;
YL = Joints[Members[i].EndNode].Y - Joints[Members[i].StartNode].Y;
MemberLength = Math.Sqrt(Math.Pow(XL,2)+Math.Pow(YL,2));
CX = XL / MemberLength;
CY = YL / MemberLength;
c1=Convert.ToInt32(Definitions.Sections.Rows[Members[i].SectionID][3])-1;
AEOL = Convert.ToDouble(Definitions.Sections.Rows[Members[i].SectionID][4])* Convert.ToDouble(Definitions.Materials.Rows[c1][2])/MemberLength;
CXX = AEOL * Math.Pow(CX,2);
CYY = AEOL * Math.Pow(CY,2);
CXY = AEOL * CX * CY;
// Member Stiffness Matrix
EK[0,0] = CXX ; EK[0,1] = CXY ; EK[0,2] = -CXX; EK[0,3] = -CXY;
EK[1,0] = CXY ; EK[1,1] = CYY ; EK[1,2] = -CXY; EK[1,3] = -CYY;
EK[2,0] = -CXX; EK[2,1] = -CXY; EK[2,2] = CXX ; EK[2,3] = CXY;
EK[3,0] = -CXY; EK[3,1] = -CYY; EK[3,2] = CXY ; EK[3,3] = CYY;
//Set Member Position
i0 = Members[i].StartNode*2; i1 = Members[i].StartNode*2+1;
j0 = Members[i].EndNode*2; j1 = Members[i].EndNode*2+1;
//Put Member Stiffness Matrix in Global Stiffness Matrix
GK[i0,i0] = GK[i0,i0]+EK[0,0]; GK[i0,i1] = GK[i0,i1]+EK[0,1]; GK[i0,j0] = GK[i0,j0]+EK[0,2]; GK[i0,j1] = GK[i0,j1]+EK[0,3];
GK[i1,i0] = GK[i1,i0]+EK[1,0]; GK[i1,i1] = GK[i1,i1]+EK[1,1]; GK[i1,j0] = GK[i1,j0]+EK[1,2]; GK[i1,j1] = GK[i1,j1]+EK[1,3];
GK[j0,i0] = GK[j0,i0]+EK[2,0]; GK[j0,i1] = GK[j0,i1]+EK[2,1]; GK[j0,j0] = GK[j0,j0]+EK[2,2]; GK[j0,j1] = GK[j0,j1]+EK[2,3];
GK[j1,i0] = GK[j1,i0]+EK[3,0]; GK[j1,i1] = GK[j1,i1]+EK[3,1]; GK[j1,j0] = GK[j1,j0]+EK[3,2]; GK[j1,j1] = GK[j1,j1]+EK[3,3]; 
}
//--------------------------------------------------------------
//Consider Boundary Conditions to Reduce Global Stiffness Matrix
//--------------------------------------------------------------
for(int i=0; i<Joints.Count; i++)
{ 
if(Joints[i].UX==1)
{
i0 = i*2;
for(int j=0; j<NumberOfEquations; j++)
{
GK[i0,j]=0; GK[j,i0]=0;
}
GK[i0,i0]=1;
LoadsVector[i0]=0;
}
if(Joints[i].UY==1)
{
i1 = i*2+1;
for(int j=0; j<NumberOfEquations; j++)
{
GK[i1,j]=0; GK[j,i1]=0;
}
GK[i1,i1]=1;
LoadsVector[i1]=0;
}
}
//------------------------------
//Claculate Joints Displacements
//------------------------------
double[] Displacements = new double[NumberOfEquations]; //initialize displacements vector
//Use Guass Solution to solve the problem
double c =0;
for(int i=0; i<NumberOfEquations; i++)
{
for(int j=i+1; j<NumberOfEquations; j++)
{
if(GK[j,i] !=0)
{
c = -GK[i,i]/GK[j,i];
for(int s=0; s<NumberOfEquations; s++)
{
GK[j,s] = c * GK[j,s] + GK[i,s];
}
LoadsVector[j] = c * LoadsVector[j] + LoadsVector[i];
}
}
}
bool NoneStability = false;
double x =0;
for(int i=NumberOfEquations-1; i>=0; i--)
{
if(GK[i,i] !=0)
{
x = 0;
for(int j=NumberOfEquations-1; j>=i+1; j--)
{
x+= GK[i,j] * Displacements[j];
}
Displacements[i] = (LoadsVector[i]-x)/GK[i,i];
}
else
{
// Structure is unstable
NoneStability = true;
break;
}
}

if(NoneStability)
{
MessageBox.Show("Structure is unstable","Warning",MessageBoxButtons.OK,MessageBoxIcon.Warning); 
}
else
{
//Calculate Members Forces (Tension Posetive) , and Reactions
double[] MemberForces = new double[NumberofElements];
for (int i=0; i<Members.Count; i++)
{
//Calculate Members Forces
XL = Joints[Members[i].EndNode].X - Joints[Members[i].StartNode].X;
YL = Joints[Members[i].EndNode].Y - Joints[Members[i].StartNode].Y;
MemberLength = Math.Sqrt(Math.Pow(XL,2)+Math.Pow(YL,2));
CX = XL / MemberLength;
CY = YL / MemberLength;
c1=Convert.ToInt32(Definitions.Sections.Rows[Members[i].SectionID][3])-1;
AEOL = Convert.ToDouble(Definitions.Sections.Rows[Members[i].SectionID][4])* Convert.ToDouble(Definitions.Materials.Rows[c1][2])/MemberLength;
CXX = AEOL * Math.Pow(CX,2);
CYY = AEOL * Math.Pow(CY,2);
CXY = AEOL * CX * CY;
MemberForces[i] = AEOL*(CX*(Displacements[Members[i].EndNode*2]-Displacements[Members[i].StartNode*2])+CY*(Displacements[Members[i].EndNode*2+1]-Displacements[Members[i].StartNode*2+1]));

//Calculate Reactions
if(Joints[Members[i].StartNode].UX == 1)
Reactions[Members[i].StartNode,0] -= CX * MemberForces[i];
if(Joints[Members[i].StartNode].UY == 1)
Reactions[Members[i].StartNode,1] -= CY * MemberForces[i];
if(Joints[Members[i].EndNode].UX == 1)
Reactions[Members[i].EndNode,0] += CX * MemberForces[i];
if(Joints[Members[i].EndNode].UY == 1)
Reactions[Members[i].EndNode,1] += CY * MemberForces[i];
}
//Output Results
//Print Joint Displacements
lstReport.Items.Add("");
lstReport.Items.Add("Joint Displacements");
lstReport.Items.Add("\tJoint\tX-Dis\t\tY-Dis");
for(int i=0; i<Joints.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + Displacements[i*2].ToString("E") + "\t" + Displacements[i*2+1].ToString("E"));
}
//Print Member Forces
lstReport.Items.Add("");
lstReport.Items.Add("Member Forces");
lstReport.Items.Add("\tMember\tAxial Force");
for(int i=0; i<Members.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + MemberForces[i].ToString("0.000"));
}
//Print Joints Reactions
lstReport.Items.Add("");
lstReport.Items.Add("Joint Reactions");
lstReport.Items.Add("\tJoint\tRX\tRY");
for(int i=0; i<Joints.Count; i++)
{
if(Reactions[i,0] !=0 || Reactions[i,1] !=0)
lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + Reactions[i,0].ToString("0.000") + "\t" + Reactions[i,1].ToString("0.000"));
}
}
}
```


----------



## محمود الصقار (12 يونيو 2010)

الله الله الله الله

السلام عليكم و رحمة الله و بركاته

جزاكم الله خيرا أستاذنا مهندس عبد الجواد و مهندسنا المتميز دائما كما تعودت أن ألقبه

و لكن هناك سؤال , أنا إلى الأن لم أقرأ ال c sharp , ما هى المميزات التى تعطيها لى ال c sharp و لا يعطيها لنا ال visual basic , ثم هل هناك شرح بسيط لهذه اللغة ؟

محمود الصقار


----------



## لؤي الماحي (14 يونيو 2010)

مشكووووووووووووووووووووووووووور


----------



## Hussein.Rida (14 يونيو 2010)

بالنسبة لسؤالك أخي محمود حول الفرق بين الفيجول بيسك والسي شارب يمكنك الرجوع للمقالة التالية (أتمنى أن تفيدك بعض الشيء):

http://www.parmaja.com/forums/viewtopic.php?id=14


خوارزمية حل الإطارات باستخدام طريقة مصفوفة القساوة:
Algorithm to solve Plane-Frame by using stiffness matrix method​
```
private void Analysis2DFrame()
{
lstReport.Items.Add("Begin Analysis at : " + DateTime.Now.ToLongTimeString());
lstReport.Items.Add("");
lstReport.Items.Add("Type of structure :\t2D Frame");
lstReport.Items.Add("Number of Degrees of Freedom per Joint NDFJ = 3");
lstReport.Items.Add("");
// Output geometry Data 
lstReport.Items.Add("Geometry");
//Read Joints data
lstReport.Items.Add("\tJoints Data :");
lstReport.Items.Add("\tNumber of Joints = " + frmMain.frmgeometry.DrawArea.Nodes.Count.ToString());
lstReport.Items.Add("\tJoint\tX-Coor\tY-Coor\tRestraints\tLoad-Fx\tLoad-Fy\tMoment-Mz");
for(int i=0; i<frmMain.frmgeometry.DrawArea.Nodes.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].X.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].Y.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].UX.ToString()+" - "+frmMain.frmgeometry.DrawArea.Nodes[i].UY.ToString()+" - "+frmMain.frmgeometry.DrawArea.Nodes[i].RZ.ToString()+"\t\t"+frmMain.frmgeometry.DrawArea.Nodes[i].FX.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].FY.ToString()+"\t"+frmMain.frmgeometry.DrawArea.Nodes[i].MZ.ToString());
}

//Read Memebers Data
lstReport.Items.Add("");
lstReport.Items.Add("\tMemebers Data :");
lstReport.Items.Add("\tNumber of Memebers = " + frmMain.frmgeometry.DrawArea.Elements.Count.ToString());
lstReport.Items.Add("\tMemebers\tI-Begin\tJ-End\tSection");
for(int i=0; i<frmMain.frmgeometry.DrawArea.Elements.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString()+"\t\t"+Convert.ToString(frmMain.frmgeometry.DrawArea.Elements[i].StartNode+1)+"\t"+Convert.ToString(frmMain.frmgeometry.DrawArea.Elements[i].EndNode+1)+"\t"+frmMain.frmgeometry.DrawArea.Elements[i].SectionName.ToString());
} 

//Number of Equations
lstReport.Items.Add("");
int NumberOfEquations = 3*frmMain.frmgeometry.DrawArea.Nodes.Count;
lstReport.Items.Add("Number of Equations = " + NumberOfEquations);
//---------------------------------------------------------------
//Begin Analysis
//---------------------------------------------------------------
Geometry.NodeCollections Joints = new Geometry.NodeCollections();
Joints = frmMain.frmgeometry.DrawArea.Nodes;
Geometry.ElementCollections Members = new Geometry.ElementCollections();
Members = frmMain.frmgeometry.DrawArea.Elements;

int NumberofJoints = Joints.Count;
int NumberofElements = Members.Count;
double[] LoadsVector = new double[NumberOfEquations];
double[,] Reactions = new double [NumberofJoints,3];
//---------------------------
//Initialize Reactions Matrix & Loads Vector
//---------------------------
for(int i=0; i<NumberofJoints; i++)
{
LoadsVector[3*i] = Joints[i].FX;
LoadsVector[3*i+1] = Joints[i].FY;
LoadsVector[3*i+2] = Joints[i].MZ;
if(Joints[i].UX == 1 && Joints[i].FX != 0)
Reactions[i,0] = -1*Joints[i].FX;
if(Joints[i].UY == 1 && Joints[i].FY != 0)
Reactions[i,1] = -1*Joints[i].FY;
if(Joints[i].RZ == 1 && Joints[i].MZ != 0)
Reactions[i,2] = -1*Joints[i].MZ;
}

double MemberLength =0; //Length of Member
double CX =0; // Cosine of Member Direction
double CY =0; // Sine of Member Direction
double XL =0; // Projection of length on X Direction
double YL =0; // Projection of length on Y Direction 
for(int i=0; i<Members.Count; i++)
{
if(Members[i].UniformLoad != 0)
{
XL = Joints[Members[i].EndNode].X - Joints[Members[i].StartNode].X;
YL = Joints[Members[i].EndNode].Y - Joints[Members[i].StartNode].Y;
MemberLength = Math.Sqrt(Math.Pow(XL,2)+Math.Pow(YL,2));
CX = XL / MemberLength;
CY = YL / MemberLength;
LoadsVector[Members[i].StartNode*3]+=Members[i].UniformLoad*MemberLength*CY/2;
LoadsVector[Members[i].StartNode*3+1]+=-Members[i].UniformLoad*MemberLength*CX/2;

LoadsVector[Members[i].EndNode*3]+=Members[i].UniformLoad*MemberLength*CY/2;
LoadsVector[Members[i].EndNode*3+1]+=-Members[i].UniformLoad*MemberLength*CX/2;
if(Joints[Members[i].StartNode].X < Joints[Members[i].EndNode].X)
{
LoadsVector[Members[i].StartNode*3+2]+=-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
LoadsVector[Members[i].EndNode*3+2]+=Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].X > Joints[Members[i].EndNode].X)
{
LoadsVector[Members[i].StartNode*3+2]+=Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
LoadsVector[Members[i].EndNode*3+2]+=-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].Y<Joints[Members[i].EndNode].Y)
{
LoadsVector[Members[i].StartNode*3+2]+=-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
LoadsVector[Members[i].EndNode*3+2]+=Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else
{
LoadsVector[Members[i].StartNode*3+2]+=Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
LoadsVector[Members[i].EndNode*3+2]+=-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
}
}
//--------------------------------
//Generate UnRestrained Global Stiffness Matrix
//--------------------------------
double[,] EK = new double[6,6]; //Member Stiffness Matrix
double[,] GK = new double[NumberOfEquations,NumberOfEquations]; // Global Stiffness Matrix
double AEOL =0; // AE/L
double CXX =0; // Cos^2
double CYY =0; // Sin^2
double CXY =0; // Cos * Sin
double EI2 =0; // 2EI/L
double EI4 =0; // 4EI/L
double EI6 =0; // 6EI/L2
double EI12 =0; // 12EI/L3
int i0=0,i1=0,i2=0,j0=0,j1=0,j2=0; //Position Of Member Stiffness Matrix in Global Stiffness Matrix
int c1=0;
for(int i=0; i<NumberofElements; i++)
{
XL = Joints[Members[i].EndNode].X - Joints[Members[i].StartNode].X;
YL = Joints[Members[i].EndNode].Y - Joints[Members[i].StartNode].Y;
MemberLength = Math.Sqrt(Math.Pow(XL,2)+Math.Pow(YL,2));
CX = XL / MemberLength;
CY = YL / MemberLength;
c1=Convert.ToInt32(Definitions.Sections.Rows[Members[i].SectionID][3])-1;
AEOL = Convert.ToDouble(Definitions.Sections.Rows[Members[i].SectionID][4])* Convert.ToDouble(Definitions.Materials.Rows[c1][2])/MemberLength;
EI2 = 2*Convert.ToDouble(Definitions.Sections.Rows[Members[i].SectionID][5])* Convert.ToDouble(Definitions.Materials.Rows[c1][2])/MemberLength;
EI4 = 2*EI2;
EI6 = 3*EI2/MemberLength;
EI12 = 2*EI6/MemberLength;
CXX = Math.Pow(CX,2);
CYY = Math.Pow(CY,2);
CXY = CX * CY;
// Member Stiffness Matrix
EK[0,0] = CXX*AEOL+CYY*EI12 ; EK[0,1] = CXY*AEOL-CXY*EI12 ; EK[0,2] = -CY*EI6; EK[0,3] = -CXX*AEOL-CYY*EI12; EK[0,4] = -CXY*AEOL+CXY*EI12; EK[0,5] = -CY*EI6;
EK[1,0] = CXY*AEOL-CXY*EI12 ; EK[1,1] = CYY*AEOL+CXX*EI12 ; EK[1,2] = CX*EI6 ; EK[1,3] = -CXY*AEOL+CXY*EI12; EK[1,4] = -CYY*AEOL-CXX*EI12; EK[1,5] = CX*EI6 ;
EK[2,0] = -CY*EI6 ; EK[2,1] = CX*EI6 ; EK[2,2] = EI4 ; EK[2,3] = CY*EI6 ; EK[2,4] = -CX*EI6 ; EK[2,5] = EI2 ;
EK[3,0] = -CXX*AEOL-CYY*EI12; EK[3,1] = -CXY*AEOL+CXY*EI12; EK[3,2] = CY*EI6 ; EK[3,3] = CXX*AEOL+CYY*EI12 ; EK[3,4] = CXY*AEOL-CXY*EI12; EK[3,5] = CY*EI6 ;
EK[4,0] = -CXY*AEOL+CXY*EI12; EK[4,1] = -CYY*AEOL-CXX*EI12; EK[4,2] = -CX*EI6; EK[4,3] = CXY*AEOL-CXY*EI12 ; EK[4,4] = CYY*AEOL+CXX*EI12; EK[4,5] = -CX*EI6;
EK[5,0] = -CY*EI6 ; EK[5,1] = CX*EI6 ; EK[5,2] = EI2 ; EK[5,3] = CY*EI6 ; EK[5,4] = -CX*EI6 ; EK[5,5] = EI4 ;
//Set Member Position
i0 = Members[i].StartNode*3; i1 = Members[i].StartNode*3+1; i2 = Members[i].StartNode*3+2;
j0 = Members[i].EndNode*3 ; j1 = Members[i].EndNode*3+1 ; j2 = Members[i].EndNode*3+2;
//Put Member Stiffness Matrix in Global Stiffness Matrix
GK[i0,i0] = GK[i0,i0]+EK[0,0]; GK[i0,i1] = GK[i0,i1]+EK[0,1]; GK[i0,i2] = GK[i0,i2]+EK[0,2]; GK[i0,j0] = GK[i0,j0]+EK[0,3]; GK[i0,j1] = GK[i0,j1]+EK[0,4]; GK[i0,j2] = GK[i0,j2]+EK[0,5];
GK[i1,i0] = GK[i1,i0]+EK[1,0]; GK[i1,i1] = GK[i1,i1]+EK[1,1]; GK[i1,i2] = GK[i1,i2]+EK[1,2]; GK[i1,j0] = GK[i1,j0]+EK[1,3]; GK[i1,j1] = GK[i1,j1]+EK[1,4]; GK[i1,j2] = GK[i1,j2]+EK[1,5];
GK[i2,i0] = GK[i2,i0]+EK[2,0]; GK[i2,i1] = GK[i2,i1]+EK[2,1]; GK[i2,i2] = GK[i2,i2]+EK[2,2]; GK[i2,j0] = GK[i2,j0]+EK[2,3]; GK[i2,j1] = GK[i2,j1]+EK[2,4]; GK[i2,j2] = GK[i2,j2]+EK[2,5];
GK[j0,i0] = GK[j0,i0]+EK[3,0]; GK[j0,i1] = GK[j0,i1]+EK[3,1]; GK[j0,i2] = GK[j0,i2]+EK[3,2]; GK[j0,j0] = GK[j0,j0]+EK[3,3]; GK[j0,j1] = GK[j0,j1]+EK[3,4]; GK[j0,j2] = GK[j0,j2]+EK[3,5];
GK[j1,i0] = GK[j1,i0]+EK[4,0]; GK[j1,i1] = GK[j1,i1]+EK[4,1]; GK[j1,i2] = GK[j1,i2]+EK[4,2]; GK[j1,j0] = GK[j1,j0]+EK[4,3]; GK[j1,j1] = GK[j1,j1]+EK[4,4]; GK[j1,j2] = GK[j1,j2]+EK[4,5];
GK[j2,i0] = GK[j2,i0]+EK[5,0]; GK[j2,i1] = GK[j2,i1]+EK[5,1]; GK[j2,i2] = GK[j2,i2]+EK[5,2]; GK[j2,j0] = GK[j2,j0]+EK[5,3]; GK[j2,j1] = GK[j2,j1]+EK[5,4]; GK[j2,j2] = GK[j2,j2]+EK[5,5]; 
}
//--------------------------------------------------------------
//Consider Boundary Conditions to Reduce Global Stiffness Matrix
//--------------------------------------------------------------
for(int i=0; i<Joints.Count; i++)
{ 
if(Joints[i].UX==1)
{
i0 = i*3;
for(int j=0; j<NumberOfEquations; j++)
{
GK[i0,j]=0; GK[j,i0]=0;
}
GK[i0,i0]=1;
LoadsVector[i0]=0;
}
if(Joints[i].UY==1)
{
i1 = i*3+1;
for(int j=0; j<NumberOfEquations; j++)
{
GK[i1,j]=0; GK[j,i1]=0;
}
GK[i1,i1]=1;
LoadsVector[i1]=0;
}
if(Joints[i].RZ==1)
{
i2 = i*3+2;
for(int j=0; j<NumberOfEquations; j++)
{
GK[i2,j]=0; GK[j,i2]=0;
}
GK[i2,i2]=1;
LoadsVector[i2]=0;
}
}
//------------------------------
//Claculate Joints Displacements
//------------------------------
double[] Displacements = new double[NumberOfEquations]; //initialize displacements vector
//Use Guass Solution to solve the problem
double c =0;
for(int i=0; i<NumberOfEquations; i++)
{
for(int j=i+1; j<NumberOfEquations; j++)
{
if(GK[j,i] !=0)
{
c = -GK[i,i]/GK[j,i];
for(int s=0; s<NumberOfEquations; s++)
{
GK[j,s] = c * GK[j,s] + GK[i,s];
}
LoadsVector[j] = c * LoadsVector[j] + LoadsVector[i];
}
}
}
bool NoneStability = false;
double x =0;
for(int i=NumberOfEquations-1; i>=0; i--)
{
if(GK[i,i] !=0)
{
x = 0;
for(int j=NumberOfEquations-1; j>=i+1; j--)
{
x+= GK[i,j] * Displacements[j];
}
Displacements[i] = (LoadsVector[i]-x)/GK[i,i];
}
else
{
// Structure is unstable
NoneStability = true;
break;
}
}

if(NoneStability)
{
MessageBox.Show("Structure is unstable","Warning",MessageBoxButtons.OK,MessageBoxIcon.Warning); 
}
else
{
//Calculate Members Forces and Reactions
double[] RXBegin = new double[NumberofElements];
double[] RXEnd = new double[NumberofElements];
double[] RYBegin = new double[NumberofElements];
double[] RYEnd = new double[NumberofElements];
double[] RZBegin = new double[NumberofElements];
double[] RZEnd = new double[NumberofElements];
double N1=0,N2=0;
double Q1=0,Q2=0;
double M1=0,M2=0;
for (int i=0; i<Members.Count; i++)
{ 
XL = Joints[Members[i].EndNode].X - Joints[Members[i].StartNode].X;
YL = Joints[Members[i].EndNode].Y - Joints[Members[i].StartNode].Y;
MemberLength = Math.Sqrt(Math.Pow(XL,2)+Math.Pow(YL,2));
CX = XL / MemberLength;
CY = YL / MemberLength;
c1=Convert.ToInt32(Definitions.Sections.Rows[Members[i].SectionID][3])-1;
AEOL = Convert.ToDouble(Definitions.Sections.Rows[Members[i].SectionID][4])* Convert.ToDouble(Definitions.Materials.Rows[c1][2])/MemberLength;
EI2 = 2*Convert.ToDouble(Definitions.Sections.Rows[Members[i].SectionID][5])* Convert.ToDouble(Definitions.Materials.Rows[c1][2])/MemberLength;
EI4 = 2*EI2;
EI6 = 3*EI2/MemberLength;
EI12 = 2*EI6/MemberLength;
CXX = Math.Pow(CX,2);
CYY = Math.Pow(CY,2);
CXY = CX * CY;
// Global Member Stiffness Matrix
EK[0,0] = CXX*AEOL+CYY*EI12 ; EK[0,1] = CXY*AEOL-CXY*EI12 ; EK[0,2] = -CY*EI6; EK[0,3] = -CXX*AEOL-CYY*EI12; EK[0,4] = -CXY*AEOL+CXY*EI12; EK[0,5] = -CY*EI6;
EK[1,0] = CXY*AEOL-CXY*EI12 ; EK[1,1] = CYY*AEOL+CXX*EI12 ; EK[1,2] = CX*EI6 ; EK[1,3] = -CXY*AEOL+CXY*EI12; EK[1,4] = -CYY*AEOL-CXX*EI12; EK[1,5] = CX*EI6 ;
EK[2,0] = -CY*EI6 ; EK[2,1] = CX*EI6 ; EK[2,2] = EI4 ; EK[2,3] = CY*EI6 ; EK[2,4] = -CX*EI6 ; EK[2,5] = EI2 ;
EK[3,0] = -CXX*AEOL-CYY*EI12; EK[3,1] = -CXY*AEOL+CXY*EI12; EK[3,2] = CY*EI6 ; EK[3,3] = CXX*AEOL+CYY*EI12 ; EK[3,4] = CXY*AEOL-CXY*EI12; EK[3,5] = CY*EI6 ;
EK[4,0] = -CXY*AEOL+CXY*EI12; EK[4,1] = -CYY*AEOL-CXX*EI12; EK[4,2] = -CX*EI6; EK[4,3] = CXY*AEOL-CXY*EI12 ; EK[4,4] = CYY*AEOL+CXX*EI12; EK[4,5] = -CX*EI6;
EK[5,0] = -CY*EI6 ; EK[5,1] = CX*EI6 ; EK[5,2] = EI2 ; EK[5,3] = CY*EI6 ; EK[5,4] = -CX*EI6 ; EK[5,5] = EI4 ;
//Set Member Position
i0 = Members[i].StartNode*3; i1 = Members[i].StartNode*3+1; i2 = Members[i].StartNode*3+2;
j0 = Members[i].EndNode*3 ; j1 = Members[i].EndNode*3+1 ; j2 = Members[i].EndNode*3+2;
RXBegin[i] = EK[0,0]*Displacements[i0]+EK[0,1]*Displacements[i1]+EK[0,2]*Displacements[i2]
+EK[0,3]*Displacements[j0]+EK[0,4]*Displacements[j1]+EK[0,5]*Displacements[j2];

RXEnd[i] = EK[3,0]*Displacements[i0]+EK[3,1]*Displacements[i1]+EK[3,2]*Displacements[i2]
+EK[3,3]*Displacements[j0]+EK[3,4]*Displacements[j1]+EK[3,5]*Displacements[j2];

RYBegin[i] = EK[1,0]*Displacements[i0]+EK[1,1]*Displacements[i1]+EK[1,2]*Displacements[i2]
+EK[1,3]*Displacements[j0]+EK[1,4]*Displacements[j1]+EK[1,5]*Displacements[j2];

RYEnd[i] = EK[4,0]*Displacements[i0]+EK[4,1]*Displacements[i1]+EK[4,2]*Displacements[i2]
+EK[4,3]*Displacements[j0]+EK[4,4]*Displacements[j1]+EK[4,5]*Displacements[j2];
RZBegin[i] = EK[2,0]*Displacements[i0]+EK[2,1]*Displacements[i1]+EK[2,2]*Displacements[i2]
+EK[2,3]*Displacements[j0]+EK[2,4]*Displacements[j1]+EK[2,5]*Displacements[j2];
RZEnd[i] = EK[5,0]*Displacements[i0]+EK[5,1]*Displacements[i1]+EK[5,2]*Displacements[i2]
+EK[5,3]*Displacements[j0]+EK[5,4]*Displacements[j1]+EK[5,5]*Displacements[j2];

//Calculate Member End Forces

//Calculate Reactions
// Begin Node
if(Joints[Members[i].StartNode].UX == 1)
Reactions[Members[i].StartNode,0] += RXBegin[i]-Members[i].UniformLoad*MemberLength*CY/2;
if(Joints[Members[i].StartNode].UY == 1)
Reactions[Members[i].StartNode,1] += RYBegin[i]+Members[i].UniformLoad*MemberLength*CX/2;

if(Joints[Members[i].StartNode].RZ == 1)
{
if(Joints[Members[i].StartNode].X < Joints[Members[i].EndNode].X)
{
Reactions[Members[i].StartNode,2] += RZBegin[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].X > Joints[Members[i].EndNode].X)
{
Reactions[Members[i].StartNode,2] += RZBegin[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].Y<Joints[Members[i].EndNode].Y)
{
Reactions[Members[i].StartNode,2] += RZBegin[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else
{
Reactions[Members[i].StartNode,2] += RZBegin[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
}

// End Node
if(Joints[Members[i].EndNode].UX == 1)
Reactions[Members[i].EndNode,0] += RXEnd[i]-Members[i].UniformLoad*MemberLength*CY/2;
if(Joints[Members[i].EndNode].UY == 1)
Reactions[Members[i].EndNode,1] += RYEnd[i]+Members[i].UniformLoad*MemberLength*CX/2;

if(Joints[Members[i].EndNode].RZ == 1)
{
if(Joints[Members[i].StartNode].X < Joints[Members[i].EndNode].X)
{
Reactions[Members[i].EndNode,2] += RZEnd[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].X > Joints[Members[i].EndNode].X)
{
Reactions[Members[i].EndNode,2] += RZEnd[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].Y<Joints[Members[i].EndNode].Y)
{
Reactions[Members[i].EndNode,2] += RZEnd[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else
{
Reactions[Members[i].EndNode,2] += RZEnd[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
}
}
//Output Results
//Print Joint Displacements
lstReport.Items.Add("");
lstReport.Items.Add("Joint Displacements");
lstReport.Items.Add("\tJoint\tX-Dis\t\tY-Dis\t\tZ-Rot");
for(int i=0; i<Joints.Count; i++)
{
lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + Displacements[i*3].ToString("E") + "\t" + Displacements[i*3+1].ToString("E") + "\t" + Displacements[i*3+2].ToString("E"));
}
//Print Member End Forces
lstReport.Items.Add("");
lstReport.Items.Add("Member End Loads");
lstReport.Items.Add("\tMember\tNode\tN\tQ\tM");
for(int i=0; i<Members.Count; i++)
{
XL = Joints[Members[i].EndNode].X - Joints[Members[i].StartNode].X;
YL = Joints[Members[i].EndNode].Y - Joints[Members[i].StartNode].Y;
MemberLength = Math.Sqrt(Math.Pow(XL,2)+Math.Pow(YL,2));
CX = XL / MemberLength;
CY = YL / MemberLength;

N1 = RXBegin[i]*CX+RYBegin[i]*CY;
Q1 = RYBegin[i]*CX-RXBegin[i]*CY + Members[i].UniformLoad*MemberLength/2; 
if(Joints[Members[i].StartNode].X < Joints[Members[i].EndNode].X)
{
M1 = RZBegin[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].X > Joints[Members[i].EndNode].X)
{
M1 = RZBegin[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].Y<Joints[Members[i].EndNode].Y)
{
M1 = RZBegin[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else
{
M1 = RZBegin[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}


N2 = RXEnd[i]*CX+RYEnd[i]*CY;
Q2 = RYEnd[i]*CX-RXEnd[i]*CY + Members[i].UniformLoad*MemberLength/2;
if(Joints[Members[i].StartNode].X < Joints[Members[i].EndNode].X)
{
M2 = RZEnd[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].X > Joints[Members[i].EndNode].X)
{
M2 = RZEnd[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else if(Joints[Members[i].StartNode].Y<Joints[Members[i].EndNode].Y)
{
M2 = RZEnd[i]-Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}
else
{
M2 = RZEnd[i]+Members[i].UniformLoad*Math.Pow(MemberLength,2)/12;
}

lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + Members[i].StartNode.ToString() + "\t" + N1.ToString("0.000") + "\t" + Q1.ToString("0.000") + "\t" + M1.ToString("0.000"));
lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + Members[i].EndNode.ToString() + "\t" + N2.ToString("0.000") + "\t" + Q2.ToString("0.000") + "\t" + M2.ToString("0.000"));
}
//Print Joints Reactions
lstReport.Items.Add("");
lstReport.Items.Add("Joint Reactions");
lstReport.Items.Add("\tJoint\tRX\tRY\tRZ");
for(int i=0; i<Joints.Count; i++)
{
if(Reactions[i,0] !=0 || Reactions[i,1] !=0)
lstReport.Items.Add("\t"+(i+1).ToString() + "\t" + Reactions[i,0].ToString("0.000") + "\t" + Reactions[i,1].ToString("0.000") + "\t" + Reactions[i,2].ToString("0.000"));
}
}
}
```


----------



## Eng Ma7moud (14 يونيو 2010)

جزاك الله كل خير


----------



## عبد الجواد (17 يونيو 2010)

السلام عليكم:

أخ حسين، أكرر شكري لك مرة أخرى على إغناء الموضوع، وأشكرك على البرنامج الذي وضعت الكود له، ويكفي أنه مفتوح المصدر ليكون جيداً ونقطة بدء لكل من يريد تطوير مثل هذا البرنامج، وفي الحقيقة لم أجربه لأن VB6 غير مثبتة لدي، فهي لا تعمل جيداً في Windows 7 وقد طلقتها منذ زمن، لا لضعفها أو قلة جمالها، ولكن لوجود من هي أجمل منها وأقوى منها VB.Net، وقد اطلعت على الملفات عن طريق Notepad.

إن أحببت أن أضع ملاحظات عليه فهي (وإن كانت شكلية):
- الكود طويل بعض الشيء وفيه خطوات كثيرة غير ضرورية
- كود قلب المصفوفة أيضاً طويل ويمكنك اختصاره كثيراً
- الكود غير مرتب بشكل جيد، وترتيب الكود ضروري للتعديل لاحقاً.

هذه الملاحظات هي لإغناء البرنامج الذي تشكر عليه وكما قلت يكفي أنه مفتوح المصدر، وأنصح كل من يريد البرمجة أن يقرأه.

وجواباً للأخ محمود حول استخدام VB.Net أو #C، كلاهما بنفس القوة والسرعة والفروق بينهما بسيطة للمستخدم المبتدئ والمتوسط وحتى المتقدم، الفروق هي في عبارات البرمجة الأساسية فقط أما الأسلوب فواحد والمكتبات المستخدمة واحدة، وبيئة العمل واحدة.
إن كنت تعمل سابقاً على VB6 فعليك ب VB.Net وإن كنت تعمل على C أو ++C فعليك ب #C أو VB.Net.
ويمكنك لاحقاً -إذا أردت- التحويل بين هاتين اللغتين بسهولة.


----------



## ELHO (24 يونيو 2010)

السلام عليكم
بارك الله فيكم على الموضوع المهم و إن شاء الله نكون في الطريق الصحيح
لدي بعض الإستفسارات
هل من الممكن رسم العناصر على v.b و قراءة الإحداثيات (2d أو 3d)
كيفية إدخال عامل الحرارة (قوة الضغط في العنصر)
شكرا و بالتوفيق إنشاء الله


----------



## عبد الجواد (26 يونيو 2010)

ELHO قال:


> السلام عليكم
> بارك الله فيكم على الموضوع المهم و إن شاء الله نكون في الطريق الصحيح
> لدي بعض الإستفسارات
> هل من الممكن رسم العناصر على v.b و قراءة الإحداثيات (2d أو 3d)
> ...



يمكن رسم العناصر على VB بنظام 2D أو 3D ولكن يحتاج هذا إلى برمجة بيئة رسم تقوم بذلك أو استخدام بيئة رسم جاهزة، وهذا شأن جميع لغات البرمجة.

أما عن إدخال عامل الحرارة فيتم بطريقة الصلابة كما يلي باختصار:
إن مبدأ طريقة الصلابة هو وضع تثبيت درجات الحرية المعتمدة ثم حساب القوى المطبقة على درجات الحرية هذه، ثم حساب الانتقالات وفقها.
في حالة الجوائز الشبكية في هذا البرنامج، فإن درجات الحرية هي انتقالات العقد وفق المحورين x و y، وفي حال تطبيق تغير في درجة الحرارة على أحد القضبان فإنه ستنشأ فيه قوة محورية داخلية بسبب تثبيت نهايتيه قيمتها:
N=E.A.alpha.T
حيث E عامل المرونة
A مساحة المقطع
alpha معامل التمدد الحراري للمادة
T تغير الحرارة

ثم يتم إسقاط هذه القوة على المحاور العامة وإضافتها إلى شعاع القوى الخارجية، ونقوم بحساب الانتقالات كما سبق.

كما يتم تعديل القوة التي ستنتج في هذا العنصر بعد حساب القوى الداخلية، بطرح قيمة القوة الداخلية التي نتجت عن التغير الحراري.


----------



## ELHO (30 يونيو 2010)

السلام عليكم شكرا لإجابة و عذرا لتأخير

فيما يخص الإستفسار الثاني طريقة حساب تأثير الحرارة يدويا واضحة
عندما قمت ببعض الأمثلة على أ شكال بسيطة كانت النتائج موافقة للحساب اليدوي لكن بالنسبة للأشكال المركبة كانت مختلفة
لتوضيح المراد من الإستفسار قمت ب 3 أمثلة على SAP2000v11
في المثالين 1 و 2 النتائج موافقة للحساب اليدوي
في المثال3 ,ما هي الطريقة للوصول إلى نتائجSAP؟ وبالتالي طريقة برمجها؟

الأمثلة لحساب تأثير الحرارة على القضيب رقم1
المعطيات
L=4m
alpha=1e-5
T=15°
A=0.03m²
E=2.1e8KN/m²

في المثال المرفق1 القضيب مثبت من جهة و حر من جهة
U=L.alpha.T=0.0006m
N=0




في المثال المرفق2 القضيب مثبت من الجهتين
N=E.A.alpha.T=945KN
U=0





في المثال المرفق3 لدينا معامل الحرارة على القضيب رقم1
N=164KN
Ux=0.0004




شكرا لإثراء الموضوع


----------



## عبد الجواد (1 يوليو 2010)

في هذه الحالة نطبق على العقدتين 1 و 2 قوى أفقية متعاكسة تكافئ ردود الأفعال الناتجة عن تطاول القضيب رقم 1 نتيجة تغير درجة الحرارة إذا كان مسنوداً من طرفيه.

إن كان الجواب غامضاً (فهو نفسه في مشاركتي السابقة) فأرجو منك وضع طريقة حلك اليدوية لنناقشها، فقد أكون مخطئاً، أو قد تكون قد أخطأت في نقطة ما، وبعدها نقارن مع نتائج sap.


----------



## ELHO (1 يوليو 2010)

شكرا أخي سأحاول تطبيق هذا المبدأ
وجدت ملف يتطرق لهذا الوضوع وهو مرفق هنا
وأعتقد أنه نفس المبدأ


----------



## mdsayed (18 يوليو 2010)




----------



## محمد a.m (18 يوليو 2010)

ما شاء الله كان 
وقد شاء وجود عقول جميلة في هذه البلد العظيم 
شكرا جزيلا لك 
مهندس عبد الجواد


----------



## سنا الإسلام (29 يوليو 2010)

تم تثبيت الموضوع بهذا الرابط

*مثبــت:* متجدد - موضوع برامج هندسية - شامل - شروحات، واستفسارات ‏(



1 2 3)

جزاكم الله خيرا وبارك الله فيك


----------



## malikmaghawat (4 أغسطس 2010)

يســـــــــــــــــــــــمــــــــــــوا


----------



## ابوصلاح اعتيبي (8 يناير 2011)

جزاكم الله عني خير الجزاء


----------



## m m a (8 فبراير 2011)

جزاكم الله خيرا


----------



## m m a (8 فبراير 2011)

اللـهم رضـاك والجـنة
لا تجعل الله أهون الناظرين إليك


----------



## m m a (8 فبراير 2011)

:77:سبحانك اللهم وبحمدك


----------



## m m a (8 فبراير 2011)

:20:اللهم رضاك والجنه


----------



## محمود مدكور (8 فبراير 2011)

شكرا


----------



## m m a (16 فبراير 2011)

السلام عليكم

تسلم إيدك يا بشمهندس عبد الجواد


----------



## himaelnady (29 أغسطس 2011)

بارك الله فيكم


----------



## العروة الوثقى1 (10 نوفمبر 2011)

_*مشكورررررررررين.*__*..........*_ *وجزاكم الله خير الجزاء*


----------



## m m a (10 فبراير 2012)

جزاكم الله كل الخير


----------

