Exemple #1
0
        private static void TestStiffness0()
        {
            var factory = new ContinuumElement2DFactory(thickness, material0, dynamicMaterial);
            ContinuumElement2D quad8 = factory.CreateElement(CellType.Quad8, nodeSet0);
            IMatrix            K     = quad8.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 375957.1179055000, -130889.8953535400, 150398.7276607000, -30577.4536395990, 256263.9470137800, -74238.0130438120, 120262.5252654800, -29264.7336935000, -201002.5528104600, 86903.8674540020, -257013.8069723100, 62503.0900498910, -46878.8680758500, 18155.7769717120, -397987.0899868400, 97407.3612548510 },
                { -130889.8953535400, 264620.9765739100, -32500.5305626760, 108395.9237548000, -74238.0130438120, 148536.2310068900, -27341.6567704230, 66761.0027359010, 94596.1751463100, -240343.8078467800, 62503.0900498910, -121948.9418401700, 18155.7769717120, -45778.2662465080, 89715.0535625430, -180243.1181380300 },
                { 150398.7276607000, -32500.5305626760, 227070.8522891000, 24999.1791433860, 228075.7272750800, -35916.2249916640, 84715.8706078410, 5691.9746958972, -125567.3958918900, -7749.8459233937, -292871.0398821500, 29891.4228662980, -48734.4768523870, -12619.4433884890, -223088.2652062900, 28203.4681606430 },
                { -30577.4536395990, 108395.9237548000, 24999.1791433860, 135717.9797677600, -37839.3019147410, 115695.2678105500, 5691.9746958972, 47395.7262976820, -15442.1536157010, -174789.3743509800, 37583.7305586050, -85742.6925983560, -12619.4433884890, -59359.2032811550, 28203.4681606430, -87313.6274002970 },
                { 256263.9470137800, -74238.0130438120, 228075.7272750800, -37839.3019147410, 758698.8330168600, -151201.1982884900, 164115.4999410500, -25847.0928360870, -256843.4834062300, 67264.1450855650, -543079.2639940800, 68308.1044726010, -237729.8010194900, 72706.8336500980, -369501.4588269600, 80846.5228748690 },
                { -74238.0130438120, 148536.2310068900, -35916.2249916640, 115695.2678105500, -151201.1982884900, 368478.4546134000, -27770.1697591640, 85552.6038287820, 67264.1450855650, -166187.6357417500, 60615.7967802930, -223855.9737213700, 80399.1413424050, -193251.7815799700, 80846.5228748690, -134967.1662165300 },
                { 120262.5252654800, -27341.6567704230, 84715.8706078410, 5691.9746958972, 164115.4999410500, -27770.1697591640, 120174.7405891600, 2419.9582040241, -64973.3681564819, 9886.9381472210, -156296.6219667900, 10235.6574488430, -29392.1129538440, -12237.5732893820, -238606.5333264100, 39114.8713229830 },
                { -29264.7336935000, 66761.0027359010, 5691.9746958972, 47395.7262976820, -25847.0928360870, 85552.6038287820, 2419.9582040241, 63320.7521890160, 9886.9381472210, -67395.8289291320, 10235.6574488430, -47867.5471489640, -19929.8809816900, -81314.4790110740, 46807.1790152900, -66452.2299622090 },
                { -201002.5528104600, 94596.1751463100, -125567.3958918900, -15442.1536157010, -256843.4834062300, 67264.1450855650, -64973.3681564819, 9886.9381472210, 429358.6456627000, -85681.3574299900, 91327.9338391870, 31186.8509038820, -120846.2914647200, 7660.6709468983, 248546.5122279100, -109471.2691841800 },
                { 86903.8674540020, -240343.8078467800, -7749.8459233937, -174789.3743509800, 67264.1450855650, -166187.6357417500, 9886.9381472210, -67395.8289291320, -85681.3574299900, 501789.8020087000, 31186.8509038820, -24500.7443298540, 7660.6709468983, 60837.6092548520, -109471.2691841800, 110589.9799349400 },
                { -257013.8069723100, 62503.0900498910, -292871.0398821500, 37583.7305586050, -543079.2639940800, 60615.7967802930, -156296.6219667900, 10235.6574488430, 91327.9338391870, 31186.8509038820, 618909.3895160900, -107045.7505943100, 156953.5398894400, -38863.3219066200, 382069.8695706200, -56216.0532405820 },
                { 62503.0900498910, -121948.9418401700, 29891.4228662980, -85742.6925983560, 68308.1044726010, -223855.9737213700, 10235.6574488430, -47867.5471489640, 31186.8509038820, -24500.7443298540, -107045.7505943100, 363810.1766979700, -38863.3219066200, 60473.5634510330, -56216.0532405820, 79632.1594897160 },
                { -46878.8680758500, 18155.7769717120, -48734.4768523870, -12619.4433884890, -237729.8010194900, 80399.1413424050, -29392.1129538440, -19929.8809816900, -120846.2914647200, 7660.6709468983, 156953.5398894400, -38863.3219066200, 585811.6805262000, -190782.6753367700, -259183.6700493400, 155979.7323525500 },
                { 18155.7769717120, -45778.2662465080, -12619.4433884890, -59359.2032811550, 72706.8336500980, -193251.7815799700, -12237.5732893820, -81314.4790110740, 7660.6709468983, 60837.6092548520, -38863.3219066200, 60473.5634510330, -190782.6753367700, 616593.8061240300, 155979.7323525500, -358201.2487112100 },
                { -397987.0899868400, 89715.0535625430, -223088.2652062900, 28203.4681606430, -369501.4588269600, 80846.5228748690, -238606.5333264100, 46807.1790152900, 248546.5122279100, -109471.2691841800, 382069.8695706200, -56216.0532405820, -259183.6700493400, 155979.7323525500, 857750.6355973100, -235864.6335411300 },
                { 97407.3612548510, -180243.1181380300, 28203.4681606430, -87313.6274002970, 80846.5228748690, -134967.1662165300, 39114.8713229830, -66452.2299622090, -109471.2691841800, 110589.9799349400, -56216.0532405820, 79632.1594897160, 155979.7323525500, -358201.2487112100, -235864.6335411300, 636955.2510036100 }
            }; // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-10));
        }
