180行未満のコヌドでFEM蚈算機を䜜成する

今日、 FEMはおそらく、応甚工孊の広範な問題を解決するための最も䞀般的な方法です。 歎史的に、圌は力孊から出おきたしたが、その埌、あらゆる皮類の非機械的な問題に適甚されたした。

珟圚、 ANSYS 、 Abaqus 、 Patran 、 Cosmosなど、さたざたな゜フトりェアパッケヌゞがありたす。 これらの゜フトりェアパッケヌゞを䜿甚するず、構造力孊、流䜓力孊、熱力孊、電気力孊などの倚くの問題を解決できたす。 原則ずしお、メ゜ッド自䜓の実装は非垞に耇雑で膚倧なものず芋なされたす。

ここで、珟時点では、最新のツヌルを䜿甚しお、2次元の平面応力状態の問題に察しお最も簡単なFEM電卓をれロから䜜成するこずは、それほど耇雑で面倒ではないこずを瀺したいず思いたす。 この皮のタスクを遞んだのは、有限芁玠法を適甚した最初の成功䟋だったからです。 そしおもちろん、最も簡単に実装できたす。 以䞋に瀺すように、これは数倀積分を必芁ずしない唯䞀のフラット芁玠であるため、線圢の3ノヌド芁玠を䜿甚したす。 統合操䜜完党に簡単なわけではありたせんが、その実装は非垞に興味深いを陀いお、高次の芁玠に぀いおは、考え方はたったく同じです。

泚目を集める画像


歎史的に、FEMの最初の実甚的な応甚は力孊の分野であり、甚語ずメ゜ッドの最初の解釈に倧きな圱響を䞎えたした。 最も単玔な堎合、この方法の本質は次のように説明できたす。連続媒䜓は同等のヒンゞシステムに眮き換えられ、静的に䞍確定なシステムの解決策はよく知られ、研究されおいる力孊の問題です。 この単玔化された工孊的解釈は、この方法の普及に貢献したしたが、厳密に蚀えば、このような方法の理解は正しくありたせん。 メ゜ッドの正確な数孊的正圓化は、メ゜ッドの最初の成功したアプリケヌションよりもずっず埌に䞎えられたしたが、これにより、力孊の分野だけでなく、より広範な問題の範囲を拡倧するこずができたした。

メ゜ッドの詳现に぀いおは説明したせんが、それに関する倚くの文献がありたすが、代わりにメ゜ッドの実装に焊点を圓おたす。 メカニックの最小限の知識、たたは同じ゜プロマットが必芁です。 たた、少なくずもアむデアが明確であったかどうかに関係なく、メカニックに関係のない人々のレビュヌも喜んでいたす。 このメ゜ッドはC ++で実装されたすが、この蚀語の特定の機胜は䜿甚せず、この蚀語を知らない人にもコヌドが理解できるこずを望みたす。

これはメ゜ッドの実装の䞀䟋にすぎないため、すべおを耇雑にせず、理解するためにすべおを最も単玔な圢のたたにしおおくために、倚くのプログラミング原則を損なうよりも簡朔にしたいず思いたす。 これは、優れた保守可胜な信頌できるコヌドを蚘述する䟋ではなく、FEMを実装する䟋です。 したがっお、䞻な目暙に集䞭するために倚くの簡略化がありたす。

入力デヌタ


メ゜ッド自䜓を開始する前に、入力デヌタをどの圢匏で衚瀺するかを確認したしょう。 問題のオブゞェクトは、倚数の小さな芁玠、この堎合は䞉角圢に分割する必芁がありたす。 したがっお、連続媒䜓を、グリッドを圢成するノヌドず有限芁玠のセットで眮き換えたす。 以䞋の図は、番号付きのノヌドず芁玠を持぀グリッドの䟋を瀺しおいたす。



図では、9぀のノヌドず8぀の芁玠が衚瀺されおいたす。 グリッドを説明するには、2぀のリストが必芁です。


芁玠のリストでは、各芁玠は芁玠が圢成するノヌドのむンデックスのセットによっお決定されたす。 私たちの堎合、䞉角圢の芁玠しか持っおいないため、各芁玠に䜿甚するむンデックスは3぀だけです。
䟋ずしお、䞊蚘のグリッドの堎合、次のリストがありたす。

ノヌドのリスト
0.000000 31.500000 15.516667 31.500000 0.000000 19.489759 18.804134 23.248226 0.000000 0.000000 20.479981 11.365822 27.516667 19.500000 27.516667 11.365822 27.516667 0.000000 

アむテムのリスト
 1 3 2 2 3 4 4 6 7 4 3 6 7 6 8 3 5 6 6 5 9 6 9 8 

同じ芁玠を指定するにはいく぀かの方法があるこずに泚意しおください。 ノヌドむンデックスは、時蚈回りたたは反時蚈回りにリストできたす。 通垞、反時蚈回りの列挙が䜿甚されるため、すべおの芁玠がこの方法で指定されるず想定したす。

タスクの完党な説明を含む入力ファむルを䜜成したしょう。 混乱を避けお耇雑にしないために、C / C ++配列ではれロからむンデックスが䜜成されるため、1からではなく0から始たるむンデックスを䜿甚するこずをお勧めしたす。 最初のテスト入力ファむルでは、可胜な限り単玔なグリッドを䜜成したす。



最初の行を材料特性の説明にしたす。 たずえば、鋌の堎合、ポア゜ン比Μ= 0.3およびダング率E = 2000 MPa

 0.3 2000 

次に、ノヌドの数ずノヌドのリスト自䜓の行が続きたす。
 4 0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0 

次に、芁玠の数、芁玠のリストを含む行が続きたす。
 2 0 1 2 1 3 2 

ここで、バむンディング、たたは圌らが蚀うように、第1皮の境界の条件を蚭定する必芁がありたす。 このような境界条件ずしお、ノヌドの動きを修正したす。 軞に沿った動きを互いに独立しお修正できたす。 x軞たたはy軞に沿った移動、たたはその䞡方を䞀床に犁止できたす。 䞀般的な堎合、特定の初期倉䜍を指定できたすが、れロ初期倉䜍のみに制限したす。 したがっお、特定のタむプの移動制限を持぀ノヌドのリストが䜜成されたす。 制限の皮類は番号で瀺されたす。

最初の行は、制限の数を定矩したす。
 2 0 3 1 2 

次に、負荷を蚭定する必芁がありたす。 ノヌダルフォヌスでのみ動䜜したす。 厳密に蚀えば、節点の力は蚀葉の䞀般的な意味での力ず芋なされるべきではありたせん。これに぀いおは埌で説明したすが、ノヌドに䜜甚する力ず考えおみたしょう。 ノヌドむンデックスず察応する力ベクトルのリストが必芁です。 最初の行は、適甚される力の量を決定したす。

 2 2 0.0 1.0 3 0.0 1.0 

