// See slides p.44 public void GetLocalNodeCoordinates(out Matrix xel, out Matrix Tg) { Vector3D v1 = Nodes[1].Pos - Nodes[0].Pos; Vector3D _v2 = Nodes[2].Pos - Nodes[0].Pos; Vector3D v3 = Vector3D.CrossProduct(v1, _v2); Vector3D v2 = Vector3D.CrossProduct(v3, v1); if (v1.IsZeroVector() || v2.IsZeroVector() || v3.IsZeroVector()) { throw new Exception("Bad element, ID: " + this.Id.ToString()); } Vector3D e1 = v1.Normalize(false); Vector3D e2 = v2.Normalize(false); Vector3D e3 = v3.Normalize(false); Matrix xeg = new Matrix(3, 3); xeg.SetRow(v1.ToMatrix().Transpose(), 1); xeg.SetRow(_v2.ToMatrix().Transpose(), 2); Matrix T = new Matrix(3, 3); T.SetCol(e1.ToMatrix(), 0); T.SetCol(e2.ToMatrix(), 1); T.SetCol(e3.ToMatrix(), 2); xel = xeg * T; Tg = new Matrix(18, 18); int[] pos1 = SF.intSrs(0, 2); int[] pos2 = SF.intSrs(3, 5); int[] pos3 = SF.intSrs(6, 8); int[] pos4 = SF.intSrs(9, 11); int[] pos5 = SF.intSrs(12, 14); int[] pos6 = SF.intSrs(15, 17); Tg[pos1, pos1] = T; Tg[pos2, pos2] = T; Tg[pos3, pos3] = T; Tg[pos4, pos4] = T; Tg[pos5, pos5] = T; Tg[pos6, pos6] = T; }
//Only verified to MATLAB-cod with configurations: 4 laminas (all 0 degrees), 4 laminas (45,30,30,45) degrees public static void eqModulus(ShellElement shell, out Matrix D, out List <Matrix> Qtot, out List <double> zValues) { //Just used for the shorter name List <double> E1s = shell.Section.Exs; List <double> E2s = shell.Section.Eys; List <double> angles = shell.Section.angles; List <double> thickness = shell.Section.thickness; List <double> v12s = shell.Section.vs; List <double> Gxys = shell.Section.Gxys; List <double> densitys = shell.Section.densitys; double totThick = shell.Section.totalThickness; //Used for gravity load //double gravity = 9.81; //Global stiffness matrices for the laminate Matrix AA = new Matrix(3, 3); //Extensional or membrane stiffness terms of a laminate Matrix BB = new Matrix(3, 3); //Coupling stiffness terms of a laminate Matrix DD = new Matrix(3, 3); //Bending stiffness n therms of a laminate //Testing stresses Qtot = new List <Matrix>(); zValues = new List <double>(); //Global bodyforces matrices for the laminate (not used now) double II0 = 0; //double II1 = 0; //double II2 = 0; //Get the maximum of the different inputs int[] lengths = { E1s.Count, E2s.Count, angles.Count, thickness.Count, v12s.Count }; int listLength = lengths.Max(); //Check if number of inputs is one or the same as the maximum And make the lists same length E1s = SF.checkPlyListLength(E1s, listLength); E2s = SF.checkPlyListLength(E2s, listLength); angles = SF.checkPlyListLength(angles, listLength); thickness = SF.checkPlyListLength(thickness, listLength); v12s = SF.checkPlyListLength(v12s, listLength); Gxys = SF.checkPlyListLength(Gxys, listLength); //if odd numbers of numbers double iterations = Math.Ceiling(listLength / 2.0); iterations = listLength; //For the moment only half of the layers are iterated thorough (and then doubled), it is necessary that the //layers are symmetrical. A check is done for this in Section GH-component. Should be changed later for (int i = 0; i < iterations; i++) { double v21 = v12s[i] * E2s[i] / E1s[i]; // Stiffness and strength analysis (Bokmärke) 4.2 //Reduced stiffness terms (EUROCOMP eq4.50) double Q11 = E1s[i] / (1 - v12s[i] * v21); double Q12 = v21 * E1s[i] / (1 - v12s[i] * v21); //= Q21 double Q22 = E2s[i] / (1 - v12s[i] * v21); double Q66 = Gxys[i]; //Take local coordinate system into account double angle = angles[i] + shell.MaterialOrientationAngle; //angle in degree double m = Math.Cos(angle * 2 * Math.PI / 360); //Math.Cos uses radians double n = Math.Sin(angle * 2 * Math.PI / 360); //Math.Cos uses radians //EUROCOMP, fast första är fel där (m^4) (Step 2) double Q_11 = Q11 * Math.Pow(m, 4) + Q22 * Math.Pow(n, 4) + Q12 * 2 * Math.Pow(m, 2) * Math.Pow(n, 2) + Q66 * 4 * Math.Pow(m, 2) * Math.Pow(n, 2); double Q_22 = Q11 * Math.Pow(n, 4) + Q22 * Math.Pow(m, 4) + Q12 * 2 * Math.Pow(m, 2) * Math.Pow(n, 2) + Q66 * 4 * Math.Pow(m, 2) * Math.Pow(n, 2); double Q_66 = (Q11 + Q22 - 2 * Q12) * Math.Pow(m, 2) * Math.Pow(n, 2) + Q66 * Math.Pow(Math.Pow(m, 2) - Math.Pow(n, 2), 2); double Q_12 = (Q11 + Q22 - 4 * Q66) * Math.Pow(n, 2) * Math.Pow(m, 2) + Q12 * (Math.Pow(n, 4) + Math.Pow(m, 4)); double Q_16 = Q11 * Math.Pow(m, 3) * n - Q22 * Math.Pow(n, 3) * m + Q12 * (Math.Pow(n, 3) * m - Math.Pow(m, 3) * n) + Q66 * 2 * (Math.Pow(n, 3) * m - Math.Pow(m, 3) * n); double Q_26 = Q11 * Math.Pow(n, 3) * m - Q22 * Math.Pow(m, 3) * n + Q12 * (Math.Pow(m, 3) * n - Math.Pow(n, 3) * m) + Q66 * 2 * (Math.Pow(m, 3) * n - Math.Pow(n, 3) * m); Matrix Q_ = new Matrix(new double[, ] { { Q_11, Q_12, Q_16 }, { Q_12, Q_22, Q_26 }, { Q_16, Q_26, Q_66 } }); //Determine distances from the mid-plane //Good picture in laminatedComposite PDF double hkNew = totThick / 2.0; double hkMinus1New = totThick / 2.0 - thickness[i]; for (int j = 0; j < i; j++) { hkNew -= thickness[j]; hkMinus1New -= thickness[j]; } //Ändra till += AA = AA + (hkNew - hkMinus1New) * Q_; BB = BB + (Math.Pow(hkNew, 2) - Math.Pow(hkMinus1New, 2)) * Q_; DD = DD + (Math.Pow(hkNew, 3) - Math.Pow(hkMinus1New, 3)) * Q_; //Same but for the masses II0 = II0 + thickness[i]; //For stresses Matrix Qlarge = new Matrix(6, 6); Qlarge[new int[] { 0, 1, 2 }, new int[] { 0, 1, 2 }] = Q_; Qtot.Add(Qlarge); zValues.Add(hkNew - thickness[i] / 2); } BB = (1.0 / 2.0) * BB; DD = (1.0 / 3.0) * DD; // II2 = (1.0 / 3.0) * II2; // II0 = II0 * density * gravity; //Step 5 i euroCOMP // Matrix a = AA.Invert(); //TEMPORARY. THEY GET SINGULAR // Matrix b = B.Invert(); // Matrix d = DD.Invert(); //Step 6 euroCOMP /* double totalThick = listLength * thickLam; * double Ex = 1 / (totalThick * a[0, 0]); * double Ey = 1 / (totalThick * a[1, 1]); * double Gxy = 1 / (totalThick * a[2, 2]); * double vxy = -a[0, 1] / a[0, 0]; * double vyx = -a[0, 1] / a[1, 1]; */ //d and b matrices can be used for the equivalent bending elastic constants (step 6 euroCOMP) //Total D-matrix D=[AA -BB;-BB DD] D = new Matrix(6, 6); D[new int[] { 0, 1, 2 }, new int[] { 0, 1, 2 }] = AA; D[new int[] { 3, 4, 5 }, new int[] { 3, 4, 5 }] = DD; D[new int[] { 0, 1, 2 }, new int[] { 3, 4, 5 }] = -BB; D[new int[] { 3, 4, 5 }, new int[] { 0, 1, 2 }] = -BB; //Total Gravity load matrix //q = new Matrix(new double[,] { { 0 } , { 0 }, { -II0 } }); //Gravity works in negative direction }
//Calculate principal tresses for all the elements public void CalcStresses() { //Folllowing plants in MATlab, each element 15 dofs //the 15 active dofs used in each element (with 18 dofs in total) int[] activeDofs = new int[] { 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16 }; PrincipalStresses = new List <Vector3D>(); stresses = new List <Matrix>(); PrincipalAngles = new List <double>(); vonMises = new List <double>(); for (int i = 0; i < elements.Count; i++) { //Get all the 18 element dofs from the global int[] dofsFull = elements[i].GetElementDofs(); //Take the deformations from the element dofs Matrix aTrans = new Matrix(18, 1); for (int j = 0; j < dofsFull.Count(); j++) { aTrans[j] = a[dofsFull[j]]; } //Transform the local coordinates to global aTrans = elements[i].Te.Invert() * aTrans; //Take the 15 active dofs that should be used from the transformed defrormations Matrix ed = new Matrix(1, 15); for (int j = 0; j < activeDofs.Count(); j++) { ed[0, j] = aTrans[activeDofs[j]]; } //Stresses (D*B*a) // Matrix ss = elements[i].DBe * ed[0, SF.intSrs(0, 14)].Transpose(); // stresses.Add(ss); double theta = 0; Vector3D vMax = new Vector3D(); //for every layer for (int j = 0; j < elements[i].DBe.Count; j++) { Matrix ss = new Matrix(6, 1); ed[3] *= elements[i].zs[j]; ed[4] *= elements[i].zs[j]; ed[8] *= elements[i].zs[j]; ed[9] *= elements[i].zs[j]; ed[13] *= elements[i].zs[j]; ed[14] *= elements[i].zs[j]; ss = elements[i].DBe[j] * ed[0, SF.intSrs(0, 14)].Transpose(); //Make sure there is no errors when this is changed // theta = 0.5 * Math.Atan(2 * ss[2] / (ss[0] - ss[1])); // if (ss[0] < ss[1]) theta = theta + Math.PI / 2; //PrincipalAngles.Add(theta); //Principle stresses double p1 = (ss[0] + ss[1]) / 2.0 + Math.Sqrt(Math.Pow((ss[0] - ss[1]) / 2, 2) + Math.Pow(ss[2], 2)); double p2 = (ss[0] + ss[1]) / 2.0 - Math.Sqrt(Math.Pow((ss[0] - ss[1]) / 2, 2) + Math.Pow(ss[2], 2)); Vector3D v = new Vector3D(p1, p2, 0); if (v.Length > vMax.Length) { vMax = v; theta = 0.5 * Math.Atan(2 * ss[2] / (ss[0] - ss[1])); if (ss[0] < ss[1]) { theta = theta + Math.PI / 2; } } } // PrincipalStresses.Add(new Vector3D(p1, p2, 0)); PrincipalStresses.Add(vMax); // vonMises.Add(Math.Sqrt(p1 * p1 - p1 * p2 + p2 * p2)); vonMises.Add(Math.Sqrt(vMax.X * vMax.X - vMax.X * vMax.Y + vMax.Y * vMax.Y)); PrincipalAngles.Add(theta); } }