Exemple #2
0
        public static void TestStrainsStresses0()
        {
            var factory = new ContinuumElement2DFactory(thickness, material0, null);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet0);

            // Abaqus results
            double[] displacements =
            {
                0.0, 0.0,                   // Node 1
                0.0, 0.0,                   // Node 2
                -3.1797E-03, -8.6560E-03,   // Node 3
                4.4274E-03, -1.8570E-02     // Node 4
            };

            // The Gauss points in Abaqus have the same order as in GaussLegendre2D.Order2x2: Xi major, Eta minor
            double[][] expectedStrainsAtGPs =
            {
                new double[] {  1.1178E-03,  1.5988E-03, -7.4619E-03 },  // Gauss point 1
                new double[] { -1.2757E-03,  8.6753E-04, -4.5415E-03 },  // Gauss point 2
                new double[] {  2.8614E-04, -7.3510E-04, -4.0517E-03 },  // Gauss point 3
                new double[] { -2.3014E-03, -1.8646E-03, -5.0422E-04 }   // Gauss point 4
            };
            double[][] expectedStressesAtGPs =
            {
                new double[] {  368.6,  446.3, -602.7 },  // Gauss point 1
                new double[] { -234.3,  111.9, -366.8 },  // Gauss point 2
                new double[] {  15.14, -149.8, -327.3 },  // Gauss point 3
                new double[] { -660.2, -589.6, -40.73 }   // Gauss point 4
            };

            // However the order of nodes is different, since in that Abaqus job the preprocessor numbered them differently from
            // the counter-clockwise order of Quad4 nodes.
            double[][] expectedStrainsAtNodes =
            {
                new double[] {  2.2723E-03,  2.6674E-03, -9.6950E-03 },  // Node 1
                new double[] { -1.7504E-03,  1.6532E-03, -5.0343E-03 },  // Node 2
                new double[] { -3.6499E-03, -3.3314E-03,  2.3560E-03 },  // Node 3
                new double[] {  9.5484E-04, -1.1226E-03, -4.1860E-03 }   // Node 4
            };
            double[][] expectedStressesAtNodes =
            {
                new double[] {   709.0,   772.9, -783.1 },  // Node 1
                new double[] {  -289.5,   260.3, -406.6 },  // Node 2
                new double[] { -1073.0, -1021.0,  190.3 },  // Node 3
                new double[] {   142.6,  -193.0, -338.1 }   // Node 4
            };

            (IReadOnlyList <double[]> strainsAtGPs, IReadOnlyList <double[]> stressesAtGPs) =
                quad4.UpdateStrainsStressesAtGaussPoints(displacements);
            IReadOnlyList <double[]> strainsAtNodes =
                quad4.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, quad4.Interpolation);
            IReadOnlyList <double[]> stressesAtNodes =
                quad4.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, quad4.Interpolation);

            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtGPs, strainsAtGPs, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtGPs, stressesAtGPs, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtNodes, strainsAtNodes, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtNodes, stressesAtNodes, 1e-3));
        }
Exemple #3
0
        public static void TestStrainsStresses1()
        {
            var factory = new ContinuumElement2DFactory(thickness, material0, null);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet2);

            // Abaqus results
            double[] displacements =
            {
                0.0, 0.0,                     // Node 1
                0.0, 0.0,                     // Node 2
                1.0, -499.614E-03,            // Node 4
                986.100E-03, 1.0              // Node 3
            };

            // The Gauss points in Abaqus have the same order as in GaussLegendre2D.Order2x2: Xi major, Eta minor
            double[][] expectedStrainsAtGPs =
            {
                new double[] { 1.46867E-03,  341.547E-03,  336.066E-03 },  // Gauss point 1
                new double[] { 1.46867E-03, -91.3541E-03,  340.078E-03 },  // Gauss point 2
                new double[] { 5.48114E-03,  341.547E-03, -96.8352E-03 },  // Gauss point 3
                new double[] { 5.48114E-03, -91.3541E-03, -92.8228E-03 }   // Gauss point 4
            };
            double[][] expectedStressesAtGPs =
            {
                new double[] {  23.9845E+03,  78.9202E+03,  27.1438E+03 },  // Gauss point 1
                new double[] { -5.98559E+03, -20.9800E+03,  27.4679E+03 },  // Gauss point 2
                new double[] {  24.9104E+03,  79.1980E+03, -7.82131E+03 },  // Gauss point 3
                new double[] { -5.05964E+03, -20.7023E+03, -7.49722E+03 }   // Gauss point 4
            };

            // The order of the nodes is also the same (at least in this job)
            double[][] expectedStrainsAtNodes =
            {
                new double[] { 58.2077E-12,  500.000E-03,  493.050E-03 },  // Node 1
                new double[] {         0.0, -249.807E-03,    500.0E-03 },  // Node 2
                new double[] { 6.94981E-03, -249.807E-03, -249.807E-03 },  // Node 4
                new double[] { 6.94981E-03,  500.000E-03, -256.757E-03 }   // Node 3
            };
            double[][] expectedStressesAtNodes =
            {
                new double[] {  34.6154E+03,  115.385E+03,  39.8233E+03 },  // Node 1
                new double[] { -17.2943E+03, -57.6478E+03,  40.3846E+03 },  // Node 2
                new double[] { -15.6905E+03, -57.1666E+03, -20.1767E+03 },  // Node 4
                new double[] {  36.2192E+03,  115.866E+03, -20.7380E+03 }   // Node 3
            };

            (IReadOnlyList <double[]> strainsAtGPs, IReadOnlyList <double[]> stressesAtGPs) =
                quad4.UpdateStrainsStressesAtGaussPoints(displacements);
            IReadOnlyList <double[]> strainsAtNodes =
                quad4.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, quad4.Interpolation);
            IReadOnlyList <double[]> stressesAtNodes =
                quad4.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, quad4.Interpolation);

            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtGPs, strainsAtGPs, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtGPs, stressesAtGPs, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtNodes, strainsAtNodes, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtNodes, stressesAtNodes, 1e-4));
        }