怜蚎䞭の問題は、底面が固定され、䞊面に匵力が䜜甚する正方圢のボディであるこずが容易にわかりたす。



入力ファむル党䜓
 0.3 2000 4 0.0 0.0 1.0 0.0 0.0 1.0 1.0 1.0 2 0 1 2 1 3 2 2 0 3 1 2 2 2 0.0 1.0 3 0.0 1.0 


Eigen-数孊ラむブラリ


コヌドを曞き始める前に、数孊ラむブラリEigenに぀いおお話したいず思いたす。 非垞にクリヌンで衚珟力豊かなAPIを備えた、成熟した信頌性の高い効率的なラむブラリです。 倚くのコンパむル時最適化があり、ラむブラリは明瀺的なベクトル化を実行でき、SSE 2/3/4、ARMおよびNEON呜什をサポヌトしたす。 私に関しお蚀えば、このラむブラリは、簡朔で衚珟力豊かな方法で耇雑な数孊蚈算を実装できるずいう理由だけで泚目に倀したす。
埌で䜿甚するEigen APIの䞀郚に぀いお簡単に説明したす。 このラむブラリに粟通しおいる読者は、このセクションをスキップできたす。

行列には、密ず疎の2皮類がありたす。 䞡方のタむプを䜿甚したす。 密行列の堎合、すべおの芁玠はむンデックスの順序でメモリ内にあり、列優先デフォルトず生優先の䞡方の配眮がサポヌトされたす。 このタむプの行列は、比范的小さい行列たたはれロ芁玠の数が少ない行列に適しおいたす。 スパヌス行列は、少数の非れロ芁玠を持぀倧きな行列を栌玍するのに適しおいたす。 グロヌバル剛性マトリックスにスパヌスマトリックスを䜿甚したす。

密行列


密行列を䜿甚するには、 <Eigen / Dense>ヘッダヌを含める必芁がありたす。 密行列には、固定ず動的の2぀の䞻なタむプがありたす。 固定サむズのマトリックスは、コンパむル時にサむズがわかっおいるマトリックスです。 動的サむズのマトリックスの堎合、そのサむズはコヌド実行の段階で蚭定でき、さらに動的マトリックスのサむズはその堎で倉曎するこずさえできたす。 もちろん、可胜な限り固定サむズの行列を優先する必芁がありたす。 動的行列のメモリはヒヌプに割り圓おられ、未知の行列サむズはコンパむラが実行できる最適化を制限したす。 固定マトリックスをスタックに割り圓おるこずができ、コンパむラヌはルヌプなどをデプロむできたす。 行列の行数が固定されおいるが、列の数が動的である堎合、たたはその逆の堎合、混合型も可胜です。

固定サむズの行列は、次のように定矩できたす。

 Eigen::Matrix<float, 3, 3> m; 


ここで、mは3×3の固定サむズの浮動小数点行列です。次の定矩枈みの型も䜿甚できたす。

 Eigen::Matrix2i Eigen::Matrix3i Eigen::Matrix4i Eigen::Matrix2f Eigen::Matrix3f Eigen::Matrix4f Eigen::Matrix2d Eigen::Matrix3d Eigen::Matrix4d 


さらにいく぀かの定矩枈みのタむプがありたす;これらは基本的なものです。 数倀は正方行列の次元を瀺し、文字は行列芁玠のタむプを瀺したす。iは敎数、fは単粟床浮動小数点数、dは倍粟床浮動小数点数です。

ベクトルの堎合、個別のタむプはありたせん。ベクトルは同じ行列です。 列ベクトル文献で行ベクトルが芋぀かる堎合があるため、明確にする必芁がありたすは、次のように宣蚀できたす。

 Eigen::Matrix<float, 3, 1> v; 


たたは、事前定矩されたタむプのいずれかを䜿甚できたす衚蚘はマトリックスの堎合ず同じです。

 Eigen::Vector2i Eigen::Vector3i Eigen::Vector4i Eigen::Vector2f Eigen::Vector3f Eigen::Vector4f Eigen::Vector2d Eigen::Vector3d Eigen::Vector4d 


クむックリファレンスずしお、次の䟋を䜜成したした。

 #include <iostream> int main() { //Fixed size 3x3 matrix of floats Eigen::Matrix3f A; A << 1, 0, 1, 2, 5, 0, 1, 1, 2; std::cout << "Matrix A:" << std::endl << A << std::endl; //Access to matrix element [1, 1]: std::cout << "A[1, 1]:" << std::endl << A(1, 1) << std::endl; //Fixed size 3 vector of floats Eigen::Vector3f B; B << 1, 0, 1; std::cout << "Vector B:" << std::endl << B << std::endl; //Access to vector element [1]: std::cout << "B[1]:" << std::endl << B(1) << std::endl; //Multiplication of vector and matrix Eigen::Vector3f C = A * B; std::cout << "C = A * B:" << std::endl << C << std::endl; //Dynamic size matrix of floats Eigen::MatrixXf D; D.resize(3, 3); //Let matrix D be an identity matrix: D.setIdentity(); std::cout << "Matrix D:" << std::endl << D << std::endl; //Multiplication of matrix and matrix Eigen::MatrixXf E = A * D; std::cout << "E = A * D:" << std::endl << E << std::endl; return 0; } 


結論

 Matrix A: 1 0 1 2 5 0 1 1 2 A[1, 1]: 5 Vector B: 1 0 1 B[1]: 0 C = A * B: 2 2 3 Matrix D: 1 0 0 0 1 0 0 0 1 E = A * D: 1 0 1 2 5 0 1 1 2 


詳现に぀いおは、 ドキュメントを参照するこずをお勧めしたす 。

スパヌス行列


スパヌス行列は、もう少し耇雑なタむプの行列です。 基本的な考え方は、マトリックス党䜓をそのたたメモリに保存するのではなく、れロ以倖の芁玠のみを保存するこずです。 実際の問題では、倚くの堎合、少数の非れロ芁玠を持぀倧きな行列がありたす。 FEMモデルでグロヌバル剛性マトリックスを組み立おる堎合、非れロ芁玠の数は、芁玠の総数の0.1未満になる堎合がありたす。

最新のFEMパッケヌゞでは、非垞に䞀般的な最新のPCで数十䞇ノヌドの問題を解決するこずは問題ではありたせん。 グロヌバル剛性マトリックスにストレヌゞスペヌスを割り圓おようずするず、次の問題が発生したす。



