はじめに
Step1
骨組解析とは
![image](images/sa1.png)
画像のように、ラーメン構造にいろいろな力が作用しているとします。
頭の良い方は、手計算で各応力を算出できるかもしれませんが、おいさんは無理です。
そんな人のために、自動でせん断応力や曲げモーメントおよび軸力を算出してくれる方法が「骨組解析」
と呼ばれるもののようです。
これがあれば、どんな複雑な条件でも簡単に応力を算出できるようになります。
なので、自分で簡単な鉄筋コンクリート等の設計ができるようになるかもしれません。最後にそこを目指そうと思います。
Step2
鬼のように難しい導入部分
![image](images/sa2.png)
「骨組解析」について調べていくと、鬼のように難しいことが判明。
とても、一気に理解することは難しいので少しずつ進めていきたいと思います。
まず、抜本的な考え方ですが、ラーメン構造等の骨組を「①各部材(要素と呼ぶようです)に分解」します。
次に、「②各要素の力と変位の関係を表す方程式を作成」するようです。
それを再び組み合わせて、「③各要素の力と変位が一致する条件の方程式」を作成し、それを解くことで、すべての「④変位を求める」ようです。
求めた変位から、「⑤部材の応力を求める」ようです。
何を書いているか自分でもわかりませんが、上記の番号順に少しずつ進めたいと思います。
Step3
①各部材(要素と呼ぶようです)に分解
![image](images/sa3.png)
最初に、構造体(骨組)を決定していきます。
今回も、いつもどおり、新しいプロジェクトから「Windowsフォームアプリケーション」を使用します。
![image](images/sa4.png)
まず、構造体の形を設定する必要があります。
そのため、まず、節点数と要素数を決める必要があります。
節点数と要素数を入力するフォームは別フォームで入力することにします。
ソリューションエクスプローラーの下の「骨組解析」を右クリックして「追加」を選択し、[新しい項目」を選びます。
![image](images/sa5.png)
その中の「フォーム」を選びます。
名前はデフォルトの「Form2」のままにします。
![image](images/sa6.png)
「Form2」の画面をデザインします。
節点数を入力するテキストボックスが「textBox1」で要素数を入力するテキストボックスが「textBox2」になります。
また、 はじめて「radioButton」を配置しています。トラスの場合はモーメントが拘束されるようで、あらかじめ指定するとにします。
その他の画面デザインは、以前と変わらないので割愛します。
デザインが完了したので、コードが書ける画面に移動します。
まず、プロパティ?を宣言します。普通ならここで変数宣言ですが、今回はC#独自のプロパティを使用します。
参考にしているコードがプロパティだったので、そのまま、まねています。特に作為的ものはありません。
プロパティは「骨組」か「トラス」のどちらかのフラグと節点用と要素用の3つを用意します。
![image](images/sa7.png)
![image](images/sa8.png)
次は、恒例の入力制限です。
テキストボックスに数字しか入力できないように入力制限を行います。
![image](images/sa9.png)
次に、「入力完了」ボタンと「閉じる」ボタンのコードになります。
「入力完了」ボタンでは、まず、各テキストボックスに値の入力がない場合の処理をしています。
その後、if文でラジオボタンのチェック状況により、骨組の場合は「f」をトラスの場合は「t」を「typeFlag」
に格納します。
次に、節点数と要素数をそれぞれ「nodeNum」と「elementNum」に格納します。
最後は、このフォームを閉じるためのコードを書いています。
「閉じる」ボタンは、フォームを閉じるためのコードのみになります。
![image](images/sa10.png)
「Form1」に戻ります。まず、全角を半角に変換できる命令文が書けるようにその準備をします。
ソリューションエクスプローラーの「参照」を右クリックします。
そうするとメニューが表示されるので「参照の追加」をクリックします。
![image](images/sa11.png)
「参照マネージャー」ダイアログが表示されますので、「アセンブリ」を選択し、 表示されるアセンブリの一覧から 「Microsoft.VisualBasic」を選択し「OK」ボタンをクリックします。
![image](images/sa12.png)
「form1」のコードを書く画面に移動し一番上の方に「using Microsoft.VisualBasic;」を追加します。
![image](images/sa13.png)
「Form1」のデザイン画面に移動し、「MenuStrip」をドラックアンドドロップします。
![image](images/sa14.png)
メニューバーに項目を追加します。
ひとまず、「ファイル」、「計算」、「設定」、「参照」の4つを追加します。
さらに、「設定」下層に「節点数と要素数」を追加し、名前を「nodelmNumM」に変更しました。
この「節点数と要素数」を押すと先程作成した「Form2」を表示し、節点数と要素数を入力できるようにしようと思います。
![image](images/sa15.png)
「節点数と要素数」と「Form1」自体をそれぞれダブルクリックし、コード入力画面に移ります。
画像のとおり、コード上部の箇所でフォーム用の変数と「節点数と要素数」用の変数を宣言し、「Form1_Load」イベントでインスタンス
をします。
そして、「nodelmNumM_Click」イベントで、「Form2」を表示するコードを入力します。
![image](images/sa16.png)
「nodelmNumM_Click」イベントの続きになります。
まず、「Form2」で「節点数と要素数」が入力されていなければ、以降の処理を行わないようにします。
if文を用いて、「typeFlag」に値があるか確認し、無ければ「「nodelmNumM_Click」イベントを終了します
次に、「節点数と要素数」の値を半角処理と文字→数字処理をします。
![image](images/sa17.png)
「Form1」のデザイン画面に戻ります。
ツールボックスから「DataGridView」を選択して、ドラックアンドドロップします。
![image](images/sa18.png)
フォームに配置したら、そのまま、「▶」を押し、「列の追加」を押します。
![image](images/sa19.png)
列に項目を追加していきます。
項目は、「節点番号、x座標(m)、y座標(m)、x拘束、y拘束、回転拘束、x荷重(kN)、y荷重(kN)、モーメント(kN/m)」
で、そのままヘッダーテキストに入力します。
その項目に対する列名を「nodNumC、xCoord、yCoord、xRestraint、yRestraint、mRestraint、xLoad、yLoad、moment」としました。
![image](images/sa20.png)
画像は、入力完了後の状態になります。
![image](images/sa21.png)
もう一つ、「DataGridView」を配置します。
今度の項目は、「選択、要素番号、節点1、節点2、ヤング係数、断面積、断面2次モーメント、分布荷重x1
、分布荷重x2、分布荷重y1、分布荷重y2」とし、ヘッダーテキストに入力します。
また、その項目に対する列名を「selectRow、elementNumC、nod1、nod2、youngcoefficient、mArea、
doubleMoment、distributedLoadsX1、distributedLoadsx2、distributedLoadsy1、distributedLoadsy2」としました。
![image](images/sa22.png)
画面デザイン上の最初の「DataGridView」に戻って、細かい設定をしていきます。
「DataGridView1」のイベントの「ditingControlShowing」をダブルクリックして、コード画面に移動します。
![image](images/sa23.png)
ここでは、「DataGridView1」の入力制限をします。
先に、下のコードの「Column1_KeyPress」関数について、説明します。
このコードは、「数字」と「、」と「-」のみ入力できるようにする命令文です。
なので、「DataGridView1」の項目としては、「x座標、y座標、x荷重、y荷重、モーメント」にこの入力制限を適用することになります。
そこで、その上のコードで、その項目を選んだ場合は、「Column1_KeyPress」関数に移行するようにしています。
コードの中身は、おいさんも理解できないのですが、とにかくインスタンスするようです。
![image](images/sa24.png)
デザイン画面に戻り、「DataGridView1」の「▶」を押して、「列の編集」を選択します」
![image](images/sa25.png)
「x拘束、y拘束、回転拘束」は「0」か「1」のみの入力にしたいと思います。
なので、「x拘束、y拘束、回転拘束」の「columnType」を「DataGridViewComboBoxColumn」に変更し、
コンボボックスを使用します。
![image](images/sa26.png)
次に「アルファベット順」のボタンを押します。
その中から、「Items」を選択します。
![image](images/sa27.png)
コレクションの中に0と1を入力します。
これで、コンボボックスの選択肢ができました。
![image](images/sa28.png)
デザイン画面に戻り、「DataGridView2」の「▶」を押して、「列の編集」を選択します」
![image](images/sa29.png)
項目「選択」の「columnType」を「DataGridViewButtonColumn」に変更し、ボタン表示にします。
![image](images/sa30.png)
そして、「DefaultCellStyle」の「...」を押します。
![image](images/sa31.png)
データの箇所に「選択」を入力します。
これで、ボタン上に「選択」が表示されるようになります。
![image](images/sa32.png)
次に、「DataGridView2」のイベントの「ditingControlShowing」をダブルクリックして、コード画面に移動します。
![image](images/sa33.png)
画面移動したら、「DataGridView2」の入力制限をします。
先に、下のコードの「Column2_KeyPress」関数について、説明します。
前回と違うのは、数字のみしか入力できないパターンと、「数字」と「、」と「-」のみ入力できるパターンに分かれることです。
なので、「DataGridView2」の項目として、「節点1、節点2」は数字のみ、「ヤング係数~分布荷重」までをそれ以外の入力制限を適用することしてます。
後は、前回と同様で、その項目を選んだ場合は、「Column2_KeyPress」関数に移行するようにしています。
![image](images/sa34.png)
入力制限が完了したので、「選択」ボタンの制御をしたいと思います。
「選択」ボタンをダブルクリックして、コードの画面に移動します。
![image](images/sa35.png)
「DataGridView」を使うのは初めてなので、ボタンの制御について、勉強しようと思います。
ここで、試しに画面のコードを入力して実行してみます。
![image](images/sa36.png)
上記のコードを実行すると、メッセージボックスが表示され、その中に数字が表示されています。
この数字が、行数を表示していることがわかります。
なのでこの機能を利用して、ボタンの制御をしようと思います。
![image](images/sa37.png)
まず、この「選択」ボタンを何に使用するか書きます。
このボタンのある表「DataGridView2」の項目には、ヤング係数、断面積、断面2次モーメントを入力する必要があります。
この項目をいちいち入力するのは面倒なので、その入力を補完する機能を作ろうと思います。
なので、「選択」ボタンから、別のフォームに移動し、その入力補完をする操作画面を作ろうと思います。
ソリューションエクスプローラーの下の「骨組解析」を右クリックして「追加」を選択し、[新しい項目」を選びます。
![image](images/sa38.png)
その中の「フォーム」を選びます。
名前はデフォルトの「Form3」のままにします。
![image](images/sa39.png)
「Form3」の画面デザインは、画像のとおりとしました。
![image](images/sa40.png)
「comboBox1」の「items」には「鋼材」と「鉄筋コンクリート」の2つにします。
![image](images/sa41.png)
「textBox1」と「textBox2」に、恒例の数値等しか入力できない制限をします。
![image](images/sa42.png)
「textBox3」~「textBox5」までの「Modifiers」を「Public」にします。
これで、「Form1」のコード内でも、このテキストボックスを呼び出すことができます。
![image](images/sa43.png)
「Form3」のコードに移動して、まず、このフォームで計算した値を適用するかどうかのフラグをプロパティ
で宣言します。プロパティ名は、「applyFlag」としました。
次に、フォームロードイベントで、ひとまず「applyFlag」の格納値を「"no"」、つまり現時点では適用しないとしています。
![image](images/sa44.png)
次は「OK」ボタンの処理です。
まず、未入力の場合の処理を入力しています。
その後、ヤング係数の設定と、断面積と断面2次モーメントの計算をして、テクストボックスに格納しています。
![image](images/sa45.png)
最後に、「適用」ボタン(button2)と「閉じる」ボタン(button3)のクリックイベントを入力します。
どちらも、共通してフォームを閉じるためのコードを書いています。さらに「適用」ボタンでは「applyFlag」の
格納値を「"yes"」に変更し、このフォームの計算結果を適用することを確定させます。
以上で、「Form3」の作業は完了になります。
![image](images/sa46.png)
「Form1」のコードに戻ります。
まず、「Form3」を使用できるようにするため、変数宣言とインスタンスを行います。
入力箇所は、「Form2」と同じ箇所にします。
![image](images/sa47.png)
「選択」ボタンクリックイベントのコードに移動します。
「applyFlag」の格納値が「"yes"」の時だけ実行したいので、まず、その確認をします。
確認後、セルに計算結果をセットするようにしています。実際のコードは、「dataGridView2.Rows[e.RowIndex].Cells[4].Value = f3.textBox3.Text;」
になります。
ここで、「Rows]が行で、「Cells]が列を意味しているようです。
![image](images/sa48.png)
一旦実行してみます。
まず、「選択」ボタンを押して、[Form3」を表示し、計算をします。
今回は、3行目の「選択」ボタンを押してみました。
![image](images/sa49.png)
「適用」ボタンを押します。
画像のとおり、無事、3行目のセルに値がセットされました。
![image](images/sa50.png)
メニューバーの「設定」の中の「節点数と要素数」イベントが途中でしたので、その続きをします。
新たに追加したコードは、画像のとおりとなります。
コードの内容は、コメントに書いていますので割愛します。これで、表の完成になります。
![image](images/sa51.png)
再度、表設定ができるように、表のクリア機能を追加します。
メニューバーの「設定」の中の「節点数と要素数」イベントの下に「表のクリア」を追加します。
名前は、「clearTableM」にしました。
![image](images/sa52.png)
「clearTableM」をダブルクリックし、コード入力画面に移動します。
表を削除したい場合は、単純に「dataGridView1.Rows.Clear();」と書けば良いようです。
「dataGridView2」についても同様に削除するようにします。
![image](images/sa54.png)
コード上部に、変数を追加します。
今回の変数は配列にしています。変数の内容はコードのコメントを参照してください。
![image](images/sa53.png)
デザイン画面のメニューバーの「計算」の下層に「計算実行」を追加します。
名前は「calcRunM」にしました。
![image](images/sa55.png)
「calcRunM」をダブルクリックして、コード入力画面に移動します。
「nnd」と「ngd」ですが、1要素に節点が2つなので「nnd」は2になります。また、節点の自由度はx、y、M方向の
3方向になりますので「ngd」は3になります。
次に、表に未入力部分があれば、このイベントを実行しないよう制限をかけます。
ただし、かなりセルが多いので、「DataGridView1」については、x、y座標を、「DataGridView2」については
節点番号を対象にします。
それから、エラーが怖いので、try文を使用しました。
![image](images/sa56.png)
設定したデータを、先程宣言した変数に格納していく作業をします。
ここでは、節点座標を「xd、yd」に値を格納していきます。
「DataGridView」のセルの値は、文字だと思っていたのですが、そうではないようです。
なので、先に型変換(キャスト)をして、一旦文字にしています。
それから、数字に変換して、変数に格納しています。
![image](images/sa57.png)
次に要素両端の節点番号を変数に格納します
先程と同様で、型変換をして変数に格納します。
![image](images/sa58.png)
最後に、ヤング係数、断面積、断面2次モーメントをそれぞれ、「eyoug」、「earea」、「esii」に格納します。
これで、現段階での変数格納は完了です。
このステップでは、「①各部材に分解」という項目での話でしたが、「分解」というより、最初から
各部材を設定していくだけでした。
Step4
②各要素の力と変位の関係を表す方程式を作成
![image](images/sa59.png)
ここからは、画像のとおり、ある1つの要素について、力と変位の関係を構築していきます。
![image](images/sa60.png)
みなさんは、フックの法則を覚えておられますか?
式は画像のとおり、「f=k・x」になります。
単純にある力を与えると比例的(線形的)にばねが伸びる(変位)ということを表すだけの式です。
この式を要素にあてはめて、つまり1つの要素を1つのばねと見立てて、力と変位の関係を表すことがこのステップの目的になります。
なので、コンクリートのように力と変位の関係が非線形の材料でも、すべて線形(弾性)挙動として計算していきます。
![image](images/sa61.png)
まず、フックの法則の「k」の部分から取り掛かります。
「k」を行列で表すと、画像のとおりになるようです。
恐ろしく複雑ですが、こんなものだとして深く考えずに進めます。(おいさんにも理解不能です。)
ちなみに、Eがヤング率、Lが要素の長さ、Aが要素の断面積、Iが断面2次モーメントになります。
![image](images/sa62.png)
「k」の設定をメインコードに書くとさらにごちゃごちゃするので、別クラスを用意してそこで計算するようにします。
それでは、新しいクラスを追加したいと思います。
ソリューションエクスプローラーの「骨組解析」のところで右クリックします。
すると、画像のとおり、選択できる画面が出てきますので、「追加」→「新しい項目」を選択します。
![image](images/sa63.png)
「クラス」を選択し、名前を入力します。
名前の先頭文字は大文字にする必要があるようです。今回は「ElementStiffnessMatrix.cs」としました。
名前を入力したら「追加」ボタンを押します。
![image](images/sa64.png)
「追加」ボタンを押すと、コードが書ける画面が現れます。
ここに、「k」を設定するコードを入力していきます。
![image](images/sa65.png)
「k」のコードを書く前に、「Form1」の変数をこのクラスでも使えるようにします。
方法は、「Form1」のコードに戻り、変数宣言している箇所の頭に「public static」を追記するだけです。
ここで「static」は、一つの値を共有する性質を持たせる命令らしいです。よくわかりませんが、これで、「骨組解析」というファイル内で
共通して使える変数になるようです。
![image](images/sa66.png)
それでは「ElementStiffnessMatrix」クラスに戻ります。
ちなみに、このクラス名は、「k」のことを「要素剛性マトリクス」と呼ぶらしいので、それを表すクラス名にしています。
まず、メンバー変数と、「k」を設定するメンバー関数を書きます。
メンバー変数は、「tkeMatrix」という配列変数とし、これを「Form1」に返すようにします。
メンバー関数は、「SetValue(int ne)」とし、要素数「ne」を受け取り、「k」を設定していきます。
メンバー関数「SetValue(int ne)」では、まず、変数を宣言しています。ただし、ここで「k」を設定しますが、少し変換(座標変換)処理をする必要が
あるので、2つの変数を用意しています。詳細は、後述で説明しようと思います。
![image](images/sa67.png)
メンバー関数「SetValue(int ne)」の続きです。
ここでは、まず節点座標を取得します。先ほど、座標の変数は「public static」を付けているので、このクラスでも使用可能に
なっています。
なので、その変数を再度、x1からy2までに格納していきます。なお、x1とy1が「Form1」のデザイン画面の下表の「節点番号1」の
座標を格納し、x2、y2が「節点番号2」の値を格納するようにしています。
![image](images/sa68.png)
「k」を設定するのに、あと足りない項目は要素の長さになります。
要素両端のx、y座標を取得したので、画像に示すとおり要素の長さは計算で求められます。
また、次に、変数「keMatrix」の行列を0で初期化します。
![image](images/sa69.png)
変数「keMatrix」に値を格納していきます。
値は、上述で示した行列内の数式になります。1つ1つ地道に格納していきます。
![image](images/sa70.png)
変数「keMatrix」の設定が終わりましたので、次に進みますが、次はこの変数「keMatrix」を座標変換する作業になります。
ただ、どうして、座標変換が必要なのかを先においさんの理解の範囲内で述べます。
まず、フックの法則のxの部分に着目します。わかりにくいのでxの変化を図で表します。
画像は、要素(緑色)が力を受けて要素(水色)に変化した場合の模式図を表しています。
フックの法則のx部分はこの図のd1とd2になります。
さらにd1に着目すると、u1とv1に分けることができますが、これは要素独自の座標系x,yにより分けたものになります。
しかし、実際は、統一座標のX、Y座標系での変化量が必要になります。
なので、その関係を式で表すと「u1=cosα・ug1+sinα・vg1」となります。なぜ、こういう関係式になるかはわかりません。
![image](images/sa71.png)
その他の変位についてもまとめると画像のとおりとなります。
以降、行列を書くのが大変なので「T」と「dg」として表記します。
![image](images/sa72.png)
また、フックの法則に戻ります。
変位xを上記の式で置き換えると、「f=k・T・dg」となります。
ただし、力「f」はまだ要素独自の座標計の方向のままです。
なのでこれも全体座標系に変換する必要があります。
変換方法は、なぜか「T」の転置を掛けるだけで良いみたいです。ですので、両辺に「T」の転置を掛けます。
結果、画像のとおり「k」の間にTとTの転置行列が存在するので、これを新しいkとして以降に計算していきます。
![image](images/sa73.png)
メンバー関数「SetValue(int ne)」のコード画面に戻ります。
まずは、行列「tMatrix」を0で初期化します。
![image](images/sa74.png)
行列「tMatrix」の中の要素に、sinとcosの三角関数があります。
この値は、画像のとおり、数式で求めることができます。
![image](images/sa75.png)
ここで、行列「tMatrix」を設定し、その後「新しいk」すなわち「tk」行列を計算しています。
![image](images/sa76.png)
最後に、計算した行列「tk」をメインコード(Form1)に返す関数を設定します。
これで、このクラスのすべての作業が完了となります。
さらに、要素の力と変位の関係を「tk」行列で表せたので、このステップも完了になります。
Step5
③各要素の力と変位が一致する条件の方程式
![image](images/sa77.png)
タイトルのとおり、「各要素の力と変位が一致する条件の方程式」を作成していきます。
とはいっても、どういうことかというと、これまでは、要素1つについて力と変位の関係性を現す「新しいk」を作成してきました。
今度は、これを元の形(画像の左)に戻した場合の構造体全体の関係性を現す「新しいk」(行列)を作成していきます。
ただし、すべての要素をまとめて説明すると大変なので、画像の囲んでいる2要素に着目して書いていきます。
![image](images/sa78.png)
前回のステップで求めた関係式を画像のとおり、2つの要素に設定します。
また、その関係式を行列で表したものを併せて画像に示したとおりとします。
ここで、「fg」に当たる「Pg、Qg、Mg」ですが、それぞれ正負の2種類存在しています。これは、各要素両端の力を示して
いて、正負があるのは反力方向に力が存在していることをイメージしています。
![image](images/sa79.png)
ここで、各要素の力と変位が一致する条件になるには、構造体全体で力と変位が一致する必要があります。
この例の場合、画像の構造体の赤丸の節点の力と変位が一致する必要があります。
行列でいうと、朱書の箇所が一致する必要があります。
![image](images/sa80.png)
節点2の力と変位が一致する条件を行列で表すと画像のとおりとなり、一致する「tk」行列部分は単に足し算になります。
この、足し合わせた「tk」行列(以後tkgとする)を全体剛性マトリクスと呼ぶようです。
次は、この全体剛性マトリクス「tkg]を作成していきます。
![image](images/sa81.png)
まずは全体剛性マトリクスを格納する変数を宣言します。
変数は、配列とし、変数名は「atkg」としました。
![image](images/sa82.png)
「Form1」の「calcRunM」コード入力画面に戻り、この続きに全体剛性マトリクスのコードを書いていきます。
まずは、初期設定をします。
すべての値の初期値をゼロにします。
![image](images/sa83.png)
次に、先程作った要素剛性マトリクス設定クラスを呼び出すための設定をします。
変数名を「esm」として、インスタンスします。
![image](images/sa84.png)
ここから、一気に全体剛性マトリクスの計算をしていきます。
まずは、「tkeM」の変数を宣言します。この変数には、先程インスタンスした要素マトリクスの値を格納します。
実際には「esm.SetValue(ne);」で要素番号を渡し、「tkeM = esm.Gettke();」で変数に格納しています。
いよいよ、全体剛性マトリクスの計算です。
「For」文が4つもあるので難しいですが、これだけで重ね合わせ(全体剛性マトリクス)の計算が完了になります。
![image](images/sa85.png)
全体剛性マトリクスの計算が完了したので、次は荷重「fg」の値を格納していきます。
式でいうと、画像の赤で囲まれた箇所になります。
![image](images/sa86.png)
荷重は、画像のとおり、「DataGridView1」の6~8列目に入力するようにしています。
なので、まずはこの値を取得します。
![image](images/sa87.png)
最初に、荷重を格納する変数を宣言します。先が読めないのでグローバル関数にしておきます。
ついでに、荷重「fg」を格納する変数も宣言しておきます。
![image](images/sa88.png)
「DataGridView1」から、入力データを取得します。
その後、それぞれの変数に格納しています。
![image](images/sa89.png)
荷重マトリクス「fg」に入力値を格納していきます。
内容は、コードのとおりとなります。
これで、荷重部分は完了になります。
Step6
④変位を求める
![image](images/sa90.png)
全体剛性マトリクスの方程式が完了しましたので、ここではその方程式から変位を求めます。
また、先程の2要素について説明していきますが、説明しやすいようにさらに条件を追加します。
追加内容は、節点②のX方向に荷重10kNを負荷することです。それだけです。
後は、節点①のxとy方向が拘束されていることを理解しておけばO.kです。
![image](images/sa91.png)
上述の条件のもと、全体剛性マトリクスの方程式を表すと画像のとおりとなります。
その中で、節点①のx、y方向は拘束されていますので、変位は0になり、変位を求める必要がないことがわかると思います。
なので、残りの変位のみに着目した方程式を再度組み直す作業をしていきます。(赤枠で囲まれた箇所のみの方程式に再構築)
![image](images/sa92.png)
それでは、コードに移ります。
まず、変数を宣言します。
宣言する変数は、画像のとおりになります。横に変数の内容を書いていますが、うまく表現できていません。
なので、以降のコードでどのように使用しているか理解してもらうしかないと思います。(すみません。)
![image](images/sa93.png)
「計算実行」のコードの最後部に移ります。
ここで最初に、変位マトリクス番号を1で初期化します。
この、変位マトリクス番号「idNum」変数は変位が0かそれ以外かを識別するための配列番号を取得するための変数になります。
なので、初期化は別に0で無ければ何でも良いのでとりあえず1にしています。
![image](images/sa94.png)
拘束条件は、画像のとおり、「DataGridView1」の3~5列目に入力するようにしています。
それでは、この値を取得します。
![image](images/sa95.png)
拘束条件を取得するコードは画像のとおりとなります。
内容は、以前と同様ですので、割愛します。
![image](images/sa96.png)
次に、先程取得した拘束条件で、1(拘束されている)が入力されている場合、すなわち変位が0の場合、「idNum」変数に0を格納します。
拘束条件は、x、y、モーメント方向の3つがありますが、それをまとめて、1次元の配列変数として格納していきます。
![image](images/sa97.png)
ここでは、まず「ndNum」を0で初期化します。「ndNum」は番号変数配列の総数を取得する変数になります。
次に、拘束されていない(初期値1が残っている)「idNum」変数のみ再度順番に番号を付けていきます。
![image](images/sa98.png)
最後に、全体剛性マトリクス「atkg」と荷重マトリクス「fg」で変位が0でない配列のみで再構成します。
コードは画像のとおりになります。また、「goto」文は「for」文を抜ける命令文になり、「goto」文で指定したマークのある箇所まで飛ぶ命令文
になります。この命令文により、変位0の時は何もしない(飛ばす)コードにしています。
![image](images/sa99.png)
拘束条件による配列の再構成後の式は、画像のとおりとなります。
後は、この式を解けば変位が求まることになります。ただし、この連立方程式は簡単に解ける代物ではありません。
そこで、「ガウスの消去法」という方法を用いてこの連立方程式を解いていくことが一般的のようです。
![image](images/sa100.png)
「ガウスの消去法」をメインコードに書くとやはりごちゃごちゃしそうなので、別クラスを用意してそこで計算するようにします。
それでは、新しいクラスを追加したいと思います。
ソリューションエクスプローラーの「骨組解析」のところで右クリックします。
すると、画像のとおり、選択できる画面が出てきますので、「追加」→「新しい項目」を選択します。
![image](images/sa101.png)
「クラス」を選択し、名前を入力します。
名前の先頭文字は大文字にする必要がありますので注意が必要です。今回は「GaussElimination.cs」としました。
名前を入力したら「追加」ボタンを押します。
![image](images/sa102.png)
「追加」ボタンを押すと、コードが書ける画面が現れます。
ここに、「ガウスの消去法」で計算するコードを入力していきます。
![image](images/sa103.png)
今回は、「public static」を付けている全体剛性マトリクス「atkg」と荷重マトリクス「fg」を直接触るのでメンバー変数は使用しません。
メンバー関数は、「SetValue(int ne)」とし、マトリクスサイズを「ne」で受け取り、変位を計算していきます。
計算方法は、先に述べたように、ガウスの消去法による計算ですが、おいさんはほとんど理解できません。なので、コードもネット上で探して丸パチリしています。ご了承ください。
![image](images/sa104.png)
メインの「計算実行」の最後部に戻ります。
ここに、先程作った「ガウスの消去法」クラスを呼び出します。
変数名を「ge」として、インスタンスします。
インスタンスが完了したら、早速クラスの実行をします。渡す値は、マトリクスサイズの「ndNum」になります。
これで、計算が完了し、変位が求まっているはずです。
![image](images/sa105.png)
計算された変位を表示してみようと思います。
変位を表示するフォームは別フォームで入力することにします。
ソリューションエクスプローラーの下の「骨組解析」を右クリックして「追加」を選択し、[新しい項目」を選びます。
![image](images/sa106.png)
その中の「フォーム」を選びます。
名前はデフォルトの「Form4」のままにします。
![image](images/sa107.png)
「Form4」の画面をデザインしていきます。
ツールボックスから「DataGridView」を選択して、ドラックアンドドロップします。
![image](images/sa108.png)
フォームに配置したら、そのまま、「▶」を押し、「列の追加」を押します。
![image](images/sa109.png)
列に項目を追加していきます。
項目は、「節点番号、水平変位(m)、鉛直変位(m)、回転角度」 で、そのままヘッダーテキストに入力します。
その項目に対する列名を「nodNumOut、horizontalDisplacement、rotationAngle」としました。
![image](images/sa110.png)
画面デザインの「DataGridView」に戻って、イベント時の設定をしていきます。
「DataGridView1」のイベントの「EditingControlShowing」をダブルクリックして、コード画面に移動します。
![image](images/sa111.png)
ここでは奇数行の背景色を変更します。
コードは「dataGridView1.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;」になります。
![image](images/sa112.png)
「Form1」のメインコードに戻ります。
まず、「Form4」を使用できるようにするため、変数宣言をします。
ついでに、変位マトリクスを格納する変数と「Form4」に渡す用の節点数を格納する変数も宣言しておきます。
![image](images/sa113.png)
次に「Form1」ロードイベントで「Form4」のインスタンスをします。
![image](images/sa114.png)
「計算実行」コードの最後部に移動します。
まず、変位マトリクスに計算結果を格納します。
また、節点数を別フォームで使用できるように、「public」変数に格納します。
その後、「Form4」を表示するコードを書きます。
![image](images/sa115.png)
「Form4」のデザイン画面に移動します。
ここで、フォーム自体をダブルクリックして、「Form4」のロードイベントに移動します。
その中に画面のとおり変位の計算結果を表示するコードを入力します。
datagridviewに計算結果を追加する命令文は「dataGridView1.Rows.Add」のようで、これで行が追加できるようです。
Step7
⑤部材の応力を求める
![image](images/sa116.png)
変位が求まったので、その値を利用して各部材の応力を求めます。
各部材応力を求める式は画像のとおりのようです。
式の意味はわかりません。ここで、注意ですが、この式は各要素座標系の変位から応力を求める式になっています。
![image](images/sa117.png)
要素座標系の変位u1、u2、v1、v2、θ1、θ2と全体座標系の変位ug1、ug2、vg1、vg2、θg1、θg2の関係は、
以前記載しましたが、画像のような関係性があるとなっています。
ここで、全体座標系の変位ug1、ug2、vg1、vg2、θg1、θg2はStep6で求まっているので自ずと要素座標系の変位u1、u2、v1、v2、θ1、θ2
も求めることができます。
なので、要素座標系の変位から各部材の応力を求めることができます。
![image](images/sa118.png)
「各部材の応力計算」もメインコードに書かずに、別クラスを用意してそこで計算するようにします。
新しいクラスを追加します。
ソリューションエクスプローラーの「骨組解析」のところで右クリックし、「追加」→「新しい項目」を選択します。
![image](images/sa119.png)
「クラス」を選択し、名前を入力します。
名前の先頭文字は大文字にする必要がありますので注意が必要です。今回は「StressCalc.cs」としました。
名前を入力したら「追加」ボタンを押します。
![image](images/sa120.png)
「追加」ボタンを押すと、コードが書ける画面が現れます。 ここに、「各部材の応力計算」のコードを入力していきます。
![image](images/sa121.png)
このクラスを実行するメンバー関数は「RunCalc(int ne)」にしました。
要素数をもらうため、引数「ne」を設定しています。
まずは、変数を宣言します。宣言する変数は、全体座標系の変位、要素座標系の変位及び座標変換マトリクスにしています。
以前もこの変数は宣言していますが、以前の変数を使うと訳がわからなくなるので、このクラスでしか通用しない変数を再度用意することにしました。
次に、要素数を変数に格納しています。
![image](images/sa122.png)
応力の計算は各部材(要素)ごとに計算していきますが、最終的には、すべての部材の応力を計算しないといけないので
部材数分繰り返しをする中に各部材の応力を計算するコードを書いていきます。
なので、画像のとおり、for文で要素数分繰り返しを行うことにしています。今後は、その中にコードを追記していく形になります。
![image](images/sa123.png)
ここでは、先程宣言した全体座標系の変位変数に、Step6で求まった変位を格納していきます。
1部材には節点が2箇所あるので2回繰り返しを行います。
さらに、1節点には3つの変位がありますので、3回繰り返しを行うようにしています。
これで、1部材あたりの変位がすべて格納できるようになります。
![image](images/sa124.png)
ここでの計算は、Step4と同様の内容になりますので割愛します。
![image](images/sa125.png)
要素座標系に変換するため行列計算をします。
これで、要素座標系の変位が取得できました。
![image](images/sa126.png)
次は、部材の応力の計算をするとこなのですが、それを格納する変数の宣言をしていませんでした。
なので、一旦「Form1」のコードの上部に戻り変数宣言をします。
宣言する変数は、圧縮応力、せん断応力及び曲げモーメントで、部材両端分を用意します。
![image](images/sa127.png)
応力を格納する変数を宣言したので、「StressCalc」クラスのコードに戻ります。
ここは単純に応力の計算をしていきます。
あまりに小さい計算結果の場合はゼロにしています。
これで、このクラスのコードは終了になります。
![image](images/sa128.png)
「Form1」のコードの上部に戻り、要素数を「Form4」に渡せるように変数を宣言します。
![image](images/sa129.png)
「Form1」の「計算実行」の最後部に戻ります。
ここに、先程作った「部材の応力計算」クラスを呼び出します。
変数名を「sc」として、インスタンスします。
インスタンスが完了したら、早速クラスの実行をします。渡す値は、要素数の「ndNum」になります。
これで、計算が完了し、応力が求まっているはずです。
![image](images/sa130.png)
「Form4」のデザイン画面に移動します。
ツールボックスから「DataGridView」を選択して、ドラックアンドドロップします。
![image](images/sa131.png)
フォームに配置したら、そのまま、「▶」を押し、「列の追加」を押します。
![image](images/sa132.png)
列に項目を追加していきます。
項目は、「要素番号、軸力1、せん断力1、曲げモーメント1、軸力2、せん断力2、曲げモーメント2」 で、そのままヘッダーテキストに入力します。
その項目に対する列名を「elmnum、axialForce1、shearForce1、bendingMoment1、axialForce2、shearForce2、bendingMoment2」としました。
![image](images/sa133.png)
画面デザインの「DataGridView」に戻って、イベント時の設定をしていきます。
「DataGridView2」のイベントの「EditingControlShowing」をダブルクリックして、コード画面に移動します。
![image](images/sa134.png)
ここでは奇数行の背景色を変更します。
コードは「dataGridView2.AlternatingRowsDefaultCellStyle.BackColor = Color.AliceBlue;」になります。
![image](images/sa135.png)
「Form4」のロードイベントに移動します。
その中に画面のとおり応力の計算結果を表示するコードを追記します。
datagridviewに計算結果を追加する命令文は前回と同様で「dataGridView2.Rows.Add」になります。
また、このソフト上の正負と構造計算上の正負が異なるようで、その調整もしています。さらに、小数第4位で四捨五入するようにしました。
これで、応力計算関係の作業はすべて完了になります。
あまりに長い内容で、まだまだ先が長そうなので「Day10」はここで終了します。続きは「Day11」にします。
突然ですが、「骨組解析」もしくは「フレーム解析」という言葉をご存じでしょうか。
おいさんは、恥ずかしながら全く知りませんでした。
多分、現場で働く方にとっては必要ないかもしれませんが、知っておいても損はしないのではないかと考えています。
とにかく、構造計算の勉強をしていたら、この言葉にぶち当たりました。
非常に難しそうですが、今回はこれにチャレンジしようと思います。