Exemple #4
0
        public static void TestStrainsStresses0()
        {
            var factory             = new ContinuumElement2DFactory(thickness, material0, null);
            ContinuumElement2D tri3 = factory.CreateElement(CellType.Tri3, nodeSet0);

            // Abaqus results
            double[] displacements =
            {
                0.0, 0.0,                    // Node 1
                0.0, 0.0,                    // Node 2
                -1.4632E-03, -1.2747E-02     // Node 3
            };

            // There is only 1 Gauss point.
            double[][] expectedStrainsAtGPs =
            {
                new double[] { -4.8201E-04, 7.4983E-04, -4.1130E-03 }                   // Gauss point 1
            };
            double[][] expectedStressesAtGPs =
            {
                new double[] { -59.32, 139.7, -332.2 }                  // Gauss point 1
            };

            // The order of the nodes is the same (at least in this job)
            double[][] expectedStrainsAtNodes =
            {
                new double[] { -4.8201E-04, 7.4983E-04, -4.1130E-03 },   // Node 1
                new double[] { -4.8201E-04, 7.4983E-04, -4.1130E-03 },   // Node 2
                new double[] { -4.8201E-04, 7.4983E-04, -4.1130E-03 }    // Node 3
            };
            double[][] expectedStressesAtNodes =
            {
                new double[] { -59.32, 139.7, -332.2 },  // Node 1
                new double[] { -59.32, 139.7, -332.2 },  // Node 2
                new double[] { -59.32, 139.7, -332.2 }   // Node 3
            };

            (IReadOnlyList <double[]> strainsAtGPs, IReadOnlyList <double[]> stressesAtGPs) =
                tri3.UpdateStrainsStressesAtGaussPoints(displacements);
            IReadOnlyList <double[]> strainsAtNodes =
                tri3.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, tri3.Interpolation);
            IReadOnlyList <double[]> stressesAtNodes =
                tri3.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, tri3.Interpolation);

            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtGPs, strainsAtGPs, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtGPs, stressesAtGPs, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtNodes, strainsAtNodes, 1e-4));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtNodes, stressesAtNodes, 1e-3));
        }
Exemple #5
0
        private static void TestStiffness0()
        {
            var factory             = new ContinuumElement2DFactory(thickness, material0, dynamicMaterial);
            ContinuumElement2D tri3 = factory.CreateElement(CellType.Tri3, nodeSet0);
            IMatrix            K    = tri3.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 43303.16742081400, 5294.11764705880, -43778.28054298600, -44796.38009049800, 475.11312217194, 39502.26244343900 },
                { 5294.11764705880, 122361.99095023000, -39027.14932126700, -104660.63348416000, 33733.03167420800, -17701.35746606300 },
                { -43778.28054298600, -39027.14932126700, 151866.51583710000, 66176.47058823500, -108088.23529412000, -27149.32126696800 },
                { -44796.38009049800, -104660.63348416000, 66176.47058823500, 127601.80995475000, -21380.09049773800, -22941.17647058800 },
                { 475.11312217194, 33733.03167420800, -108088.23529412000, -21380.09049773800, 107613.12217195000, -12352.94117647100 },
                { 39502.26244343900, -17701.35746606300, -27149.32126696800, -22941.17647058800, -12352.94117647100, 40642.53393665200 }
            };             // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-10));
        }
Exemple #6
0
        private static void TestStiffness2()
        {
            var factory = new ContinuumElement2DFactory(thickness, material1, dynamicMaterial);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet1);
            IMatrix            K     = quad4.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 879120.87912088, 357142.85714286, -109890.10989011, -27472.527472527, -439560.43956044, -357142.85714286, -329670.32967033, 27472.527472527 },
                { 357142.85714286, 1593406.5934066, 27472.527472528, 604395.60439560, -357142.85714286, -796703.29670329, -27472.527472528, -1401098.9010989 },
                { -109890.10989011, 27472.527472528, 879120.87912088, -357142.85714286, -329670.32967033, -27472.527472527, -439560.43956044, 357142.85714286 },
                { -27472.527472527, 604395.60439560, -357142.85714286, 1593406.5934066, 27472.527472528, -1401098.9010989, 357142.85714286, -796703.29670329 },
                { -439560.43956044, -357142.85714286, -329670.32967033, 27472.527472528, 879120.87912088, 357142.85714286, -109890.10989011, -27472.527472527 },
                { -357142.85714286, -796703.29670329, -27472.527472527, -1401098.9010989, 357142.85714286, 1593406.5934066, 27472.527472528, 604395.60439560 },
                { -329670.32967033, -27472.527472528, -439560.43956044, 357142.85714286, -109890.10989011, 27472.527472528, 879120.87912088, -357142.85714286 },
                { 27472.527472527, -1401098.9010989, 357142.85714286, -796703.29670329, -27472.527472527, 604395.60439560, -357142.85714286, 1593406.5934066 }
            };             // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-10));
        }
Exemple #7
0
        private static void TestStiffness0()
        {
            var factory = new ContinuumElement2DFactory(thickness, material0, dynamicMaterial);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet0);
            IMatrix            K     = quad4.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 181603.19122884000, -89089.52288016200, -4991.10465483030, 7519.91442892909, -126789.16986973000, 70773.21914644800, -49822.91670427800, 10796.38930478500 },
                { -89089.52288016200, 210532.99196037000, 13289.14519816000, -85869.32985046300, 70773.21914644800, -146868.68100448000, 5027.15853555400, 22205.01889457400 },
                { -4991.10465483030, 13289.14519816000, 73155.65851293700, 4056.21872780570, -66433.22620703800, 10577.55360637600, -1731.32765106900, -27922.91753234200 },
                { 7519.91442892909, -85869.32985046300, 4056.21872780570, 85360.61861633800, 16346.78437560700, 2912.80345339600, -27922.91753234200, -2404.09221927070 },
                { -126789.16986973000, 70773.21914644800, -66433.22620703800, 16346.78437560700, 200705.04715702000, -95472.47721160800, -7482.65108024430, 8352.47368955240 },
                { 70773.21914644800, -146868.68100448000, 10577.55360637600, 2912.80345339600, -95472.47721160800, 232719.03971773000, 14121.70445878300, -88763.16216664000 },
                { -49822.91670427800, 5027.15853555400, -1731.32765106900, -27922.91753234200, -7482.65108024430, 14121.70445878300, 59036.89543559100, 8774.05453800470 },
                { 10796.38930478500, 22205.01889457400, -27922.91753234200, -2404.09221927070, 8352.47368955240, -88763.16216664000, 8774.05453800470, 68962.23549133600 }
            };             // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-10));
        }