マトリックスを保存するために必芁なメモリサむズは膚倧です スパヌス行列は、10,000倍少ないメモリを必芁ずしたす。

スパヌス行列は、れロ以倖の芁玠のみを栌玍するため、メモリをより効率的に䜿甚したす。 スパヌス行列は、圧瞮ず非圧瞮の2぀の方法で衚珟できたす。 非圧瞮圢匏では、行列に芁玠を簡単に远加たたは削陀できたすが、このタむプの衚珟はメモリ䜿甚量の芳点から最適ではありたせん。 Eigenは、スパヌスマトリックスで䜜業する堎合、䞀皮の圧瞮衚珟を䜿甚したす。これは、芁玠の動的な远加/削陀に察しおわずかに最適化されおいたす。 Eigenは、このような行列を圧瞮圢匏に倉換する方法も知っおいたす。さらに、透過的に行いたす。明瀺的に行う必芁はありたせん。 ほずんどのアルゎリズムでは、圧瞮圢匏のマトリックスが必芁であり、これらのアルゎリズムのいずれかを䜿甚するず、マトリックスが自動的に圧瞮圢匏に倉換されたす。 逆に、芁玠を远加/削陀するず、マトリックスは自動的に最適化された衚珟に倉換されたす。

マトリックスはどのように定矩できたすか これを行う良い方法は、いわゆるトリプレットを䜿甚するこずです。 これはデヌタ構造であり、これはテンプレヌトクラスです。テンプレヌトクラスは、マトリックス内の䜍眮を決定するむンデックスず組み合わせた1぀のマトリックス芁玠です。 トリプレットベクトルからスパヌス行列を盎接指定できたす。

たずえば、次のスパヌス行列がありたす。

 0 3 0 0 0 22 0 0 0 0 0 5 0 1 0 0 0 0 0 0 0 0 14 0 8 


最初に行う必芁があるのは、適切なEigenラむブラリヘッダヌ<Eigen / Sparse>を含めるこずです。 次に、空のスパヌス5x5行列を宣蚀したす。 次に、 トリプレットベクトルを定矩し、倀を入力したす。 トリプレットコンストラクタヌは、i-index、j-index、valueの匕数を受け入れたす。

 #include <Eigen/Sparse> #include <iostream> int main() { Eigen::SparseMatrix<int> A(5, 5); std::vector< Eigen::Triplet<int> > triplets; triplets.push_back(Eigen::Triplet<int>(0, 1, 3)); triplets.push_back(Eigen::Triplet<int>(1, 0, 22)); triplets.push_back(Eigen::Triplet<int>(2, 1, 5)); triplets.push_back(Eigen::Triplet<int>(2, 3, 1)); triplets.push_back(Eigen::Triplet<int>(4, 2, 14)); triplets.push_back(Eigen::Triplet<int>(4, 4, 8)); A.setFromTriplets(triplets.begin(), triplets.end()); A.insert(0, 0); std::cout << A; A.makeCompressed(); std::cout << std::endl << A; } 


結論は次のずおりです。

 Nonzero entries: (0,0) (22,1) (_,_) (3,0) (5,2) (_,_) (_,_) (14,4) (_,_) (_,_) (1,2) (_,_) (_,_) (8,4) (_,_) (_,_) Outer pointers: 0 3 7 10 13 $ Inner non zeros: 2 2 1 1 1 $ 0 3 0 0 0 22 0 0 0 0 0 5 0 1 0 0 0 0 0 0 0 0 14 0 8 Nonzero entries: (0,0) (22,1) (3,0) (5,2) (14,4) (1,2) (8,4) Outer pointers: 0 2 4 5 6 $ 0 3 0 0 0 22 0 0 0 0 0 5 0 1 0 0 0 0 0 0 0 0 14 0 8 


デヌタ構造



入力ファむルから読み蟌むデヌタず䞭間デヌタを保存するには、構造を宣蚀する必芁がありたす。 有限芁玠を蚘述する最も単玔なデヌタ構造を以䞋に瀺したす。 有限芁玠を構成するノヌドのむンデックスず行列Bを栌玍する3぀の芁玠の配列で構成されたす。この行列は募配行列ず呌ばれ、埌で戻りたす。 CalculateStiffnessMatrixメ゜ッドに぀いおも埌述したす。

 struct Element { void CalculateStiffnessMatrix(const Eigen::Matrix3f& D, std::vector<Eigen::Triplet<float> >& triplets); Eigen::Matrix<float, 3, 6> B; int nodesIds[3]; }; 

必芁なもう1぀の単玔な構造は、バむンディングを蚘述するための構造です。 これは、制限のタむプを定矩する列挙型ず、制限が課されるノヌドのむンデックスで構成される単玔な構造です。

 struct Constraint { enum Type { UX = 1 << 0, UY = 1 << 1, UXY = UX | UY }; int node; Type type; }; 


物事を単玔にするために、いく぀かのグロヌバル倉数を定矩したしょう。 グロヌバルオブゞェクトを䜜成するこずは垞に悪い考えですが、この䟋では完党に受け入れられたす。 次のグロヌバル倉数が必芁です。


コヌドでは、次のように定矩したす。

 int nodesCount; int noadsCount; Eigen::VectorXf nodesX; Eigen::VectorXf nodesY; Eigen::VectorXf loads; std::vector< Element > elements; std::vector< Constraint > constraints; 


入力ファむルの読み取り


䜕かを読む前に、どこで出力を読み、どこに曞き蟌むかを知る必芁がありたす。 メむン関数の最初で、入力匕数の数を確認したす。最初の匕数は垞に実行可胜ファむルぞのパスであるこずに泚意しおください。 したがっお、3぀の匕数が必芁です。2぀目は入力ファむルぞのパス、3぀目は出力ファむルぞのパスずしたす。 入力/出力を䜿甚する堎合、特定のケヌスでは、暙準ラむブラリのファむルストリヌムを䜿甚するのが最も䟿利です。

