def run_solver(self, interpolation_method): """Run solver.""" self.interpolation_method = interpolation_method t0 = time.time() n_vertex = len(set(self.mesh_data.all_nodes) - self.dirichlet_nodes) print("interpolation runing...") self.get_nodes_weights(interpolation_method) print( "done interpolation...", "took {0} seconds to interpolate over {1} verts".format( time.time() - t0, n_vertex ), ) print("filling the transmissibility matrix...") begin = time.time() try: for volume in self.volumes: volume_id = self.mb.tag_get_data(self.global_id_tag, volume)[ 0 ][0] RHS = self.mb.tag_get_data(self.source_tag, volume)[0][0] self.Q[volume_id] += RHS # self.Q[volume_id, 0] += RHS except Exception: pass for face in self.neumann_faces: face_flow = self.mb.tag_get_data(self.neumann_tag, face)[0][0] volume = self.mtu.get_bridge_adjacencies(face, 2, 3) volume = np.asarray(volume, dtype="uint64") id_volume = self.mb.tag_get_data(self.global_id_tag, volume)[0][0] face_nodes = self.mtu.get_bridge_adjacencies(face, 0, 0) node_crds = self.mb.get_coords(face_nodes).reshape([3, 3]) face_area = geo._area_vector(node_crds, norma=True) RHS = face_flow * face_area self.Q[id_volume] += -RHS # self.Q[id_volume, 0] += - RHS id_volumes = [] all_LHS = [] for face in self.dirichlet_faces: # '2' argument was initially '0' but it's incorrect I, J, K = self.mtu.get_bridge_adjacencies(face, 2, 0) left_volume = np.asarray( self.mtu.get_bridge_adjacencies(face, 2, 3), dtype="uint64" ) id_volume = self.mb.tag_get_data(self.global_id_tag, left_volume)[ 0 ][0] id_volumes.append(id_volume) JI = self.mb.get_coords([I]) - self.mb.get_coords([J]) JK = self.mb.get_coords([K]) - self.mb.get_coords([J]) LJ = ( self.mb.get_coords([J]) - self.mesh_data.mb.tag_get_data( self.volume_centre_tag, left_volume )[0] ) N_IJK = np.cross(JI, JK) / 2.0 _test = np.dot(LJ, N_IJK) if _test < 0.0: I, K = K, I JI = self.mb.get_coords([I]) - self.mb.get_coords([J]) JK = self.mb.get_coords([K]) - self.mb.get_coords([J]) N_IJK = np.cross(JI, JK) / 2.0 tan_JI = np.cross(N_IJK, JI) tan_JK = np.cross(N_IJK, JK) self.mb.tag_set_data(self.normal_tag, face, N_IJK) face_area = np.sqrt(np.dot(N_IJK, N_IJK)) h_L = geo.get_height(N_IJK, LJ) g_I = self.get_boundary_node_pressure(I) g_J = self.get_boundary_node_pressure(J) g_K = self.get_boundary_node_pressure(K) K_L = self.mb.tag_get_data(self.perm_tag, left_volume).reshape( [3, 3] ) K_n_L = self.vmv_multiply(N_IJK, K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, K_L, tan_JK) D_JK = self.get_cross_diffusion_term( tan_JK, LJ, face_area, h_L, K_n_L, K_L_JK, boundary=True ) D_JI = self.get_cross_diffusion_term( tan_JI, LJ, face_area, h_L, K_n_L, K_L_JI, boundary=True ) K_eq = (1 / h_L) * (face_area * K_n_L) RHS = D_JK * (g_I - g_J) - K_eq * g_J + D_JI * (g_J - g_K) LHS = K_eq all_LHS.append(LHS) self.Q[id_volume] += -RHS # self.Q[id_volume, 0] += - RHS # self.mb.tag_set_data(self.flux_info_tag, face, # [D_JK, D_JI, K_eq, I, J, K, face_area]) all_cols = [] all_rows = [] all_values = [] self.ids = [] self.v_ids = [] self.ivalues = [] for face in self.intern_faces: left_volume, right_volume = self.mtu.get_bridge_adjacencies( face, 2, 3 ) L = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, left_volume )[0] R = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, right_volume )[0] dist_LR = R - L I, J, K = self.mtu.get_bridge_adjacencies(face, 0, 0) JI = self.mb.get_coords([I]) - self.mb.get_coords([J]) JK = self.mb.get_coords([K]) - self.mb.get_coords([J]) N_IJK = np.cross(JI, JK) / 2.0 test = np.dot(N_IJK, dist_LR) if test < 0: left_volume, right_volume = right_volume, left_volume L = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, left_volume )[0] R = self.mesh_data.mb.tag_get_data( self.volume_centre_tag, right_volume )[0] dist_LR = R - L face_area = np.sqrt(np.dot(N_IJK, N_IJK)) tan_JI = np.cross(N_IJK, JI) tan_JK = np.cross(N_IJK, JK) K_R = self.mb.tag_get_data(self.perm_tag, right_volume).reshape( [3, 3] ) RJ = R - self.mb.get_coords([J]) h_R = geo.get_height(N_IJK, RJ) K_R_n = self.vmv_multiply(N_IJK, K_R, N_IJK) K_R_JI = self.vmv_multiply(N_IJK, K_R, tan_JI) K_R_JK = self.vmv_multiply(N_IJK, K_R, tan_JK) K_L = self.mb.tag_get_data(self.perm_tag, left_volume).reshape( [3, 3] ) LJ = L - self.mb.get_coords([J]) h_L = geo.get_height(N_IJK, LJ) K_L_n = self.vmv_multiply(N_IJK, K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, K_L, tan_JK) D_JI = self.get_cross_diffusion_term( tan_JI, dist_LR, face_area, h_L, K_L_n, K_L_JI, h_R, K_R_JI, K_R_n, ) D_JK = self.get_cross_diffusion_term( tan_JK, dist_LR, face_area, h_L, K_L_n, K_L_JK, h_R, K_R_JK, K_R_n, ) K_eq = (K_R_n * K_L_n) / (K_R_n * h_L + K_L_n * h_R) * face_area id_right = self.mb.tag_get_data(self.global_id_tag, right_volume) id_left = self.mb.tag_get_data(self.global_id_tag, left_volume) col_ids = [id_right, id_right, id_left, id_left] row_ids = [id_right, id_left, id_left, id_right] values = [K_eq, -K_eq, K_eq, -K_eq] all_cols.append(col_ids) all_rows.append(row_ids) all_values.append(values) # wait for interpolation to be done self._node_treatment(I, id_left, id_right, K_eq, D_JK=D_JK) self._node_treatment( J, id_left, id_right, K_eq, D_JI=D_JI, D_JK=-D_JK ) self._node_treatment(K, id_left, id_right, K_eq, D_JI=-D_JI) # self.mb.tag_set_data(self.flux_info_tag, face, # [D_JK, D_JI, K_eq, I, J, K, face_area]) self.T.InsertGlobalValues(self.ids, self.v_ids, self.ivalues) # self.T[ # np.asarray(self.ids)[:, :, 0, 0], np.asarray(self.v_ids) # ] = np.asarray(self.ivalues) self.T.InsertGlobalValues(id_volumes, id_volumes, all_LHS) # self.T[ # np.asarray(id_volumes), np.asarray(id_volumes) # ] = np.asarray(all_LHS) self.T.InsertGlobalValues(all_cols, all_rows, all_values) # self.T[ # np.asarray(all_cols)[:, 0, 0, 0], # np.asarray(all_rows)[:, 0, 0, 0] # ] = np.asarray(all_values)[:, 0] self.T.FillComplete() mat_fill_time = time.time() - begin print("matrix fill took {0} seconds...".format(mat_fill_time)) mesh_size = len(self.volumes) print("running solver...") USE_DIRECT_SOLVER = False linearProblem = Epetra.LinearProblem(self.T, self.x, self.Q) if USE_DIRECT_SOLVER: solver = Amesos.Lapack(linearProblem) print("1) Performing symbolic factorizations...") solver.SymbolicFactorization() print("2) Performing numeric factorizations...") solver.NumericFactorization() print("3) Solving the linear system...") solver.Solve() t = time.time() - t0 print( "Solver took {0} seconds to run over {1} volumes".format( t, mesh_size ) ) else: solver = AztecOO.AztecOO(linearProblem) solver.SetAztecOption(AztecOO.AZ_solver, AztecOO.AZ_gmres) solver.SetAztecOption(AztecOO.AZ_output, AztecOO.AZ_none) # solver.SetAztecOption(AztecOO.AZ_precond, AztecOO.AZ_Jacobi) # solver.SetAztecOption(AztecOO.AZ_kspace, 1251) # solver.SetAztecOption(AztecOO.AZ_orthog, AztecOO.AZ_modified) # solver.SetAztecOption(AztecOO.AZ_conv, AztecOO.AZ_Anorm) solver.Iterate(8000, 1e-10) t = time.time() - t0 its = solver.GetAztecStatus()[0] solver_time = solver.GetAztecStatus()[6] print( "Solver took {0} seconds to run over {1} volumes".format( t, mesh_size ) ) print( "Solver converged at %.dth iteration in %3f seconds." % (int(its), solver_time) ) # self.T = self.T.tocsc() # self.Q = self.Q.tocsc() # self.x = spsolve(self.T, self.Q) # print(np.sum(self.T[50]), self.Q[50]) self.mb.tag_set_data(self.pressure_tag, self.volumes, self.x)
print "Matrix fill took", time.time() - t0, "seconds... Ran over ", len( volumes), "elems" mb.tag_set_data(pres_tag, volumes, np.asarray(b[v_ids])) if USE_DIRECT_SOLVER: outfile_template = "Results/output_direct_{0}.vtk" else: outfile_template = "output_iterative_fine_grid{0}.vtk" mb.write_file(outfile_template.format(0)) linearProblem = Epetra.LinearProblem(A, x, b) if USE_DIRECT_SOLVER: solver = Amesos.Lapack(linearProblem) print "1) Performing symbolic factorizations..." solver.SymbolicFactorization() print "2) Performing numeric factorizations..." solver.NumericFactorization() print "3) Solving the linear system..." ierr = solver.Solve() else: solver = AztecOO.AztecOO(linearProblem) ierr = solver.Iterate(1000, 1e-9) print " solver.Solve() return code = ", ierr