Exemple #8
0
        private static void TestStiffness3()
        {
            var factory = new ContinuumElement2DFactory(thickness, material1, dynamicMaterial);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet3);
            IMatrix            K     = quad4.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 514198.06499808, -10764.170693892, -403744.28140248, 6179.6240659003, 136202.13267487, -257206.34711690, -246655.91627047, 261790.89374489 },
                { -10764.170693892, 877762.34956189, 61124.679010955, 241708.83734231, -257206.34711690, -50430.336321830, 206845.83879984, -1069040.8505824 },
                { -403744.28140248, 61124.679010955, 2618366.6203953, -1268741.0140479, -648721.49301375, 372500.34071924, -1565900.8459791, 835115.99431770 },
                { 6179.6240659003, 241708.83734231, -1268741.0140479, 3119360.6646083, 427445.39566429, -1580482.4587671, 835115.99431770, -1780587.0431835 },
                { 136202.13267487, -257206.34711690, -648721.49301375, 427445.39566429, 691579.93709070, -83847.039187745, -179060.57675182, -86392.009359646 },
                { -257206.34711690, -50430.336321830, 372500.34071924, -1580482.4587671, -83847.039187745, 1103398.3531728, -31446.954414592, 527514.44191615 },
                { -246655.91627047, 206845.83879984, -1565900.8459791, 835115.99431770, -179060.57675182, -31446.954414592, 1991617.3390014, -1010514.8787030 },
                { 261790.89374489, -1069040.8505824, 835115.99431770, -1780587.0431835, -86392.009359646, 527514.44191615, -1010514.8787030, 2322113.4518497 }
            };             // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-10));
        }
Exemple #9
0
        private static void TestStiffness4()
        {
            var factory = new ContinuumElement2DFactory(thickness, material1, dynamicMaterial);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet3);
            IMatrix            K     = quad4.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 0.2592059570522744, -0.005023279657148771, -0.1906544880785286, -0.017628995948735127, 0.06474697564228854, -0.12002962865455298, -0.13329844461603435, 0.1426819042604369 },
                { -0.005023279657148771, 0.42886928984872097, 0.049037670717931546, 0.11055696733570626, -0.12002962865455298, -0.022348176556173396, 0.0760152375937702, -0.5170780806282538 },
                { -0.1906544880785286, 0.049037670717931546, 1.3012408988907096, -0.5920791398890163, -0.33356025755449087, 0.15332067182282197, -0.77702615325769, 0.3897207973482628 },
                { -0.017628995948735127, 0.11055696733570626, -0.5920791398890163, 1.5350381195234322, 0.21998733848948865, -0.7683820415727372, 0.3897207973482628, -0.8772130452864011 },
                { 0.06474697564228854, -0.12002962865455298, -0.33356025755449087, 0.21998733848948865, 0.3475567568780642, -0.03912861828761283, -0.07874347496586184, -0.060829091547322856 },
                { -0.12002962865455298, -0.022348176556173396, 0.15332067182282197, -0.7683820415727372, -0.03912861828761283, 0.5397386843830521, 0.005837575119343828, 0.25099153374585864 },
                { -0.13329844461603435, 0.0760152375937702, -0.77702615325769, 0.3897207973482628, -0.07874347496586184, 0.005837575119343828, 0.9890680728395862, -0.4715736100613768 },
                { 0.1426819042604369, -0.5170780806282538, 0.3897207973482628, -0.8772130452864011, -0.060829091547322856, 0.25099153374585864, -0.4715736100613768, 1.1432995921687963 }
            };             // from Solverize
                           //Assert.True(Utilities.AreMatricesEqual(K, new Matrix(expectedK), 1e-10));
        }
Exemple #10
0
        private static void TestStiffness1()
        {
            var factory = new ContinuumElement2DFactory(thickness, material1, dynamicMaterial);
            ContinuumElement2D quad4 = factory.CreateElement(CellType.Quad4, nodeSet2);
            IMatrix            K     = quad4.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 989010.98901099, 357142.85714286, -604395.60439561, -27472.527472528, -494505.49450549, -357142.85714286, 109890.10989011, 27472.527472528 },
                { 357142.85714286, 989010.98901099, 27472.527472528, 109890.10989011, -357142.85714286, -494505.49450549, -27472.527472528, -604395.60439561 },
                { -604395.60439561, 27472.527472528, 989010.98901099, -357142.85714286, 109890.10989011, -27472.527472528, -494505.49450549, 357142.85714286 },
                { -27472.527472528, 109890.10989011, -357142.85714286, 989010.98901099, 27472.527472528, -604395.60439561, 357142.85714286, -494505.49450549 },
                { -494505.49450549, -357142.85714286, 109890.10989011, 27472.527472528, 989010.98901099, 357142.85714286, -604395.60439561, -27472.527472528 },
                { -357142.85714286, -494505.49450549, -27472.527472528, -604395.60439561, 357142.85714286, 989010.98901099, 27472.527472528, 109890.10989011 },
                { 109890.10989011, -27472.527472528, -494505.49450549, 357142.85714286, -604395.60439561, 27472.527472528, 989010.98901099, -357142.85714286 },
                { 27472.527472528, -604395.60439561, 357142.85714286, -494505.49450549, -27472.527472528, 109890.10989011, -357142.85714286, 989010.98901099 }
            };             // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-10));
        }