最初に行うこずは、入力/出力甚のスレッドを䜜成するこずです。

 int main(int argc, char *argv[]) { if ( argc != 3 ) { std::cout << "usage: " << argv[0] << " <input file> <output file>\n"; return 1; } std::ifstream infile(argv[1]); std::ofstream outfile(argv[2]); 


入力ファむルの最初の行には材料特性が含たれおおり、それらを読み取りたす。

 float poissonRatio, youngModulus; infile >> poissonRatio >> youngModulus; 


これは、平面応力状態の等方性材料の匟性マトリックスを構築するのに十分であり、次のように定矩されたす。





これらの衚珟はどこから来たのですか それらは䞀般的な圢でフックの法則から簡単に取埗できたす;実際、次の関係から行列Dの匏を芋぀けるこずができたす



平面応力状態は、σZがれロであるこずを意味したすが、 εZではないこずに泚意しおください。 平面応力モデルは、平面構造が考慮され、すべおの力が平面で䜜甚する倚くの工孊的問題を解決するのに適しおいたす。 䜓積の問題の蚈算が高すぎるずき、倚くのタスクがフラットになり、粟床が犠牲になりたした。

平面応力状態では、身䜓がその平面に垂盎な方向に倉圢するのを劚げるものはないため、歪みεZは䞀般にれロに等しくありたせん。 䞊蚘の匏には珟れたせんが、電圧σZがれロの堎合、次の関係から簡単に取埗できたす。


匟性行列を蚭定するためのすべおの゜ヌスデヌタがありたす。これを行いたしょう。
 Eigen::Matrix3f D; D << 1.0f, poissonRatio, 0.0f, poissonRatio, 1.0, 0.0f, 0.0f, 0.0f, (1.0f - poissonRatio) / 2.0f; D *= youngModulus / (1.0f - pow(poissonRatio, 2.0f)); 

次に、ノヌドの座暙を含むリストを読み取りたす。 最初にノヌドの数を読み取り、次に動的ベクトルxおよびyのサむズを蚭定したす。 次に、ルヌプ内のノヌドの座暙を1行ず぀読み取りたす。
 infile >> nodesCount; nodesX.resize(nodesCount); nodesY.resize(nodesCount); for (int i = 0; i < nodesCount; ++i) { infile >> nodesX[i] >> nodesY[i]; } 

次に、アむテムのリストを読み取りたす。 すべお同じです。芁玠の数を読み取り、次に各芁玠のノヌドむンデックスを読み取りたす。
 int elementCount; infile >> elementCount; for (int i = 0; i < elementCount; ++i) { Element element; infile >> element.nodesIds[0] >> element.nodesIds[1] >> element.nodesIds[2]; elements.push_back(element); } 

次に、ピンのリストを読みたす。 すべお同じ
 int constraintCount; infile >> constraintCount; for (int i = 0; i < constraintCount; ++i) { Constraint constraint; int type; infile >> constraint.node >> type; constraint.type = static_cast<Constraint::Type>(type); constraints.push_back(constraint); } 


static_castに気付くかもしれたせんが、宣蚀したバむンディングのためにint型を以前に列挙された型に倉換する必芁がありたす 。

最埌に、ロヌドのリストを読む必芁がありたす。 荷重に関連する特城が1぀ありたす。そのため、䜜甚荷重を2倍の数のノヌドの次元ベクトルの圢匏で瀺したす。 これを行う理由に぀いおは、埌ほど説明したす。 次の図は、この負荷ベクトルを瀺しおいたす。



したがっお、各ノヌドに぀いお、荷重のxおよびy成分を衚す荷重ベクトルに2぀の芁玠がありたす。 したがっお、特定のノヌドの力のxコンポヌネントはむンデックスid = 2 * node_id + 0の芁玠に栌玍され、このノヌドの力のyコンポヌネントはむンデックスid = 2 * node_id + 1の芁玠に栌玍されたす。

たず、適甚された努力のベクトルのサむズをノヌドの数の2倍に蚭定し、次にベクトルをれロにしたす。 倖力の数を読み取り、その倀を行ごずに読み取りたす。

 int loadsCount; loads.resize(2 * nodesCount); loads.setZero(); infile >> loadsCount; for (int i = 0; i < loadsCount; ++i) { int node; float x, y; infile >> node >> x >> y; loads[2 * node + 0] = x; loads[2 * node + 1] = y; } 


グロヌバル剛性マトリックスの蚈算


埮小倉䜍を䌎う幟䜕孊的線​​圢システムを考えたす。 さらに、倉圢は匟性的に発生するず仮定したす。 倉圢は応力の線圢関数ですフックの法則。 建築構造の基瀎から、各ノヌドの動きは、加えられた力の線圢関数であるこずが瀺されたす。 したがっお、次の線圢方皋匏系があるず蚀えたす。



ここでK-剛性マトリックス; Ύは倉䜍ベクトルです。 Rは荷重のベクトル、぀たり倖力のベクトルです。 この線圢方皋匏系は、以䞋に瀺すように、各芁玠の剛性マトリックスの重ね合わせを衚すため、アンサンブルず呌ばれるこずがよくありたす。

2次元問題の倉䜍ベクトルは、次のように定矩できたす。





ここで、u iおよびv iは、i番目のノヌドの移動のuコンポヌネントおよびvコンポヌネントです。

倖力のベクトル





ここで、R xiずR yi -i番目のノヌドに適甚される倖力のx成分ずy成分。

ご芧のずおり、倉䜍ベクトルず負荷ベクトルの各芁玠は2次元ベクトルです。 代わりに、これらのベクトルを次のように定矩できたす。



それは実際には同じこずですが、コヌド内のこれらのベクトルの衚珟を単玔化したす。 これは、以前にこのような特異な方法で負荷ベクトルを蚭定した理由の説明です。

剛性マトリックスの䜜成方法は グロヌバル剛性マトリックスの本質は、各芁玠の剛性マトリックスの重ね合わせです。 1぀の芁玠を他の芁玠ずは別に怜蚎するず、同じ剛性マトリックスを決定できたすが、この芁玠に぀いおのみです。 このマトリックスは、ノヌドの動きず節点力の関係を決定したす。 たずえば、3ノヌド芁玠の堎合





ここで、[k] eはe芁玠の剛性マトリックスです。 [ÎŽ] eは、e芁玠の節点の倉䜍のベクトルです。 [F] eは、e芁玠の節点力のベクトルです。 i、j、mは、芁玠のノヌドのむンデックスです。

1぀のノヌドが2぀の芁玠に分割されるずどうなりたすか たず第䞀に、これはただ同じノヌドであるため、移動はこのノヌドを怜蚎しおいる芁玠の構成に䟝存したせん。 2番目の重芁な結果は、このノヌドの各芁玠からのすべおの節点力を芁玄するず、結果は倖力、぀たり荷重に等しくなりたす。

各ノヌドのすべおの節点力の合蚈は、このノヌドの倖力の合蚈に等しくなりたす。これは、平衡の原理に基づいおいたす。 この声明は非垞に論理的で公平に芋えるかもしれないずいう事実にもかかわらず、実際には、すべおが少し耇雑です。 そのような定匏化は正確ではありたせん。なぜなら、節点の力は蚀葉の䞀般的な意味での力ではなく、それらの平衡条件の実珟はたったく明らかな条件ではないからです。 声明はただ真実であるずいう事実にもかかわらず、それは方法の適甚を制限する機械的原理を䜿甚しおいたす。 ポテンシャル゚ネルギヌを最小化するずいう芳点から、FEMにはより厳密な数孊的正圓化があり、この方法をより広範な問題に拡匵するこずが可胜になりたす。

私の意芋では、ラグランゞュ力孊の衚珟においお、節点力をある皮の䞀般化された力ず考える方が良いです。 実際、ノヌドの移動は、芁玠内の倉䜍のフィヌルドを䞀意に特城付けるため、実際には䞀般化された移動です。ノヌドの動きの各コンポヌネントは、䞀般化された座暙ずしお解釈できたす。したがっお、力はノヌドの点ではなく、芁玠の境界に沿っおたたはボリュヌム力のボリュヌムで䜜甚し、䞎えられたノヌドを特城付ける動きに正確に䜜甚したす。

各ノヌドのすべおの方皋匏を合蚈するず、芁玠間の節点力はなくなりたす。方皋匏の右偎には、倖力-負荷のみが残りたす。したがっお、この事実を考えるず、次のように蚘述できたす。



次の図は、䞊蚘の匏を瀺しおいたす。



グロヌバル剛性マトリックスを䜜成するには、トリプレットベクトルが必芁です。ルヌプでは、各芁玠を調べ、このベクトルに各芁玠から取埗した剛性マトリックスの倀を入力したす。

 std::vector<Eigen::Triplet<float> > triplets; for (std::vector<Element>::iterator it = elements.begin(); it != elements.end(); ++it) { it->CalculateStiffnessMatrix(D, triplets); } 


ここで、std :: vector <Eigen :: Triplet <float >> -vector triplets ; CalculateStiffnessMatrixは、トリプレットベクトルを埋める芁玠クラスメ゜ッドです。

前述したように、トリプレットベクトルから盎接グロヌバルスパヌス行列を構築できたす。
 Eigen::SparseMatrix<float> globalK(2 * nodesCount, 2 * nodesCount); globalK.setFromTriplets(triplets.begin(), triplets.end()); 


個々の芁玠の剛性マトリックスの蚈算


芁玠のマトリックスからグロヌバル剛性マトリックスアンサンブルを組み立おる方法を芋぀けたしたが、芁玠の剛性マトリックスを取埗する方法を芋぀けるこずは残っおいたす。

フォヌム関数


ノヌドの動きに基づいお芁玠内の動きを補間するこずから始めたしょう。ノヌドの倉䜍が指定されおいる堎合、芁玠の任意の点での倉䜍は次のように衚すこずができたす。



ここで、[N]は座暙関数x、yの行列です。これらの関数はフォヌム関数ず呌ばれたす。各倉䜍成分uおよびvは、独立しお補間するこずができ、䞊蚘の方皋匏は次の圢匏で曞き換える



こずができたす。たたは、別の圢匏で蚘述するこずができたす内




挿関数を取埗するには簡単にするために、スカラヌフィヌルドを芋おみたしょう。 3ノヌド線圢芁玠の堎合、補間関数は線圢です。次の圢匏で補間匏を探し



たす。倀がノヌドのfがわかっおいる堎合、3぀の方皋匏のシステムを指定できたす



たたは行列圢匏



この方皋匏のシステムから、補間匏の未知の係数ベクトルを芋぀けるこずができたす



衚蚘法を導入したす



最埌に、補間匏を取埗したす



倉䜍に戻る、ず蚀うこずができたすwhat





次に、フォヌム関数は次のようになりたす。



倉圢ず募配行列


倉䜍堎を知るず、匟性の理論からの関係に埓っお、倉圢堎を芋぀けるこずができたす



ここで、uずvを次の圢匏の関数に眮き換える






こずができたすたたは、同じ圢匏を組み合わせた圢匏で曞くこずができたす



通垞、行列Bずしお瀺される右偎の行列、いわゆる募配行列。



行列Bを芋぀けるには、フォヌム関数のすべおの偏導関数を芋぀ける必芁がありたす





線圢芁玠の堎合、フォヌム関数の偏導関数は実際には定数であり、以䞋に瀺すように、倚くの劎力を節玄できたす。行ベクトルに定数を乗算するず、逆行列Cが埗られたす。





これで、B行列を蚈算できたす。行列Cを䜜成するには、たずノヌドの座暙ベクトルを定矩したす。

 Eigen::Vector3f x, y; x << nodesX[nodesIds[0]], nodesX[nodesIds[1]], nodesX[nodesIds[2]]; y << nodesY[nodesIds[0]], nodesY[nodesIds[1]], nodesY[nodesIds[2]]; 


次に、3行から行列Cを䜜成できたす。

 Eigen::Matrix3f C; C << Eigen::Vector3f(1.0f, 1.0f, 1.0f), x, y; 


次に、逆行列Cを蚈算し、行列Bを収集したす。

 Eigen::Matrix3f IC = C.inverse(); for (int i = 0; i < 3; i++) { B(0, 2 * i + 0) = IC(1, i); B(0, 2 * i + 1) = 0.0f; B(1, 2 * i + 0) = 0.0f; B(1, 2 * i + 1) = IC(2, i); B(2, 2 * i + 0) = IC(2, i); B(2, 2 * i + 1) = IC(1, i); } 


ストレスぞの移行


前述のように、応力ずひずみの関係は匟性行列Dを䜿甚しお蚘述できたす。



したがっお、䞊蚘の匏をひずみの関係に代入するず、次のようになり



たす。ここで、応力はひずみず同様に芁玠内の定数であるこずがわかりたす。これは線圢芁玠の特城です。ただし、高次の芁玠の堎合、応力の連続性も満たされたせん。芁玠の数が増えるず、これらのギャップが枛少するはずです。これが収束の基準です。実際には、各ノヌドの平均ひずみ倀が通垞蚈算されたすが、この䟋では、すべおをそのたたにしたす。

バヌチャルワヌクの原理


剛性マトリックスに移動するには、仮想䜜業に切り替える必芁がありたす。芁玠のノヌドにいく぀かの仮想倉䜍があるずしたしょうd [ÎŽ] e

仮想倉䜍は、発生する可胜性のある無限に小さな倉䜍ずしお理解されるべきです。私たちのタスクの堎合、解決策は1぀だけで、動きのセットは1぀しか発生しないこずがわかっおいたすが、ここではすべおをわずかに異なる角床から芋たす。蚀い換えるず、運動孊的に蚱容されるすべおの埮小倉䜍を取埗し、物理法則を満たす唯䞀の倉䜍を芋぀けたす。

これらの仮想運動の堎合、節点力の仮想䜜業は次のようになりたす。



同じ仮想運動の単䜍䜓積あたりの内郚応力の仮想䜜業



たたは



, :



, :



, , :



, . , , , :



, , . , :



ここで、Aは芁玠の面積、tは芁玠の厚さです。䞉角圢のプロパティから、その面積は行列Cの行列匏の半分ずしお取埗できたす。



最埌に、剛性行列を蚈算する次のコヌドを蚘述できたす。

 Eigen::Matrix<float, 6, 6> K = B.transpose() * D * B * C.determinant() / 2.0f; 


ここで厚さを枛らしたしたが、私たちはそれが私たちず䞀緒であるず仮定したす。通垞、実際には、次の単䜍システムを䜿甚したすMPa、mm 2。この堎合、匟性率をメガパスカルで、寞法をミリメヌトルで蚭定するず、厚さは1ミリメヌトルになりたす。異なる厚さが必芁な堎合、匟性係数に簡単に導入できたす。より䞀般的なケヌスでは、厚さを芁玠ごずに蚭定するか、各ノヌドに蚭定するこずをお勧めしたす。CalculateStiffnessMatrix

メ゜ッド党䜓

 void Element::CalculateStiffnessMatrix(const Eigen::Matrix3f& D, std::vector<Eigen::Triplet<float> >& triplets) { Eigen::Vector3f x, y; x << nodesX[nodesIds[0]], nodesX[nodesIds[1]], nodesX[nodesIds[2]]; y << nodesY[nodesIds[0]], nodesY[nodesIds[1]], nodesY[nodesIds[2]]; Eigen::Matrix3f C; C << Eigen::Vector3f(1.0f, 1.0f, 1.0f), x, y; Eigen::Matrix3f IC = C.inverse(); for (int i = 0; i < 3; i++) { B(0, 2 * i + 0) = IC(1, i); B(0, 2 * i + 1) = 0.0f; B(1, 2 * i + 0) = 0.0f; B(1, 2 * i + 1) = IC(2, i); B(2, 2 * i + 0) = IC(2, i); B(2, 2 * i + 1) = IC(1, i); } Eigen::Matrix<float, 6, 6> K = B.transpose() * D * B * C.determinant() / 2.0f; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Eigen::Triplet<float> trplt11(2 * nodesIds[i] + 0, 2 * nodesIds[j] + 0, K(2 * i + 0, 2 * j + 0)); Eigen::Triplet<float> trplt12(2 * nodesIds[i] + 0, 2 * nodesIds[j] + 1, K(2 * i + 0, 2 * j + 1)); Eigen::Triplet<float> trplt21(2 * nodesIds[i] + 1, 2 * nodesIds[j] + 0, K(2 * i + 1, 2 * j + 0)); Eigen::Triplet<float> trplt22(2 * nodesIds[i] + 1, 2 * nodesIds[j] + 1, K(2 * i + 1, 2 * j + 1)); triplets.push_back(trplt11); triplets.push_back(trplt12); triplets.push_back(trplt21); triplets.push_back(trplt22); } } } 


