private int get_matrix_index(matrix_class i_the_matrix, int i_id, int row_count) { for (int i = 0; i < row_count; i++) { if (i_the_matrix.GetRow(i)[1] == i_id) { return(i); } } return(-1); }
private void first_order_solver(ref RichTextBox richTextBox_analysis_status) { richTextBox_analysis_status.Clear(); // clear the richTextBox_AnalysisUpdate // loop variable int i, j, k; int dof = inpt_fe_object.main_mesh.all_points.Count; int edge_count = inpt_fe_object.main_mesh.all_edges.Count; int elmt_count = inpt_fe_object.main_mesh.all_triangles.Count; matrix_class global_k_matrix = new matrix_class(dof, dof); matrix_class global_f_matrix = new matrix_class(dof, 1); matrix_class global_dof_matrix = new matrix_class(dof, 1); // create nodes, edges and elements just for analysis matrix_class all_nodes_matrix = new matrix_class(dof, 6); matrix_class all_edges_matrix = new matrix_class(edge_count, 8); matrix_class all_elements_matrix = new matrix_class(elmt_count, 8); // create node matrix for (i = 0; i < dof; i++) { // node index, node id, node x coord, node y coord, node heat source, node specififed temperature all_nodes_matrix.SetRow(i, new double[] { i, inpt_fe_object.main_mesh.all_points[i].id, inpt_fe_object.main_mesh.all_points[i].x, inpt_fe_object.main_mesh.all_points[i].y, inpt_fe_object.main_mesh.all_points[i].heat_source, inpt_fe_object.main_mesh.all_points[i].spec_temp }); } // create edges matrix for (i = 0; i < edge_count; i++) { // edge index, edge id, start node index, end node index, edge heat source, edge specified temperature, edge heat transfer coeff, edge ambient temp all_edges_matrix.SetRow(i, new double[] { i, inpt_fe_object.main_mesh.all_edges[i].edge_id, get_matrix_index(all_nodes_matrix, inpt_fe_object.main_mesh.all_edges[i].start_pt.id, dof), get_matrix_index(all_nodes_matrix, inpt_fe_object.main_mesh.all_edges[i].end_pt.id, dof), inpt_fe_object.main_mesh.all_edges[i].heat_source, inpt_fe_object.main_mesh.all_edges[i].specified_temp, inpt_fe_object.main_mesh.all_edges[i].heat_transfer_coeff, inpt_fe_object.main_mesh.all_edges[i].ambient_temp });; } richTextBox_analysis_status.AppendText("Number of Nodes " + inpt_fe_object.main_mesh.all_points.Count.ToString() + "\n\n"); richTextBox_analysis_status.AppendText("Number of Edges " + inpt_fe_object.main_mesh.all_edges.Count.ToString() + "\n\n"); richTextBox_analysis_status.AppendText("Number of Elements " + inpt_fe_object.main_mesh.all_triangles.Count.ToString() + "\n\n"); // create element matrix for (i = 0; i < elmt_count; i++) { // extract current element pslg_datastructure.triangle2d current_element = inpt_fe_object.main_mesh.all_triangles[i]; // element index, element id, vertex 1 index, vertex 2 index, vertex 3 index, edge 1 index, edge 2 index, edge 3 index all_elements_matrix.SetRow(i, new double[] { i, inpt_fe_object.main_mesh.all_triangles[i].face_id, get_matrix_index(all_nodes_matrix, inpt_fe_object.main_mesh.all_triangles[i].vertices[0].id, dof), get_matrix_index(all_nodes_matrix, inpt_fe_object.main_mesh.all_triangles[i].vertices[1].id, dof), get_matrix_index(all_nodes_matrix, inpt_fe_object.main_mesh.all_triangles[i].vertices[2].id, dof), get_matrix_index(all_edges_matrix, inpt_fe_object.main_mesh.all_triangles[i].edge_id[0], edge_count), get_matrix_index(all_edges_matrix, inpt_fe_object.main_mesh.all_triangles[i].edge_id[1], edge_count), get_matrix_index(all_edges_matrix, inpt_fe_object.main_mesh.all_triangles[i].edge_id[2], edge_count) }); // extract the edges of the element pslg_datastructure.edge2d current_elm_edge1 = inpt_fe_object.main_mesh.all_edges[(int)all_elements_matrix[i, 5]]; pslg_datastructure.edge2d current_elm_edge2 = inpt_fe_object.main_mesh.all_edges[(int)all_elements_matrix[i, 6]]; pslg_datastructure.edge2d current_elm_edge3 = inpt_fe_object.main_mesh.all_edges[(int)all_elements_matrix[i, 7]]; // conduction matrix matrix_class conduction_matrix = new matrix_class(2, 2); conduction_matrix.SetRow(0, new double[] { current_element.thermal_conductivity_x, 0.0 }); conduction_matrix.SetRow(1, new double[] { 0.0, current_element.thermal_conductivity_y }); // linear shape function parameters double a_i, b_i, c_i, a_j, b_j, c_j, a_k, b_k, c_k; a_i = (all_nodes_matrix[(int)all_elements_matrix[i, 3], 2] * all_nodes_matrix[(int)all_elements_matrix[i, 4], 3]) - (all_nodes_matrix[(int)all_elements_matrix[i, 4], 2] * all_nodes_matrix[(int)all_elements_matrix[i, 3], 3]); b_i = all_nodes_matrix[(int)all_elements_matrix[i, 3], 3] - all_nodes_matrix[(int)all_elements_matrix[i, 4], 3]; c_i = all_nodes_matrix[(int)all_elements_matrix[i, 4], 2] - all_nodes_matrix[(int)all_elements_matrix[i, 3], 2]; a_j = (all_nodes_matrix[(int)all_elements_matrix[i, 4], 2] * all_nodes_matrix[(int)all_elements_matrix[i, 2], 3]) - (all_nodes_matrix[(int)all_elements_matrix[i, 2], 2] * all_nodes_matrix[(int)all_elements_matrix[i, 4], 3]); b_j = all_nodes_matrix[(int)all_elements_matrix[i, 4], 3] - all_nodes_matrix[(int)all_elements_matrix[i, 2], 3]; c_j = all_nodes_matrix[(int)all_elements_matrix[i, 2], 2] - all_nodes_matrix[(int)all_elements_matrix[i, 4], 2]; a_k = (all_nodes_matrix[(int)all_elements_matrix[i, 2], 2] * all_nodes_matrix[(int)all_elements_matrix[i, 3], 3]) - (all_nodes_matrix[(int)all_elements_matrix[i, 3], 2] * all_nodes_matrix[(int)all_elements_matrix[i, 2], 3]); b_k = all_nodes_matrix[(int)all_elements_matrix[i, 2], 3] - all_nodes_matrix[(int)all_elements_matrix[i, 3], 3]; c_k = all_nodes_matrix[(int)all_elements_matrix[i, 3], 2] - all_nodes_matrix[(int)all_elements_matrix[i, 2], 2]; // B_matrix of linear triangle matrix_class b_matrix = new matrix_class(2, 3); b_matrix.SetRow(0, new double[] { b_i, b_j, b_k }); b_matrix.SetRow(1, new double[] { c_i, c_j, c_k }); b_matrix = (1.0 / (2.0 * current_element.element_area)) * b_matrix; // element conduction matrix matrix_class element_conduction_matrix = new matrix_class(3, 3); element_conduction_matrix = (current_element.element_thickness * current_element.element_area) * (b_matrix.Transpose() * (conduction_matrix * b_matrix)); // element convection matrix double c_param = (-2.0 * current_element.heat_transfer_coeff) / (current_element.element_thickness); matrix_class element_convection_matrix = new matrix_class(3, 3); element_convection_matrix.SetRow(0, new double[] { 2, 1, 1 }); element_convection_matrix.SetRow(1, new double[] { 1, 2, 1 }); element_convection_matrix.SetRow(2, new double[] { 1, 1, 2 }); element_convection_matrix = ((c_param * current_element.element_area) / 12.0) * element_convection_matrix; // element heat convection due to edge exposed to ambient temperature (internal edges shouldn't have convection (user caution is required)) // element convection due to edge i-j convection matrix_class element_edge_ij_convection_matrix = new matrix_class(3, 3); element_edge_ij_convection_matrix.SetRow(0, new double[] { 2, 1, 0 }); element_edge_ij_convection_matrix.SetRow(1, new double[] { 1, 2, 0 }); element_edge_ij_convection_matrix.SetRow(2, new double[] { 0, 0, 0 }); element_edge_ij_convection_matrix = ((current_elm_edge1.heat_transfer_coeff * current_elm_edge1.edge_length * current_element.element_thickness) / 6.0) * element_edge_ij_convection_matrix; // element convection due to edge j-k convection matrix_class element_edge_jk_convection_matrix = new matrix_class(3, 3); element_edge_jk_convection_matrix.SetRow(0, new double[] { 0, 0, 0 }); element_edge_jk_convection_matrix.SetRow(1, new double[] { 0, 2, 1 }); element_edge_jk_convection_matrix.SetRow(2, new double[] { 0, 1, 2 }); element_edge_jk_convection_matrix = ((current_elm_edge2.heat_transfer_coeff * current_elm_edge2.edge_length * current_element.element_thickness) / 6.0) * element_edge_jk_convection_matrix; // element convection due to edge k-i convection matrix_class element_edge_ki_convection_matrix = new matrix_class(3, 3); element_edge_ki_convection_matrix.SetRow(0, new double[] { 2, 0, 1 }); element_edge_ki_convection_matrix.SetRow(1, new double[] { 0, 0, 0 }); element_edge_ki_convection_matrix.SetRow(2, new double[] { 1, 0, 2 }); element_edge_ki_convection_matrix = ((current_elm_edge3.heat_transfer_coeff * current_elm_edge3.edge_length * current_element.element_thickness) / 6.0) * element_edge_ki_convection_matrix; // element heat source matrix matrix_class element_heat_source_matrix = new matrix_class(3, 1); element_heat_source_matrix.SetColumn(0, new double[] { 1, 1, 1 }); element_heat_source_matrix = ((current_element.heat_source * current_element.element_area * current_element.element_thickness) / 3.0) * element_heat_source_matrix; // element heat convection 1 matrix matrix_class element_heat_convection_matrix = new matrix_class(3, 1); element_heat_convection_matrix.SetColumn(0, new double[] { 1, 1, 1 }); element_heat_convection_matrix = ((c_param * current_element.ambient_temp * current_element.element_area) / 3.0) * element_heat_convection_matrix; // edge heat source matrix matrix_class edge_heatsource_matrix = new matrix_class(3, 1); // edge heat soure due to edge i-j source matrix_class edge_ij_heatsource_matrix = new matrix_class(3, 1); edge_ij_heatsource_matrix.SetColumn(0, new double[] { 1, 1, 0 }); edge_ij_heatsource_matrix = ((current_elm_edge1.heat_source * current_elm_edge1.edge_length * current_element.element_thickness) / 2.0) * edge_ij_heatsource_matrix; // edge heat soure due to edge j-k source matrix_class edge_jk_heatsource_matrix = new matrix_class(3, 1); edge_jk_heatsource_matrix.SetColumn(0, new double[] { 0, 1, 1 }); edge_jk_heatsource_matrix = ((current_elm_edge2.heat_source * current_elm_edge2.edge_length * current_element.element_thickness) / 2.0) * edge_jk_heatsource_matrix; // edge heat soure due to edge k-i source matrix_class edge_ki_heatsource_matrix = new matrix_class(3, 1); edge_ki_heatsource_matrix.SetColumn(0, new double[] { 1, 0, 1 }); edge_ki_heatsource_matrix = ((current_elm_edge3.heat_source * current_elm_edge3.edge_length * current_element.element_thickness) / 2.0) * edge_ki_heatsource_matrix; edge_heatsource_matrix = edge_ij_heatsource_matrix + edge_jk_heatsource_matrix + edge_ki_heatsource_matrix; // edge heat convection matrix matrix_class edge_heatconvection_matrix = new matrix_class(3, 1); // edge heat convection due to edge i-j ambient temperature matrix_class edge_ij_heatconvection_matrix = new matrix_class(3, 1); edge_ij_heatconvection_matrix.SetColumn(0, new double[] { 1, 1, 0 }); edge_ij_heatconvection_matrix = ((current_elm_edge1.heat_transfer_coeff * current_elm_edge1.ambient_temp * current_elm_edge1.edge_length * current_element.element_thickness) / 2.0) * edge_ij_heatconvection_matrix; // edge heat convection due to edge j-k ambient temperature matrix_class edge_jk_heatconvection_matrix = new matrix_class(3, 1); edge_jk_heatconvection_matrix.SetColumn(0, new double[] { 0, 1, 1 }); edge_jk_heatconvection_matrix = ((current_elm_edge2.heat_transfer_coeff * current_elm_edge2.ambient_temp * current_elm_edge2.edge_length * current_element.element_thickness) / 2.0) * edge_jk_heatconvection_matrix; // edge heat convection due to edge k-i ambient temperature matrix_class edge_ki_heatconvection_matrix = new matrix_class(3, 1); edge_ki_heatconvection_matrix.SetColumn(0, new double[] { 1, 0, 1 }); edge_ki_heatconvection_matrix = ((current_elm_edge3.heat_transfer_coeff * current_elm_edge3.ambient_temp * current_elm_edge3.edge_length * current_element.element_thickness) / 2.0) * edge_ki_heatconvection_matrix; edge_heatconvection_matrix = edge_ij_heatconvection_matrix + edge_jk_heatconvection_matrix + edge_ki_heatconvection_matrix; // edge specified temperature matrix matrix_class edge_spectemp_matrix = new matrix_class(3, 1); // edge i-j specified temperature matrix_class edge_ij_spectemp_matrix = new matrix_class(3, 1); edge_ij_spectemp_matrix.SetColumn(0, new double[] { 1, 1, 0 }); edge_ij_spectemp_matrix = (current_elm_edge1.specified_temp / 2.0) * edge_ij_spectemp_matrix; // edge j-k specified temperature matrix_class edge_jk_spectemp_matrix = new matrix_class(3, 1); edge_jk_spectemp_matrix.SetColumn(0, new double[] { 0, 1, 1 }); edge_jk_spectemp_matrix = (current_elm_edge2.specified_temp / 2.0) * edge_jk_spectemp_matrix; // edge k-i specified temperature matrix_class edge_ki_spectemp_matrix = new matrix_class(3, 1); edge_ki_spectemp_matrix.SetColumn(0, new double[] { 1, 0, 1 }); edge_ki_spectemp_matrix = (current_elm_edge3.specified_temp / 2.0) * edge_ki_spectemp_matrix; edge_spectemp_matrix = edge_ij_spectemp_matrix + edge_jk_spectemp_matrix + edge_ki_spectemp_matrix; // element k matrix matrix_class element_k_matrix = new matrix_class(3, 3); element_k_matrix = element_conduction_matrix + (-element_convection_matrix) + element_edge_ij_convection_matrix + element_edge_jk_convection_matrix + element_edge_ki_convection_matrix; // element f matrix matrix_class element_f_matrix = new matrix_class(3, 1); element_f_matrix = element_heat_source_matrix + element_heat_convection_matrix + edge_heatsource_matrix + edge_heatconvection_matrix; // dof matrix carries the specified temperature // element dof matrix matrix_class element_dof_matrix = new matrix_class(3, 1); element_dof_matrix = edge_spectemp_matrix; // global k matrix for (k = 0; k < 3; k++) { int v_index1 = (int)all_elements_matrix[i, 2 + k]; for (j = 0; j < 3; j++) { int v_index2 = (int)all_elements_matrix[i, 2 + j]; // global k matrix global_k_matrix[v_index1, v_index2] = global_k_matrix[v_index1, v_index2] + element_k_matrix[k, j]; } // global f matrix global_f_matrix[v_index1, 0] = global_f_matrix[v_index1, 0] + element_f_matrix[k, 0]; // global dof matrix global_dof_matrix[v_index1, 0] = global_dof_matrix[v_index1, 0] + element_dof_matrix[k, 0]; } } // Apply nodal heat source & specified temperature for (i = 0; i < dof; i++) { // heat source at node global_f_matrix[i, 0] = global_f_matrix[i, 0] + inpt_fe_object.main_mesh.all_points[i].heat_source; // specified temperature global_dof_matrix[i, 0] = global_dof_matrix[i, 0] + inpt_fe_object.main_mesh.all_points[i].spec_temp; } // Applying specified temperature as source matrix_class global_spec_temp_matrix = new matrix_class(dof, 1); global_spec_temp_matrix = -1 * (global_k_matrix * global_dof_matrix); // Find the size of matrix after boundary condition is applied int soln_matrix_count = 0; for (i = 0; i < dof; i++) { if (global_dof_matrix[i, 0] == 0) { soln_matrix_count++; } } richTextBox_analysis_status.AppendText("Total number of DOF without prescribed Temperature " + soln_matrix_count.ToString() + "\n\n"); // curtailed matrix after applying boundary condition matrix_class curtailed_global_k_matrix = new matrix_class(soln_matrix_count, soln_matrix_count); matrix_class curtailed_global_f_matrix = new matrix_class(soln_matrix_count, 1); int r = 0, s = 0; for (i = 0; i < dof; i++) { if (global_dof_matrix[i, 0] != 0) { continue; } else { // apply boundary condition to global f matrix curtailed_global_f_matrix[r, 0] = global_f_matrix[i, 0] + global_spec_temp_matrix[i, 0]; s = 0; for (j = 0; j < dof; j++) { if (global_dof_matrix[j, 0] != 0) { continue; } else { // apply boundary condition to global k matrix curtailed_global_k_matrix[r, s] = global_k_matrix[i, j]; s++; } } r++; } } // Build matrix to use in mathnet.numerics Matrix <double> A_var = Matrix <double> .Build.DenseOfArray(curtailed_global_k_matrix.return_matrix_as_double); Vector <double> B_var = Vector <double> .Build.Dense(curtailed_global_f_matrix.GetColumn(0)); // solve the matrix using mathnet.numerics Vector <double> x_var = A_var.Solve(B_var); // global t matrix double[] gloabl_t_val = new double[dof]; r = 0; for (i = 0; i < dof; i++) { if (global_dof_matrix[i, 0] != 0) { gloabl_t_val[i] = global_dof_matrix[i, 0]; } else { gloabl_t_val[i] = x_var[r]; r++; } } // create element store list List <pslg_datastructure.result_store.first_order_element_store> f_o_elements = new List <pslg_datastructure.result_store.first_order_element_store>(); // maximum and minimum z val double max_zval = gloabl_t_val.Max(); double min_zval = gloabl_t_val.Min(); // set the contour intervals double z_val_range = max_zval - min_zval; double[] contour_interval = new double[static_parameters.n_contour_intervals]; for (i = 1; i < static_parameters.n_contour_intervals; i++) { contour_interval[i] = min_zval + ((z_val_range / static_parameters.n_contour_intervals) * i); } if (z_val_range <= 1E-10 || double.IsNaN(z_val_range) == true) { richTextBox_analysis_status.AppendText("!!!!!!!! Analysis Failed !!!!!!!! " + "\n\n"); return; // Exit sub } else { richTextBox_analysis_status.AppendText("Maximum Temperature " + max_zval.ToString() + "\n"); richTextBox_analysis_status.AppendText("Minimum Temperature " + min_zval.ToString() + "\n\n"); richTextBox_analysis_status.AppendText("!!!!!!!! Analysis Complete !!!!!!!! " + "\n\n"); } // Set the results to output for (i = 0; i < elmt_count; i++) { double[] elm_z_val = new double[3]; elm_z_val[0] = gloabl_t_val[(int)all_elements_matrix[i, 2]]; elm_z_val[1] = gloabl_t_val[(int)all_elements_matrix[i, 3]]; elm_z_val[2] = gloabl_t_val[(int)all_elements_matrix[i, 4]]; pslg_datastructure.result_store.first_order_element_store f_o_elm = new pslg_datastructure.result_store.first_order_element_store(inpt_fe_object.main_mesh.all_triangles[i], elm_z_val, contour_interval, max_zval, min_zval); f_o_elements.Add(f_o_elm); } // create result store and add it to the model pslg_datastructure.result_store rslt_output = new pslg_datastructure.result_store(); rslt_output = new pslg_datastructure.result_store(1, f_o_elements, null, null, max_zval, min_zval, contour_interval); inpt_fe_object.main_mesh.set_analysis_results(rslt_output); }