Exemple #11
0
        private static void TestStiffness0()
        {
            var factory             = new ContinuumElement2DFactory(thickness, material0, dynamicMaterial);
            ContinuumElement2D tri6 = factory.CreateElement(CellType.Tri6, nodeSet0);
            IMatrix            K    = tri6.BuildStiffnessMatrix();

            double[,] expectedK = new double[, ]
            {
                { 51173.75966, -20778.82606, 4273.968122, 6461.400457, 3161.87986, -13008.35802, -16897.34468, -27025.3615, 9688.11919, 8859.762175, -51400.38215, 45491.38295 },
                { -20778.82606, 122356.4459, 4538.323534, 34691.5801, -11085.2811, 5376.486541, -19333.05381, -142941.0483, 8859.762175, 6529.450147, 37799.07526, -26012.91439 },
                { 4273.968122, 4538.323534, 88582.98224, 45240.07515, 32066.51649, 7151.333545, -34941.29312, -27750.00033, -109199.8665, -39522.63295, 19217.69278, 10342.90105 },
                { 6461.400457, 34691.5801, 45240.07515, 104048.7171, 5228.256622, 3589.586543, -35442.30802, -149252.8235, -31830.32526, 1377.198943, 10342.90105, 5545.740823 },
                { 3161.87986, -11085.2811, 32066.51649, 5228.256622, 112494.273, -16055.03055, 1567.844178, 1895.723659, -172177.9559, -18317.78738, 22887.44239, 38334.11875 },
                { -13008.35802, 5376.486541, 7151.333545, 3589.586543, -16055.03055, 44329.93416, 1895.723659, 5503.165063, -26010.09507, -38438.07765, 46026.42644, -20361.09466 },
                { -16897.34468, -19333.05381, -34941.29312, -35442.30802, 1567.844178, 1895.723659, 363079.0153, 24675.86222, -73599.74689, 108516.9545, -239208.4748, -80313.17851 },
                { -27025.3615, -142941.0483, -27750.00033, -149252.8235, 1895.723659, 5503.165063, 24675.86222, 449052.1476, 108516.9545, -110192.2562, -80313.17851, -52169.18472 },
                { 9688.11919, 8859.762175, -109199.8665, -31830.32526, -172177.9559, -26010.09507, -73599.74689, 108516.9545, 485631.597, 60752.92074, -140342.1468, -120289.217 },
                { 8859.762175, 6529.450147, -39522.63295, 1377.198943, -18317.78738, -38438.07765, 108516.9545, -110192.2562, 60752.92074, 406726.0715, -120289.217, -266002.3867 },
                { -51400.38215, 37799.07526, 19217.69278, 10342.90105, 22887.44239, 46026.42644, -239208.4748, -80313.17851, -140342.1468, -120289.217, 388845.8685, 106433.9928 },
                { 45491.38295, -26012.91439, 10342.90105, 5545.740823, 38334.11875, -20361.09466, -80313.17851, -52169.18472, -120289.217, -266002.3867, 106433.9928, 358999.8396 }
            }; // from Abaqus
            Assert.True(K.Equals(Matrix.CreateFromArray(expectedK), 1e-9));
        }
        /// <summary>
        /// Adds a whole mesh, which is defined by its nodes and elements, to the model.
        /// </summary>
        /// <param name="nodes">The nodes of the mesh.</param>
        /// <param name="elements">The elements of the mesh.</param>
        /// <param name="material">The common material of all elements in the mesh.</param>
        /// <param name="dynamicProperties">Optional material properties for dynamic analysis. Common for all elements in the
        ///     mesh.</param>
        public void AddMesh2D(IReadOnlyList <Node> nodes, IReadOnlyList <CellConnectivity <Node> > elements,
                              IFiniteElementMaterial material, DynamicMaterial dynamicProperties = null)
        {
            if (Dimensions == ProblemDimensions.ThreeDimensional)
            {
                throw new InvalidOperationException(
                          "This method can be used only for 2D problems (plane strain or plane stress)");
            }

            // Nodes
            int numNodesCurrent = model.NodesDictionary.Count;

            for (int i = 0; i < nodes.Count; ++i)
            {
                model.NodesDictionary.Add(numNodesCurrent + i, nodes[i]);
            }

            // Elements
            int numElementsCurrent   = model.Elements.Count;
            int numElementsSubdomain = model.Subdomains[0].Elements.Count;
            var factory = new ContinuumElement2DFactory(thickness, (ElasticMaterial2D)material, dynamicProperties); //TODO: extend the factory to other materials

            for (int i = 0; i < elements.Count; ++i)
            {
                ContinuumElement2D element = factory.CreateElement(elements[i].CellType, elements[i].Vertices);
                var elementWrapper         = new Element()
                {
                    ID = numElementsCurrent + i, ElementType = element
                };
                foreach (Node node in element.Nodes)
                {
                    elementWrapper.AddNode(node);
                }
                model.ElementsDictionary.Add(numElementsCurrent + i, elementWrapper);
                model.SubdomainsDictionary[0].Elements.Add(elementWrapper); //TODO: let the user decide which subdomain it will be added to.
            }
        }
Exemple #13
0
            public CantileverBeam BuildWithQuad4Elements(int numElementsAlongLength, int numElementsAlongHeight)
            {
                // Material and section properties
                double thickness = Width;
                var    material  = new ElasticMaterial2D(StressState2D.PlaneStress)
                {
                    YoungModulus = this.YoungModulus,
                    PoissonRatio = this.PoissonRatio
                };
                var dynamicProperties = new DynamicMaterial(1.0, 0.0, 0.0);

                // Model with 1 subdomain
                var model = new Model();

                model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID));

                // Generate mesh
                var meshGenerator = new UniformMeshGenerator2D <Node>(0.0, 0.0, Length, Height,
                                                                      numElementsAlongLength, numElementsAlongHeight);

                (IReadOnlyList <Node> vertices, IReadOnlyList <CellConnectivity <Node> > cells) =
                    meshGenerator.CreateMesh((id, x, y, z) => new Node(id: id, x: x, y:  y, z: z));

                // Add nodes to the model
                for (int n = 0; n < vertices.Count; ++n)
                {
                    model.NodesDictionary.Add(n, vertices[n]);
                }

                // Add Quad4 elements to the model
                var factory = new ContinuumElement2DFactory(thickness, material, dynamicProperties);

                for (int e = 0; e < cells.Count; ++e)
                {
                    ContinuumElement2D element = factory.CreateElement(cells[e].CellType, cells[e].Vertices);
                    var elementWrapper         = new Element()
                    {
                        ID = e, ElementType = element
                    };
                    foreach (Node node in element.Nodes)
                    {
                        elementWrapper.AddNode(node);
                    }
                    model.ElementsDictionary.Add(e, elementWrapper);
                    model.SubdomainsDictionary[subdomainID].Elements.Add(elementWrapper);
                }

                // Clamp boundary condition at one end
                double tol = 1E-10; //TODO: this should be chosen w.r.t. the element size along X

                foreach (var node in model.Nodes.Where(node => Math.Abs(node.X) <= tol))
                {
                    node.Constraints.Add(new Constraint()
                    {
                        DOF = StructuralDof.TranslationX, Amount = 0.0
                    });
                    node.Constraints.Add(new Constraint()
                    {
                        DOF = StructuralDof.TranslationY, Amount = 0.0
                    });
                }

                // Apply concentrated load at the other end
                Node[] loadedNodes = model.Nodes.Where(node => Math.Abs(node.X - Length) <= tol).ToArray();
                foreach (var node in loadedNodes)
                {
                    model.Loads.Add(new Load()
                    {
                        Amount = EndPointLoad / loadedNodes.Length, Node = node, DOF = StructuralDof.TranslationY
                    });
                }

                return(new CantileverBeam(Length, Height, Width, EndPointLoad, YoungModulus, model, loadedNodes));
            }