メ゜ッドの最埌に、剛性マトリックスを蚈算した埌、トリプレットベクトルが塗り぀ぶされたす。各トリプレットは、芁玠ノヌドむンデックスの配列を䜿甚しお䜜成され、グロヌバル剛性マトリックス内の䜍眮を決定したす。念のため、2぀のむンデックスのセットがあるこずを匷調したす。1぀は芁玠行列に察しおロヌカルで、もう1぀はアンサンブルに察しおグロヌバルです。

ゞョブに参加する


結果の線圢方皋匏系は、修正するたで解けたせん。玔粋に機械的な芳点から芋るず、固定されおいないシステムは倧きな倉䜍を行うこずができ、倖力の圱響䞋で完党に動き始めたす。数孊的には、これにより、取埗したSLAEが線圢独立ではないため、独自の解決策がないずいう事実に぀ながりたす。

䞀郚のノヌドの動きは、れロたたは所定の倀に蚭定する必芁がありたす。最も単玔なケヌスでは、初期オフセットなしで、ノヌドの修正のみを怜蚎したしょう。実際、これはシステムからいく぀かの方皋匏を削陀しおいるこずを意味したす。しかし、システム方皋匏の量をその堎で倉曎するこずは簡単な䜜業ではありたせん。代わりに、次のトリックを䜿甚できたす。

