/// <summary> /// Developed by: Mehrdad Negahban /// Date: 12/25/2012 /// /// Purpose: Root class for static sparse N-D solvers (KU=F) /// Comments: /// /// Date modified: /// Modified by: /// Comments: /// </summary> public override void SolveFEMSystem() { //Set up the load vector and stiffness matrix int NDF = Unknowns_NDoF; //Get the size of the unknowns temperature (one per node) Vector F = new Vector(NDF); //Make global load vector MatrixSparseLinkedList K = new MatrixSparseLinkedList(NDF); // Make global stiffness matrix Timer_Assemble = new StopWatchTimer(); Timer_Assemble.StartTimer(); //Assemble F and K int NE = Elements.Length; //Get the number of elements for (int i = 0; i < NE; i++) { Elements[i].CalculateAndAssemble_FeAndKe(ref F, ref K); } //Adjust for boundary conditions int NBE = BoundaryElements.Length; for (int i = 0; i < NBE; i++) { BoundaryElements[i].AdjustFAndK(ref F, ref K); } Timer_Assemble.StopTimer(); Timer_Solve = new StopWatchTimer(); Timer_Solve.StartTimer(); //Solve system U = K.SolveLinearSystem(F); Timer_Solve.StopTimer(); }
public override void Assemble(ref MatrixSparseLinkedList K, Matrix_Jagged Ke) { int Ip, Iq; int NNPE = ElementNodes.Length; for (int p = 0; p < NNPE; p++) { Node_ND_Unknowns_VectorField Unknown_p = (Node_ND_Unknowns_VectorField)ElementNodes[p].Unknowns; int NDFp = Unknown_p.UnknownDoFs.Length; for (int i = 0; i < NDFp; i++) { Ip = Unknown_p.UnknownDoFs[i]; for (int q = 0; q < NNPE; q++) { Node_ND_Unknowns_VectorField Unknown_q = (Node_ND_Unknowns_VectorField)ElementNodes[q].Unknowns; int NDFq = Unknown_q.UnknownDoFs.Length; for (int j = 0; j < NDFq; j++) { Iq = Unknown_q.UnknownDoFs[j]; K.AddToMatrixElement(Ip, Iq, Ke.Values[NNPE * p + i][NNPE * q + j]); } } } } }
public override void Assemble(ref MatrixSparseLinkedList K, Matrix_Jagged Ke) { int Ip, Iq; int NNPE = ElementNodes.Length; for (int p = 0; p < NNPE; p++) { Node_ND_Unknowns_ScalarField TheUnknowns_p = (Node_ND_Unknowns_ScalarField)ElementNodes[p].Unknowns; Ip = TheUnknowns_p.UnknownDoF; for (int q = 0; q < NNPE; q++) { Node_ND_Unknowns_ScalarField TheUnknowns_q = (Node_ND_Unknowns_ScalarField)ElementNodes[q].Unknowns; Iq = TheUnknowns_q.UnknownDoF; K.AddToMatrixElement(Ip, Iq, Ke.Values[p][q]); } } }
public override void SolveFEMSystem_Parallel() { //Set up the load vector and stiffness matrix int NDF = Unknowns_NDoF; //Get the size of the unknowns temperature (one per node) Vector F = new Vector(NDF); //Make global load vector MatrixSparseLinkedList K = new MatrixSparseLinkedList(NDF); // Make global stiffness matrix //Assemble F and K int NE = Elements.Length; //Get the number of elements ParallelOptions op = new ParallelOptions(); op.MaxDegreeOfParallelism = Environment.ProcessorCount; Timer_Assemble = new StopWatchTimer(); Timer_Assemble.StartTimer(); Parallel.For(0, NE, op, i => { Vector Fe = Elements[i].Calculate_Fe(); Matrix_Jagged Ke = Elements[i].Calculate_Ke(); lock (K_Lock) { Elements[i].Assemble(ref K, Ke); } lock (F_Lock) { Elements[i].Assemble(ref F, Fe); } }); //Adjust for boundary conditions int NBE = BoundaryElements.Length; for (int i = 0; i < NBE; i++) { BoundaryElements[i].AdjustFAndK(ref F, ref K); } Timer_Assemble.StopTimer(); Timer_Solve = new StopWatchTimer(); Timer_Solve.StartTimer(); //Solve system U = new Vector(); U.Values = K.SolveLinearSystem_Parallel(F.Values); Timer_Solve.StopTimer(); }
public override void Assemble(ref MatrixSparseLinkedList K, Matrix_Jagged Ke) { int Ip, Iq, I1p, I1pi, I1, I2q, I2qk, I2; int NNPE = ElementNodes.Length; int NumberOFPhysics, TotalDoFPerNode; int[] DofPerPhysics; int[] StartIndexPerPhysics = Get_StartIndexForEachPhysics(out NumberOFPhysics, out TotalDoFPerNode, out DofPerPhysics); for (int p = 0; p < NNPE; p++) { Node_ND_Unknowns_MultiPhysics Unknowns_p = (Node_ND_Unknowns_MultiPhysics)ElementNodes[p].Unknowns; I1p = TotalDoFPerNode * p; for (int i = 0; i < NumberOFPhysics; i++) { I1pi = I1p + StartIndexPerPhysics[i]; for (int j = 0; j < DofPerPhysics[i]; j++) { I1 = I1pi + j; Ip = Unknowns_p.UnknownDoFs[PhysicsUsed[i]][j]; for (int q = 0; q < NNPE; q++) { Node_ND_Unknowns_MultiPhysics Unknowns_q = (Node_ND_Unknowns_MultiPhysics)ElementNodes[q].Unknowns; I2q = TotalDoFPerNode * q; for (int k = 0; k < NumberOFPhysics; k++) { I2qk = I2q + StartIndexPerPhysics[k]; for (int l = 0; l < DofPerPhysics[k]; l++) { I2 = I2qk + l; Iq = Unknowns_q.UnknownDoFs[PhysicsUsed[k]][l]; K.AddToMatrixElement(Ip, Iq, Ke.Values[I1][I2]); } } } } } } }
/// <summary> /// Developed by: Mehrdad Negahban /// Date: 12/26/2012 /// /// Purpose: CrankNicholson solver using sparse matrix for first order transient problem (C dU/dt + K U = F) /// Comments: /// /// Date modified: /// Modified by: /// Comments: /// </summary> public override void SolveFEMSystem() { //Set up the load vector and stiffness matrix int NDF = Unknowns_NDoF; //Get the size of the unknowns temperature (one per node) Vector F_old = new Vector(NDF); //Make global load vector (old) Vector F_new = new Vector(NDF); //Make global load vector (new) MatrixSparseLinkedList K = new MatrixSparseLinkedList(NDF); // Make global stiffness matrix MatrixSparseLinkedList C = new MatrixSparseLinkedList(NDF); // Make global thermal mass matrix //Assemble F, K, C int NE = Elements.Length; //Get the number of elements for (int i = 0; i < NE; i++) { Elements[i].CalculateAndAssemble_FeAndKeAndCe(ref F_old, ref K, ref C); } //Adjust for boundary conditions int NBE = BoundaryElements.Length; for (int i = 0; i < NBE; i++) { BoundaryElements[i].AdjustK(Times.Values[StartIndex], ref K); } K = 0.5 * K; C = C / DTime; MatrixSparseLinkedList C1 = C - K; C = C + K; // Calculate Chat and store in C //Adjust C for boundary condition for (int i = 0; i < NBE; i++) { BoundaryElements[i].AdjustChat(Times.Values[StartIndex], ref C); } C.LUDecomposition_Parallel();//Run LU decomposition on C //Adjust F for BC for (int i = 0; i < NBE; i++) { BoundaryElements[i].AdjustF(Times.Values[StartIndex], ref F_old); } F_old = 0.5D * F_old; //Store initial time and temperature Vector U_old = new Vector(Ut[StartIndex]); Node_ND.Set_UnknownForNode(Nodes, U_old); StoreSensors(StartIndex); Vector Fhat; double RTime = Times.Values[StartIndex]; for (int i = StartIndex; i < NumberOfStepsToStore; i++) { for (int j = 0; j < NumberOfStepsToSkipOutput; j++) { RTime += DTime; //Increment to new time Element_ND.Time = RTime; //Give new time to all elements F_new = new Vector(NDF); for (int k = 0; k < NE; k++) { Elements[k].CalculateAndAssemble_Fe(ref F_new); //Calculate new F } //Adjust new F for BC for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustF(RTime, ref F_new); } F_new = 0.5 * F_new; Fhat = F_old + F_new + C1 * U_old; //Get Fhat //Adust Fhat for BC for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustFhat(RTime, ref F_new); } U_old.Values = C.SolveLinearSystemForwardEliminationAndBackSubstitution(Fhat.Values); //Solve for new temperatures F_old = F_new; //Move new F to old F for next step } Times.Values[i + 1] = RTime; //Store time Ut[i + 1] = new Vector(U_old); //Store vector of node temperatures Solver_Output_Info.StoreAStep(i + 1, Times.Values[i + 1], Ut[i + 1], DTime, NumberOfStepsToSkipOutput); Solver_Output_Info.SaveToFile(Solver_Output_Info.Make_OuptutAddress()); Node_ND.Set_UnknownForNode(Nodes, U_old); StoreSensors(i + 1); } }
public virtual void AdjustM(double Time, ref MatrixSparseLinkedList M) { }
public virtual void AdjustFAndK(ref Vector F, ref MatrixSparseLinkedList K) { }
public void CalculateAndAssemble_FeAndKe(ref Vector F, ref MatrixSparseLinkedList K) { CalculateAndAssemble_Fe(ref F); CalculateAndAssemble_Ke(ref K); }
public void CalculateAndAssemble_FeAndKeAndCeAndMe(ref Vector F, ref MatrixSparseLinkedList K, ref MatrixSparseLinkedList C, ref MatrixSparseLinkedList M) { CalculateAndAssemble_FeAndKeAndCe(ref F, ref K, ref C); CalculateAndAssemble_Me(ref M); }
public virtual void Assemble(ref MatrixSparseLinkedList K, Matrix_Jagged Ke) { //Need to implement }
public void CalculateAndAssemble_Me(ref MatrixSparseLinkedList M) { Matrix_Jagged Me = Calculate_Me(); Assemble(ref M, Me); }
public void CalculateAndAssemble_Ce(ref MatrixSparseLinkedList C) { Matrix_Jagged Ce = Calculate_Ce(); Assemble(ref C, Ce); }
public void CalculateAndAssemble_Ke(ref MatrixSparseLinkedList K) { Matrix_Jagged Ke = Calculate_Ke(); Assemble(ref K, Ke); }
/// <summary> /// Developed by: Mehrdad Negahban /// Date: 12/27/2012 /// /// Purpose: Newmark method to solve second order transient N-D problem using sparse matrix model (M d^2U/dt^2 + K U = F) /// Comments: May add artificial damping (+ C dU/dt) /// /// Date modified: /// Modified by: /// Comments: /// </summary> public override void SolveFEMSystem() { double beta = Newmark_beta; double gamma = Newmark_gamma; //Set up the load vector and stiffness matrix int NDF = Unknowns_NDoF; //Get the size of the unknowns temperature (one per node) Vector F = new Vector(NDF); //Make global load vector (old) Vector F_new = new Vector(NDF); //Make global load vector (new) MatrixSparseLinkedList K = new MatrixSparseLinkedList(NDF); // Make global stiffness matrix MatrixSparseLinkedList M = new MatrixSparseLinkedList(NDF); // Make global thermal mass matrix //Assemble F, K, C int NE = Elements.Length; //Get the number of elements for (int i = 0; i < NE; i++) { Elements[i].CalculateAndAssemble_FeAndKeAndMe(ref F, ref K, ref M); } MatrixSparseLinkedList CDamping = ArtificialDamping_Factor_M * M + ArtificialDamping_Factor_K * K; MatrixSparseLinkedList Mhat = M + (gamma * DTime) * CDamping + (beta * DTime * DTime) * K; Mhat.LUDecomposition_Parallel(); //Adjust for boundary conditions int NBE = BoundaryElements.Length; for (int i = 0; i < NBE; i++) { BoundaryElements[i].AdjustF(Times.Values[StartIndex], ref F); BoundaryElements[i].AdjustK(Times.Values[StartIndex], ref K); } //Initial conditions Vector u_old = new Vector(Ut[StartIndex]); Vector v_old = new Vector(Vt[StartIndex]); //Initial acceleration Vector a_old = M.SolveLinearSystem(F - K * u_old); Node_ND.Set_UnknownForNode(Nodes, u_old); StoreSensors(StartIndex); double RTime = 0.0D; for (int i = StartIndex; i < NumberOfStepsToStore; i++) { for (int j = 0; j < NumberOfStepsToSkipOutput; j++) { RTime += DTime; //Increment to new time Element_ND.Time = RTime; //Give new time to all elements F_new = new Vector(NDF); for (int k = 0; k < NE; k++) { Elements[k].CalculateAndAssemble_Fe(ref F_new); //Calculate new F } //Adjust new F for BC for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustF(RTime, ref F_new); } //solve for new values u_old += DTime * v_old + (0.5D * DTime * DTime * (1.0D - 2.0D * beta)) * a_old; for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustU(RTime, ref u_old); } v_old += ((1.0D - gamma) * DTime) * a_old; for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustV(RTime, ref v_old); } a_old.Values = Mhat.SolveLinearSystemForwardEliminationAndBackSubstitution((F_new - CDamping * v_old - K * u_old).Values); u_old += (beta * DTime * DTime) * a_old; for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustU(RTime, ref u_old); } v_old += (gamma * DTime) * a_old; for (int k = 0; k < NBE; k++) { BoundaryElements[k].AdjustV(RTime, ref v_old); } } Times.Values[i + 1] = RTime; //Store time Ut[i + 1] = new Vector(u_old); //Store vector of node displacements Vt[i + 1] = new Vector(v_old); //Store vector of node velocity Solver_Output_Info.StoreAStep(i + 1, Times.Values[i + 1], Ut[i + 1], Vt[i + 1], DTime, NumberOfStepsToSkipOutput); Solver_Output_Info.SaveToFile(Solver_Output_Info.Make_OuptutAddress()); Node_ND.Set_UnknownForNode(Nodes, u_old); StoreSensors(i + 1); } }