Exemple #14
0
        public static void TestStrainsStresses0()
        {
            var factory             = new ContinuumElement2DFactory(thickness, material0, null);
            ContinuumElement2D tri6 = factory.CreateElement(CellType.Tri6, nodeSet0);

            // Abaqus results
            double[] displacements =
            {
                0.0, 0.0,                   // Node 1
                0.0, 0.0,                   // Node 2
                -1.7903E-02, -4.2697E-02,   // Node 3
                1.5326E-03, -1.0672E-03,    // Node 4
                -8.8920E-03, -1.1654E-02,   // Node 5
                3.5728E-03, -1.2996E-02     // Node 6
            };

            double[][] expectedStrainsAtGPs =
            {
                new double[] {  3.3735E-03, 8.8893E-04, -4.6302E-03 },   // Gauss point 1
                new double[] { -4.4781E-03, 5.7927E-04,  3.6832E-04 },   // Gauss point 2
                new double[] { -1.4936E-03, 3.0967E-03, -7.1318E-03 }    // Gauss point 3
            };
            double[][] expectedStressesAtGPs =
            {
                new double[] {  840.0,  438.7, -374.00 },   // Gauss point 1
                new double[] { -993.3, -176.3,   29.75 },   // Gauss point 2
                new double[] { -130.3,  611.2, -576.00 }    // Gauss point 3
            };

            // The order of the nodes is the same (at least in this job)
            double[][] expectedStrainsAtNodes =
            {
                new double[] {  7.6130E-03,  2.5621E-04, -5.4625E-03 }, // Node 1
                new double[] { -8.0901E-03, -3.6310E-04,  4.5346E-03 }, // Node 2
                new double[] { -2.1212E-03,  4.6718E-03, -1.0466E-02 }, // Node 3
                new double[] { -2.3853E-04, -5.3446E-05, -4.6399E-04 }, // Node 4
                new double[] { -5.1056E-03,  2.1544E-03, -2.9656E-03 }, // Node 5
                new double[] {  2.7459E-03,  2.4640E-03, -7.9641E-03 }  // Node 6
            };
            double[][] expectedStressesAtNodes =
            {
                new double[] {  1775.00,  586.20, -441.20 }, // Node 1
                new double[] { -1892.00, -643.90,  366.30 }, // Node 2
                new double[] {  -166.10,  931.30, -845.30 }, // Node 3
                new double[] {   -58.74,  -28.85,  -37.48 }, // Node 4
                new double[] { -1029.00,  143.70, -239.50 }, // Node 5
                new double[] {   804.30,  758.70, -643.30 }  // Node 6
            };

            (IReadOnlyList <double[]> strainsAtGPs, IReadOnlyList <double[]> stressesAtGPs) =
                tri6.UpdateStrainsStressesAtGaussPoints(displacements);
            IReadOnlyList <double[]> strainsAtNodes =
                tri6.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, tri6.Interpolation);
            IReadOnlyList <double[]> stressesAtNodes =
                tri6.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, tri6.Interpolation);

            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtGPs, strainsAtGPs, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtGPs, stressesAtGPs, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtNodes, strainsAtNodes, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtNodes, stressesAtNodes, 1e-3));
        }
        private static Model CreateModel(IReadOnlyList <Node> nodes, IReadOnlyList <CellConnectivity <Node> > elements)
        {
            // Initialize
            int numNodes    = nodes.Count;
            int numElements = elements.Count;

            // Materials
            ElasticMaterial2D material = new ElasticMaterial2D(StressState2D.PlaneStress)
            {
                YoungModulus = youngModulus,
                PoissonRatio = poissonRatio
            };

            // Subdomains
            Model model = new Model();

            model.SubdomainsDictionary.Add(0, new Subdomain(0));

            // Nodes
            for (int i = 0; i < numNodes; ++i)
            {
                model.NodesDictionary.Add(i, nodes[i]);
            }

            // Elements
            var factory = new ContinuumElement2DFactory(thickness, material, null);

            for (int i = 0; i < numElements; ++i)
            {
                ContinuumElement2D element = factory.CreateElement(elements[i].CellType, elements[i].Vertices);
                var elementWrapper         = new Element()
                {
                    ID = i, ElementType = element
                };
                foreach (Node node in element.Nodes)
                {
                    elementWrapper.AddNode(node);
                }
                model.ElementsDictionary.Add(i, elementWrapper);
                model.SubdomainsDictionary[0].Elements.Add(elementWrapper);
            }

            // Constraints
            double tol = 1E-10;

            Node[] constrainedNodes = nodes.Where(node => Math.Abs(node.Y) <= tol).ToArray();
            for (int i = 0; i < constrainedNodes.Length; i++)
            {
                constrainedNodes[i].Constraints.Add(new Constraint {
                    DOF = StructuralDof.TranslationX
                });
                constrainedNodes[i].Constraints.Add(new Constraint {
                    DOF = StructuralDof.TranslationY
                });
            }

            // Loads
            Node[] loadedNodes = nodes.Where(
                node => (Math.Abs(node.Y - height) <= tol) && ((Math.Abs(node.X) <= tol))).ToArray();
            if (loadedNodes.Length != 1)
            {
                throw new Exception("Only 1 node was expected at the top left corner");
            }
            model.Loads.Add(new Load()
            {
                Amount = maxLoad, Node = loadedNodes[0], DOF = StructuralDof.TranslationX
            });

            return(model);
        }