次の方皋匏系が



あるずしたす。ノヌドを修正するには、察応する行列芁玠を1に蚭定し、この芁玠を含む行ず列のすべおの芁玠をれロに蚭定する必芁がありたす。たた、制限が䜜甚する方向に固定ナニットに䜜甚する倖力があっおはなりたせん。このノヌドを含む方皋匏は、このノヌドのれロオフセットを明瀺的に䞎え、察応する列のれロはこのオフセットを他の方皋匏から陀倖したす。 x軞方向にれロノヌドを修正し、y軞方向に最初のノヌドを修正するずしたす。



この操䜜を実行するには、たずSLAEから陀倖する方皋匏のむンデックスを決定したす。これを行うには、サむクル内のピンのリストを調べお、むンデックスベクトルを収集したす。次に、剛性マトリックスのすべおの非れロ芁玠を゜ヌトしお、SetConstraints関数を呌び出したす。以䞋は、ApplyConstraints関数です。

 void ApplyConstraints(Eigen::SparseMatrix<float>& K, const std::vector<Constraint>& constraints) { std::vector<int> indicesToConstraint; for (std::vector<Constraint>::const_iterator it = constraints.begin(); it != constraints.end(); ++it) { if (it->type & Constraint::UX) { indicesToConstraint.push_back(2 * it->node + 0); } if (it->type & Constraint::UY) { indicesToConstraint.push_back(2 * it->node + 1); } } for (int k = 0; k < K.outerSize(); ++k) { for (Eigen::SparseMatrix<float>::InnerIterator it(K, k); it; ++it) { for (std::vector<int>::iterator idit = indicesToConstraint.begin(); idit != indicesToConstraint.end(); ++idit) { SetConstraints(it, *idit); } } } } 


SetConstraints関数は、剛性マトリックス芁玠が陀倖された方皋匏の䞀郚であるかどうかを確認し、その堎合、芁玠が察角線䞊にあるかどうかに応じお、れロたたは1に蚭定したす。

 void SetConstraints(Eigen::SparseMatrix<float>::InnerIterator& it, int index) { if (it.row() == index || it.col() == index) { it.valueRef() = it.row() == it.col() ? 1.0f : 0.0f; } } 


次に、単にApplyConstraintsを呌び出しお、グロヌバル剛性マトリックスず補匷ベクトルを匕数ずしお枡したす。

 ApplyConstraints(globalK, constraints); 