Exemple #16
0
        private static void TestCantileverBeamGeneral()
        {
            // Define the materials
            double thickness = 1.0;
            var    material  = new ElasticMaterial2D(StressState2D.PlaneStress)
            {
                YoungModulus = youngModulus, PoissonRatio = 0.3
            };
            var dynamicProperties = new DynamicMaterial(1.0, 0.0, 0.0, true);

            // Model with 1 subdomain
            var model = new Model();

            model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID));

            // Generate mesh
            int    numElementsX = 32, numElementsY = 20;
            double lengthX = numElementsX;
            double depthY  = numElementsY;
            var    mesher  = new UniformMeshGenerator2D <Node>(0, 0, lengthX, depthY, numElementsX, numElementsY);

            (IReadOnlyList <Node> nodes, IReadOnlyList <CellConnectivity <Node> > connectivity) =
                mesher.CreateMesh((id, x, y, z) => new Node(id: id, x: x, y:  y, z: z));

            // Add nodes to the model
            for (int n = 0; n < nodes.Count; ++n)
            {
                model.NodesDictionary.Add(n, nodes[n]);
            }

            // Add Quad4 elements to the model
            var factory = new ContinuumElement2DFactory(thickness, material, dynamicProperties);

            for (int e = 0; e < connectivity.Count; ++e)
            {
                ContinuumElement2D element = factory.CreateElement(connectivity[e].CellType, connectivity[e].Vertices);
                var elementWrapper         = new Element()
                {
                    ID = e, ElementType = element
                };
                foreach (Node node in element.Nodes)
                {
                    elementWrapper.AddNode(node);
                }
                model.ElementsDictionary.Add(e, elementWrapper);
                model.SubdomainsDictionary[subdomainID].Elements.Add(elementWrapper);
            }

            // Clamp boundary condition at left edge
            double tol = 1E-10; //TODO: this should be chosen w.r.t. the element size along X

            foreach (var node in model.Nodes.Where(node => Math.Abs(node.X) <= tol))
            {
                node.Constraints.Add(new Constraint()
                {
                    DOF = StructuralDof.TranslationX, Amount = 0.0
                });
                node.Constraints.Add(new Constraint()
                {
                    DOF = StructuralDof.TranslationY, Amount = 0.0
                });
            }

            // Apply concentrated load at the bottom right corner
            double load       = 1.0;
            var    cornerNode = model.Nodes.Where(
                node => (Math.Abs(node.X - lengthX) <= tol) && (Math.Abs(node.Y - depthY) <= tol));

            Assert.True(cornerNode.Count() == 1);
            model.Loads.Add(new Load()
            {
                Amount = load, Node = cornerNode.First(), DOF = StructuralDof.TranslationY
            });

            // Define the solver
            SkylineSolver solver = (new SkylineSolver.Builder()).BuildSolver(model);

            // Define the fem analysis and the filter
            double filterAreaRadius = 1.2;
            var    fem    = new LinearFemAnalysis2DGeneral(model, solver);
            var    filter = new ProximityDensityFilter2D(model, filterAreaRadius);

            // Run the test
            TestCantileverBeam(fem, filter);
        }
        public static void WriteStiffnessOfContinuum2DStructure()
        {
            //   ____ ____
            //  |    |    |
            //  |____|____|
            //  |    |    |
            //  |____|____|

            // Model with 1 subdomain
            var model = new Model();

            model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID));

            // Material
            double thickness = 1.0;
            var    material  = new ElasticMaterial2D(StressState2D.PlaneStress)
            {
                YoungModulus = 2.1E7,
                PoissonRatio = 0.3
            };
            var dynamicProperties = new DynamicMaterial(1.0, 0.0, 0.0, true);

            // Generate mesh
            double domainLength  = 2.0;
            double domainHeight  = 2.4;
            var    meshGenerator = new UniformMeshGenerator2D <Node>(0.0, 0.0, domainLength, domainHeight, 10, 10);

            (IReadOnlyList <Node> vertices, IReadOnlyList <CellConnectivity <Node> > cells) =
                meshGenerator.CreateMesh((id, x, y, z) => new Node(id: id, x: x, y:  y, z: z));

            // Add nodes to the model
            for (int n = 0; n < vertices.Count; ++n)
            {
                model.NodesDictionary.Add(n, vertices[n]);
            }

            // Add Quad4 elements to the model
            var factory = new ContinuumElement2DFactory(thickness, material, dynamicProperties);

            for (int e = 0; e < cells.Count; ++e)
            {
                ContinuumElement2D element = factory.CreateElement(cells[e].CellType, cells[e].Vertices);
                var elementWrapper         = new Element()
                {
                    ID = e, ElementType = element
                };
                foreach (Node node in element.Nodes)
                {
                    elementWrapper.AddNode(node);
                }
                model.ElementsDictionary.Add(e, elementWrapper);
                model.SubdomainsDictionary[subdomainID].Elements.Add(elementWrapper);
            }

            // Solver
            var           solverBuilder = new SkylineSolver.Builder();
            SkylineSolver solver        = solverBuilder.BuildSolver(model);

            // Structural problem provider
            var provider = new ProblemStructural(model, solver);

            // Linear static analysis
            var childAnalyzer  = new LinearAnalyzer(model, solver, provider);
            var parentAnalyzer = new StaticAnalyzer(model, solver, provider, childAnalyzer);

            // Run the analysis to build the stiffness matrix
            parentAnalyzer.Initialize();
            parentAnalyzer.BuildMatrices();

            // Print the stiffness matrix
            //var writer = new MatlabWriter();
            var writer = new RawArraysWriter();

            writer.WriteToMultipleFiles((SkylineMatrix)solver.LinearSystems[subdomainID].Matrix,
                                        outputDirectory + @"\quad4_20x20_stiffness.txt");
        }
Exemple #18
0
        public static void TestStrainsStresses0()
        {
            var factory = new ContinuumElement2DFactory(thickness, material0, null);
            ContinuumElement2D quad8 = factory.CreateElement(CellType.Quad8, nodeSet0);

            // Abaqus results
            double[] displacements =
            {
                0.0, 0.0,                   // Node 1
                0.0, 0.0,                   // Node 2
                -6.1872E-03, -1.3677E-02,   // Node 3
                2.1193E-02, -6.0952E-02,    // Node 4
                -6.4016E-03, -2.9598E-03,   // Node 5
                -9.8052E-03, -7.6739E-03,   // Node 6
                2.0961E-03, -2.4904E-02,    // Node 7
                1.2842E-02, -2.0029E-02     // Node 8
            };

            double[][] expectedStrainsAtGPs =
            {
                new double[] {  5.0483E-03,  9.3636E-04,  1.3684E-03 },  // Gauss point 1
                new double[] {  4.4925E-04,  6.0911E-04, -1.1381E-03 },  // Gauss point 2
                new double[] { -1.0021E-02,  3.7130E-04, -6.7670E-03 },  // Gauss point 3
                new double[] {  3.0367E-03, -4.2664E-03, -6.6618E-03 },  // Gauss point 4
                new double[] {  7.6921E-04, -2.1368E-03, -5.1775E-03 },  // Gauss point 5
                new double[] { -2.5482E-03,  1.8783E-03, -6.8114E-03 },  // Gauss point 6
                new double[] {  1.2133E-03, -2.1843E-05, -1.4123E-02 },  // Gauss point 7
                new double[] { -4.6295E-03, -1.0028E-02, -4.5072E-03 },  // Gauss point 8
                new double[] {  4.6685E-03, -2.5173E-03, -3.6237E-03 }   // Gauss point 9
            };
            double[][] expectedStressesAtGPs =
            {
                new double[] {  1230.00,   565.60,   110.50 },  // Gauss point 1
                new double[] {   145.80,   171.70,   -91.92 },  // Gauss point 2
                new double[] { -2287.00,  -608.10,  -546.60 },  // Gauss point 3
                new double[] {   405.40,  -774.30,  -538.10 },  // Gauss point 4
                new double[] {    29.58,  -439.80,  -418.20 },  // Gauss point 5
                new double[] {  -458.00,   257.00,  -550.20 },  // Gauss point 6
                new double[] {   278.50,    78.95, -1141.00 },  // Gauss point 7
                new double[] { -1763.00, -2635.00,  -364.00 },  // Gauss point 8
                new double[] {   903.10,  -257.70,  -292.70 }   // Gauss point 9
            };

            // The order of the nodes is the same (at least in this job)
            double[][] expectedStrainsAtNodes =
            {
                new double[] {  6.5625E-03,  5.7325E-03,  3.8681E-03 },  // Node 1
                new double[] { -1.6562E-02, -1.2399E-03, -8.9890E-03 },  // Node 2
                new double[] {  1.4923E-02,  2.1676E-03, -3.8448E-03 },  // Node 3
                new double[] {  7.1739E-03,  1.2357E-02, -2.2045E-02 },  // Node 4
                new double[] { -7.1803E-04,  4.4174E-04,  9.2207E-04 },  // Node 5
                new double[] { -3.7108E-03,  3.4008E-03, -7.8726E-03 },  // Node 6
                new double[] { -7.2747E-03, -1.3290E-02, -3.4274E-03 },  // Node 7
                new double[] {  3.4993E-03, -4.5319E-03, -7.6795E-03 }  // Node 8
            };
            double[][] expectedStressesAtNodes =
            {
                new double[] {  1911.0,  1777.00,   312.40 },  // Node 1
                new double[] { -3908.0, -1433.00,  -726.00 },  // Node 2
                new double[] {  3594.0,  1533.00,  -310.50 },  // Node 3
                new double[] {  2511.0,  3348.00, -1781.00 },  // Node 4
                new double[] {  -135.1,    52.23,    74.47 },  // Node 5
                new double[] {  -620.9,   527.90,  -635.90 },  // Node 6
                new double[] { -2599.0, -3571.00,  -276.80 },  // Node 7
                new double[] {   493.8,  -803.60,  -620.30 }   // Node 8
            };

            (IReadOnlyList <double[]> strainsAtGPs, IReadOnlyList <double[]> stressesAtGPs) =
                quad8.UpdateStrainsStressesAtGaussPoints(displacements);
            IReadOnlyList <double[]> strainsAtNodes =
                quad8.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(strainsAtGPs, quad8.Interpolation);
            IReadOnlyList <double[]> stressesAtNodes =
                quad8.GaussPointExtrapolation.ExtrapolateTensorFromGaussPointsToNodes(stressesAtGPs, quad8.Interpolation);

            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtGPs, strainsAtGPs, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtGPs, stressesAtGPs, 0.5e-2));
            Assert.True(Utilities.AreTensorsEqual(expectedStrainsAtNodes, strainsAtNodes, 1e-3));
            Assert.True(Utilities.AreTensorsEqual(expectedStressesAtNodes, stressesAtNodes, 0.5e-2));
        }
        private static void TestQuad4LinearCantileverExample()
        {
            // Model & subdomains
            var model       = new Model();
            int subdomainID = 0;

            model.SubdomainsDictionary.Add(subdomainID, new Subdomain(subdomainID));

            // Materials
            double youngModulus = 3.76;
            double poissonRatio = 0.3779;
            double thickness    = 1.0;
            double nodalLoad    = 500.0;
            var    material     = new ElasticMaterial2D(StressState2D.PlaneStress)
            {
                YoungModulus = youngModulus,
                PoissonRatio = poissonRatio
            };

            // Nodes
            var nodes = new Node[]
            {
                new Node(id: 1, x:  0.0, y:   0.0, z: 0.0),
                new Node(id: 2, x: 10.0, y:   0.0, z: 0.0),
                new Node(id: 3, x: 10.0, y:  10.0, z: 0.0),
                new Node(id: 4, x:  0.0, y:  10.0, z: 0.0)
            };

            for (int i = 0; i < nodes.Length; ++i)
            {
                model.NodesDictionary.Add(i, nodes[i]);
            }


            // Elements
            var factory = new ContinuumElement2DFactory(thickness, material, null);

            var elementWrapper = new Element()
            {
                ID          = 0,
                ElementType = factory.CreateElement(CellType.Quad4, nodes)
            };

            elementWrapper.AddNodes(nodes);
            model.ElementsDictionary.Add(elementWrapper.ID, elementWrapper);
            model.SubdomainsDictionary[subdomainID].Elements.Add(elementWrapper);

            //var a = quad.StiffnessMatrix(element);

            // Prescribed displacements
            model.NodesDictionary[0].Constraints.Add(new Constraint()
            {
                DOF = StructuralDof.TranslationX, Amount = 0.0
            });
            model.NodesDictionary[0].Constraints.Add(new Constraint()
            {
                DOF = StructuralDof.TranslationY, Amount = 0.0
            });
            model.NodesDictionary[3].Constraints.Add(new Constraint()
            {
                DOF = StructuralDof.TranslationX, Amount = 0.0
            });
            model.NodesDictionary[3].Constraints.Add(new Constraint()
            {
                DOF = StructuralDof.TranslationY, Amount = 0.0
            });

            // Nodal loads
            model.Loads.Add(new Load()
            {
                Amount = nodalLoad, Node = model.NodesDictionary[1], DOF = StructuralDof.TranslationX
            });
            model.Loads.Add(new Load()
            {
                Amount = nodalLoad, Node = model.NodesDictionary[2], DOF = StructuralDof.TranslationX
            });

            // Solver
            var pcgBuilder = new PcgAlgorithm.Builder();

            pcgBuilder.ResidualTolerance     = 1E-6;
            pcgBuilder.MaxIterationsProvider = new PercentageMaxIterationsProvider(0.5);
            var solverBuilder = new PcgSolver.Builder();

            solverBuilder.PcgAlgorithm = pcgBuilder.Build();
            PcgSolver solver = solverBuilder.BuildSolver(model);

            // Problem type
            var provider = new ProblemStructural(model, solver);

            // Analyzers
            var childAnalyzer  = new LinearAnalyzer(model, solver, provider);
            var parentAnalyzer = new StaticAnalyzer(model, solver, provider, childAnalyzer);

            //NewmarkDynamicAnalyzer parentAnalyzer = new NewmarkDynamicAnalyzer(provider, childAnalyzer, linearSystems, 0.25, 0.5, 0.28, 3.36);

            // Request output
            childAnalyzer.LogFactories[subdomainID] = new LinearAnalyzerLogFactory(new int[] { 0 });

            // Run the anlaysis
            parentAnalyzer.Initialize();
            parentAnalyzer.Solve();

            // Check output
            DOFSLog log = (DOFSLog)childAnalyzer.Logs[subdomainID][0]; //There is a list of logs for each subdomain and we want the first one

            Assert.Equal(253.132375961535, log.DOFValues[0], 8);
        }