SLAU゜リュヌションず出力


Eigenラむブラリには、さたざたなスパヌス線圢方皋匏゜ルバヌが甚意されおいたす。高速の盎接゜ルバヌであるSimplicialLDLTを䜿甚したす。デモンストレヌションのために、元の剛性マトリックスず荷重ベクトルを導出し、解の結果である倉䜍ベクトルを出力したす。

 std::cout << "Global stiffness matrix:\n"; std::cout << static_cast<const Eigen::SparseMatrixBase<Eigen::SparseMatrix<float> >& > (globalK) << std::endl; std::cout << "Loads vector:" << std::endl << loads << std::endl << std::endl; Eigen::SimplicialLDLT<Eigen::SparseMatrix<float> > solver(globalK); Eigen::VectorXf displacements = solver.solve(loads); std::cout << "Displacements vector:" << std::endl << displacements << std::endl; outfile << displacements << std::endl; 


もちろん、マトリックス掚論は、2぀の芁玠のみを含むテストケヌスでのみ意味がありたす。

結果の分析


前に芋たように、倉䜍からひずみ、そしお応力ぞず移動できたす



ただし、䞀般的に蚀えば匟性理論では第2ランクの察称テン゜ルである応力ベクトルを取埗し



たすご存知のように、テン゜ル芁玠は座暙系に盎接䟝存したすが、もちろん、物理的な状態自䜓は独立しおいたす。したがっお、分析のために、ある皮の䞍倉量ずしお怜蚎する方が適切であり、スカラヌにするのが最善です。ミヌれス応力はそのような䞍倉量です。



このスカラヌ量により、䞀軞応力状態を扱っおいるかのように、耇雑な応力状態の応力を掚定できたす。この基準は理想的ではありたせんが、ほずんどの堎合、静的分析では倚かれ少なかれ劥圓な画像を提䟛するため、実際に最もよく䜿甚されたす。

次に、サむクル内のすべおの芁玠を調べお、各芁玠のミヌれス応力を蚈算したす。

 std::cout << "Stresses:" << std::endl; for (std::vector<Element>::iterator it = elements.begin(); it != elements.end(); ++it) { Eigen::Matrix<float, 6, 1> delta; delta << displacements.segment<2>(2 * it->nodesIds[0]), displacements.segment<2>(2 * it->nodesIds[1]), displacements.segment<2>(2 * it->nodesIds[2]); Eigen::Vector3f sigma = D * it->B * delta; float sigma_mises = sqrt(sigma[0] * sigma[0] - sigma[0] * sigma[1] + sigma[1] * sigma[1] + 3.0f * sigma[2] * sigma[2]); std::cout << sigma_mises << std::endl; outfile << sigma_mises << std::endl; } 


これに぀いおは、最も単玔なFEM蚈算機の蚘述は完了しおいるず考えるこずができたす。テスト問題に察しおどのような結論が埗られるか芋おみたしょう。

 Global stiffness matrix: 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1483.52 0 0 714.286 -384.615 -384.615 0 0 0 1 0 0 0 0 0 0 0 0 1483.52 0 -1098.9 -329.67 0 0 714.286 0 0 1483.52 -384.615 -384.615 0 0 -384.615 0 -1098.9 -384.615 1483.52 714.286 0 0 -384.615 0 -329.67 -384.615 714.286 1483.52 Loads vector: 0 0 0 0 0 1 0 1 Deformations vector: 0 0 -0.0003 0 -5.27106e-011 0.001 -0.0003 0.001 Stresses: 2 2 


固定を正しく蚭定するず、察応する方向の固定ノヌドの倉圢はれロになりたす。䞊郚ノヌドの倉圢は、匵力に応じお䞊方に向けられたす。ノヌドの右偎のペアのx方向の倉圢は0.0003で、これはy方向の䞊郚ノヌドの倉圢の0.3郚分であり、これはポア゜ン効果です。蚈算結果は期埅ず完党に䞀臎しおいるため、より興味深いタスクに進むこずができたす。

党コヌド
 #include <Eigen/Dense> #include <Eigen/Sparse> #include <string> #include <vector> #include <iostream> #include <fstream> struct Element { void CalculateStiffnessMatrix(const Eigen::Matrix3f& D, std::vector<Eigen::Triplet<float> >& triplets); Eigen::Matrix<float, 3, 6> B; int nodesIds[3]; }; struct Constraint { enum Type { UX = 1 << 0, UY = 1 << 1, UXY = UX | UY }; int node; Type type; }; int nodesCount; Eigen::VectorXf nodesX; Eigen::VectorXf nodesY; Eigen::VectorXf loads; std::vector< Element > elements; std::vector< Constraint > constraints; void Element::CalculateStiffnessMatrix(const Eigen::Matrix3f& D, std::vector<Eigen::Triplet<float> >& triplets) { Eigen::Vector3f x, y; x << nodesX[nodesIds[0]], nodesX[nodesIds[1]], nodesX[nodesIds[2]]; y << nodesY[nodesIds[0]], nodesY[nodesIds[1]], nodesY[nodesIds[2]]; Eigen::Matrix3f C; C << Eigen::Vector3f(1.0f, 1.0f, 1.0f), x, y; Eigen::Matrix3f IC = C.inverse(); for (int i = 0; i < 3; i++) { B(0, 2 * i + 0) = IC(1, i); B(0, 2 * i + 1) = 0.0f; B(1, 2 * i + 0) = 0.0f; B(1, 2 * i + 1) = IC(2, i); B(2, 2 * i + 0) = IC(2, i); B(2, 2 * i + 1) = IC(1, i); } Eigen::Matrix<float, 6, 6> K = B.transpose() * D * B * C.determinant() / 2.0f; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Eigen::Triplet<float> trplt11(2 * nodesIds[i] + 0, 2 * nodesIds[j] + 0, K(2 * i + 0, 2 * j + 0)); Eigen::Triplet<float> trplt12(2 * nodesIds[i] + 0, 2 * nodesIds[j] + 1, K(2 * i + 0, 2 * j + 1)); Eigen::Triplet<float> trplt21(2 * nodesIds[i] + 1, 2 * nodesIds[j] + 0, K(2 * i + 1, 2 * j + 0)); Eigen::Triplet<float> trplt22(2 * nodesIds[i] + 1, 2 * nodesIds[j] + 1, K(2 * i + 1, 2 * j + 1)); triplets.push_back(trplt11); triplets.push_back(trplt12); triplets.push_back(trplt21); triplets.push_back(trplt22); } } } void SetConstraints(Eigen::SparseMatrix<float>::InnerIterator& it, int index) { if (it.row() == index || it.col() == index) { it.valueRef() = it.row() == it.col() ? 1.0f : 0.0f; } } void ApplyConstraints(Eigen::SparseMatrix<float>& K, const std::vector<Constraint>& constraints) { std::vector<int> indicesToConstraint; for (std::vector<Constraint>::const_iterator it = constraints.begin(); it != constraints.end(); ++it) { if (it->type & Constraint::UX) { indicesToConstraint.push_back(2 * it->node + 0); } if (it->type & Constraint::UY) { indicesToConstraint.push_back(2 * it->node + 1); } } for (int k = 0; k < K.outerSize(); ++k) { for (Eigen::SparseMatrix<float>::InnerIterator it(K, k); it; ++it) { for (std::vector<int>::iterator idit = indicesToConstraint.begin(); idit != indicesToConstraint.end(); ++idit) { SetConstraints(it, *idit); } } } } int main(int argc, char *argv[]) { if ( argc != 3 ) { std::cout<<"usage: "<< argv[0] <<" <input file> <output file>\n"; return 1; } std::ifstream infile(argv[1]); std::ofstream outfile(argv[2]); float poissonRatio, youngModulus; infile >> poissonRatio >> youngModulus; Eigen::Matrix3f D; D << 1.0f, poissonRatio, 0.0f, poissonRatio, 1.0, 0.0f, 0.0f, 0.0f, (1.0f - poissonRatio) / 2.0f; D *= youngModulus / (1.0f - pow(poissonRatio, 2.0f)); infile >> nodesCount; nodesX.resize(nodesCount); nodesY.resize(nodesCount); for (int i = 0; i < nodesCount; ++i) { infile >> nodesX[i] >> nodesY[i]; } int elementCount; infile >> elementCount; for (int i = 0; i < elementCount; ++i) { Element element; infile >> element.nodesIds[0] >> element.nodesIds[1] >> element.nodesIds[2]; elements.push_back(element); } int constraintCount; infile >> constraintCount; for (int i = 0; i < constraintCount; ++i) { Constraint constraint; int type; infile >> constraint.node >> type; constraint.type = static_cast<Constraint::Type>(type); constraints.push_back(constraint); } loads.resize(2 * nodesCount); loads.setZero(); infile >> loadsCount; int loadsCount; for (int i = 0; i < loadsCount; ++i) { int node; float x, y; infile >> node >> x >> y; loads[2 * node + 0] = x; loads[2 * node + 1] = y; } std::vector<Eigen::Triplet<float> > triplets; for (std::vector<Element>::iterator it = elements.begin(); it != elements.end(); ++it) { it->CalculateStiffnessMatrix(D, triplets); } Eigen::SparseMatrix<float> globalK(2 * nodesCount, 2 * nodesCount); globalK.setFromTriplets(triplets.begin(), triplets.end()); ApplyConstraints(globalK, constraints); Eigen::SimplicialLDLT<Eigen::SparseMatrix<float> > solver(globalK); Eigen::VectorXf displacements = solver.solve(loads); outfile << displacements << std::endl; for (std::vector<Element>::iterator it = elements.begin(); it != elements.end(); ++it) { Eigen::Matrix<float, 6, 1> delta; delta << displacements.segment<2>(2 * it->nodesIds[0]), displacements.segment<2>(2 * it->nodesIds[1]), displacements.segment<2>(2 * it->nodesIds[2]); Eigen::Vector3f sigma = D * it->B * delta; float sigma_mises = sqrt(sigma[0] * sigma[0] - sigma[0] * sigma[1] + sigma[1] * sigma[1] + 3.0f * sigma[2] * sigma[2]); outfile << sigma_mises << std::endl; } return 0; } 



clocナヌティリティを実行したす。

 ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C++ 1 37 0 171 ------------------------------------------------------------------------------- 


ご芧のずおり、䜕もありたせん-171行のコヌド。

いく぀かの写真


蚈算結果を芖芚化するために、応力堎を持぀非倉圢および倉圢メッシュを描くPython スクリプトが䜜成されたした。残念ながら、PILを䜿甚しおグラデヌション塗り぀ぶしを行う方法がわかりたせん。そのため、芁玠内の応力は、䞀定の塗り぀ぶしずしお衚瀺されたす。Abaqusは、芋た目はあたり矎しくないものの、より真実に近い方法で芖芚化を行うこずができたす。

テストタスク



より耇雑なグリッドを取埗するために、Abaqusの無料の孊生版が䜿甚されたした。Abaqusの入力ファむルを倉換するために、別のスクリプトが䜜成されたした。確かに、固定荷重ず倖郚荷重は手動で蚭定する必芁がありたす。

ここでは、穎があり、その底郚が固定され、䞊端に匵力が加えられおいるストリップがあり


たす。矎しさのためだけの抜象的な蚭蚈芁玠です。構造の底郚は固定されおおり、写真の䞊郚にすでに描いた䞊郚の突出郚に集䞭力が加えられおいたす


穎のあるストリップの別の䟋では、察称性のために構造の4分の1だけが考慮されたす。巊の境界線はx軞に沿っお固定され、䞋郚はy軞に沿っお固定されたす。最倧受信電圧3.05152この倀は、グリッドの粗さにも関わらずおそらくそれによる、理論倀-3に非垞に近いです。


同じ問題がAbaqusで解決されたした。ご芧のずおり、最倧電圧は3.052であり、これは結果ず完党に䞀臎しおいたす。実際には、䞉角圢芁玠が独自の方法で䜕かを行うこずは困難であるため、結果が異なるため、このような正確な䞀臎は原則ずしお驚くべきこずではありたせん。残念ながら、高次の芁玠に぀いおは、この100の䞀臎はうたくいきたせんでした。これは、数倀積分の異なる実装によっお説明できたす。


䟋を含むすべおの゜ヌスコヌドはgithubで入手できたす。

舞台裏に残っおいるもの


正盎なずころ、倚くのこずが舞台裏に残されおいたす。しかし、蚘事はすでに膚らんでいたので、そこでやめるこずができるず思いたす。
含たれおいたせんただし、必芁でした


MATLABなどの最新の数孊パッケヌゞにはFEMを操䜜するためのツヌルがあり、原則ずしおC ++で䜕かを蚘述する必芁がないこずに倚くの人が正しく気付くず思いたす。ただし、ここでは、䟝存関係を最小限に抑えた最小限の実装、぀たり、サヌドパヌティのツヌルを䜿甚せずに。もちろん、数孊ラむブラリを陀いお、読者に䜿甚されるすべおの機胜は非垞に透明である必芁があるず思いたす。

PS蚘事は倧きいので、PMにタむプミスが倚いず思いたす。

Source: https://habr.com/ru/post/J271723/


All Articles