def lambda_lpew3(self, node, aux_node, face): # Should include tao parameter in order to change interpolation region adj_vols = self.mtu.get_bridge_adjacencies(face, 2, 3) face_nodes = self.mtu.get_bridge_adjacencies(face, 2, 0) ref_node = list(set(face_nodes) - (set([node]) | set([aux_node]))) face_nodes_crds = self.mb.get_coords(face_nodes) face_nodes_crds = np.reshape(face_nodes_crds, (3, 3)) ref_node = self.mb.get_coords(ref_node) aux_node = self.mb.get_coords([aux_node]) node = self.mb.get_coords([node]) lambda_l = 0.0 for a_vol in adj_vols: vol_perm = self.mb.tag_get_data(self.perm_tag, a_vol) vol_perm = np.reshape(vol_perm, (3, 3)) vol_cent = self.mesh_data.mb.tag_get_data( self.mesh_data.volume_centre_tag, a_vol)[0] vol_nodes = self.mb.get_adjacencies(a_vol, 0) sub_vol = np.append(face_nodes_crds, vol_cent) sub_vol = np.reshape(sub_vol, (4, 3)) tetra_vol = self.mesh_data.get_tetra_volume(sub_vol) ref_node_i = list(set(vol_nodes) - set(face_nodes)) ref_node_i = self.mb.get_coords(ref_node_i) N_int = geo._area_vector([node, aux_node, vol_cent], ref_node)[0] N_i = geo._area_vector(face_nodes_crds, ref_node_i)[0] lambda_l += self.flux_term(N_i, vol_perm, N_int) / tetra_vol return lambda_l
def test_if_flux_is_conservative_for_all_volumes(self): """Test if flux is conservative for all volumes in the test domain.""" mb = self.od.mb bcVerts = self.od.get_boundary_nodes() for bcVert in bcVerts: vertCoords = mb.get_coords([bcVert]) bcVal = self.psol1(vertCoords) mb.tag_set_data(self.od.dirichlet_tag, bcVert, bcVal) self.node_pressure_tag = self.od_mpfad.mb.tag_get_handle( "Node Pressure", 1, types.MB_TYPE_DOUBLE, types.MB_TAG_SPARSE, True) self.od_mpfad.run_solver(LPEW3(self.od).interpolate) p_verts = [] for node in self.od.all_nodes: p_vert = self.od_mpfad.mb.tag_get_data(self.od_mpfad.dirichlet_tag, node) p_verts.append(p_vert[0]) self.od_mpfad.mb.tag_set_data(self.node_pressure_tag, self.od.all_nodes, p_verts) for a_volume in self.od.all_volumes: vol_centroid = self.od.mtu.get_average_position([a_volume]) vol_faces = self.od.mtu.get_bridge_adjacencies(a_volume, 2, 2) vol_p = self.od.mb.tag_get_data(self.od_mpfad.pressure_tag, a_volume)[0][0] vol_nodes = self.od.mtu.get_bridge_adjacencies(a_volume, 0, 0) vol_crds = self.od.mb.get_coords(vol_nodes) vol_crds = np.reshape(vol_crds, ([4, 3])) vol_volume = self.od.get_tetra_volume(vol_crds) vol_perm = self.od.mb.tag_get_data(self.od_mpfad.perm_tag, a_volume).reshape([3, 3]) fluxes = [] for a_face in vol_faces: f_nodes = self.od.mtu.get_bridge_adjacencies(a_face, 0, 0) fc_nodes = self.od.mb.get_coords(f_nodes) fc_nodes = np.reshape(fc_nodes, ([3, 3])) grad = np.zeros(3) for i in range(len(fc_nodes)): set_of_verts = np.array( [fc_nodes[i], fc_nodes[i - 1], vol_centroid]) area_vect = geo._area_vector(set_of_verts, fc_nodes[i - 2])[0] p_node_op = self.od_mpfad.mb.tag_get_data( self.node_pressure_tag, f_nodes[i - 2])[0][0] grad += area_vect * p_node_op area_vect = geo._area_vector(fc_nodes, vol_centroid)[0] grad += area_vect * vol_p grad = grad / (3.0 * vol_volume) flux = -np.dot(np.dot(vol_perm, grad), area_vect) fluxes.append(flux) fluxes_sum = abs(sum(fluxes)) self.assertAlmostEqual(fluxes_sum, 0.0, delta=1e-9)
def sigma_lpew3(self, node, vol): node_crds = self.mb.get_coords([node]) adj_faces = set(self.mtu.get_bridge_adjacencies(node, 0, 2)) vol_faces = set(self.mtu.get_bridge_adjacencies(vol, 3, 2)) in_faces = list(adj_faces & vol_faces) vol_cent = self.mesh_data.mb.tag_get_data( self.mesh_data.volume_centre_tag, vol)[0] clockwise = 1.0 counter_clockwise = 1.0 for a_face in in_faces: aux_nodes = set(self.mtu.get_bridge_adjacencies(a_face, 2, 0)) aux_nodes.remove(node) aux_nodes = list(aux_nodes) aux_nodes_crds = self.mb.get_coords(aux_nodes) aux_nodes_crds = np.reshape(aux_nodes_crds, (2, 3)) aux_vect = [node_crds, aux_nodes_crds[0], aux_nodes_crds[1]] spin = geo._area_vector(aux_vect, vol_cent)[1] if spin < 0: aux_nodes[0], aux_nodes[1] = aux_nodes[1], aux_nodes[0] count = self.lambda_lpew3(node, aux_nodes[0], a_face) counter_clockwise = counter_clockwise * count clock = self.lambda_lpew3(node, aux_nodes[1], a_face) clockwise = clockwise * clock sigma = clockwise + counter_clockwise return sigma
def neta_lpew3(self, node, vol, face): vol_perm = self.mb.tag_get_data(self.perm_tag, vol) vol_perm = np.reshape(vol_perm, (3, 3)) vol_nodes = self.mb.get_adjacencies(vol, 0) face_nodes = self.mtu.get_bridge_adjacencies(face, 2, 0) face_nodes_crds = self.mb.get_coords(face_nodes) face_nodes_crds = np.reshape(face_nodes_crds, (3, 3)) ref_node = list(set(vol_nodes) - set(face_nodes)) ref_node = self.mb.get_coords(ref_node) vol_nodes_crds = self.mb.get_coords(list(vol_nodes)) vol_nodes_crds = np.reshape(vol_nodes_crds, (4, 3)) tetra_vol = self.mesh_data.get_tetra_volume(vol_nodes_crds) vol_nodes = set(vol_nodes) vol_nodes.remove(node) face_nodes_i = self.mb.get_coords(list(vol_nodes)) face_nodes_i = np.reshape(face_nodes_i, (3, 3)) node = self.mb.get_coords([node]) N_out = geo._area_vector(face_nodes_i, node)[0] N_i = geo._area_vector(face_nodes_crds, ref_node)[0] neta = self.flux_term(N_out, vol_perm, N_i) / tetra_vol return neta
def csi_lpew3(self, face, vol): vol_perm = self.mb.tag_get_data(self.perm_tag, vol) vol_perm = np.reshape(vol_perm, (3, 3)) vol_cent = self.mesh_data.mb.tag_get_data( self.mesh_data.volume_centre_tag, vol)[0] face_nodes = self.mtu.get_bridge_adjacencies(face, 2, 0) face_nodes = self.mb.get_coords(face_nodes) face_nodes = np.reshape(face_nodes, (3, 3)) N_i = geo._area_vector(face_nodes, vol_cent)[0] sub_vol = np.append(face_nodes, vol_cent) sub_vol = np.reshape(sub_vol, (4, 3)) tetra_vol = self.mesh_data.get_tetra_volume(sub_vol) csi = self.flux_term(N_i, vol_perm, N_i) / tetra_vol return csi
def neumann_treatment(self, node): adj_faces = self.mtu.get_bridge_adjacencies(node, 0, 2) N_term_sum = 0.0 for face in adj_faces: if face not in self.neumann_faces: continue face_flux = self.mb.tag_get_data(self.neumann_tag, face)[0][0] face_nodes = self.mb.get_adjacencies(face, 0) nodes_crds = self.mb.get_coords(face_nodes) nodes_crds = np.reshape(nodes_crds, (len(face_nodes), 3)) face_area = geo._area_vector(nodes_crds, np.array([0.0, 0.0, 0.0]), norma=True) # store face_area vol_N = tuple(self.mtu.get_bridge_adjacencies(face, 2, 3)) psi_N = self.psi_sum_lpew3(node, vol_N, face) phi_N = self.phi_lpew3(node, vol_N, face) N_term = -3.0 * (1 + (psi_N - phi_N)) * face_flux * face_area N_term_sum += N_term return N_term_sum
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)
def get_velocity(self, bmk): self.node_pressure_tag = self.mpfad.mb.tag_get_handle( "Node Pressure", 1, types.MB_TYPE_DOUBLE, types.MB_TAG_SPARSE, True ) p_verts = [] for node in self.mesh.all_nodes: try: p_vert = self.mpfad.mb.tag_get_data( self.mpfad.dirichlet_tag, node ) p_verts.append(p_vert[0]) except Exception: p_vert = 0.0 p_tag = self.mpfad.pressure_tag nd_weights = self.mpfad.nodes_ws[node] for volume, wt in nd_weights.items(): p_vol = self.mpfad.mb.tag_get_data(p_tag, volume) p_vert += p_vol * wt p_verts.append(p_vert[0]) self.mpfad.mb.tag_set_data( self.node_pressure_tag, self.mesh.all_nodes, p_verts ) err = [] err_grad = [] grads_p = [] all_vels = [] areas = [] vols = [] for a_volume in self.mesh.all_volumes: vol_faces = self.mesh.mtu.get_bridge_adjacencies(a_volume, 2, 2) vol_nodes = self.mesh.mtu.get_bridge_adjacencies(a_volume, 0, 0) vol_crds = self.mesh.mb.get_coords(vol_nodes) vol_crds = np.reshape(vol_crds, ([4, 3])) vol_volume = self.mesh.get_tetra_volume(vol_crds) vols.append(vol_volume) I, J, K = self.mesh.mtu.get_bridge_adjacencies(vol_faces[0], 2, 0) L = list( set(vol_nodes).difference( set( self.mesh.mtu.get_bridge_adjacencies( vol_faces[0], 2, 0 ) ) ) ) JI = self.mesh.mb.get_coords([I]) - self.mesh.mb.get_coords([J]) JK = self.mesh.mb.get_coords([K]) - self.mesh.mb.get_coords([J]) LJ = self.mesh.mb.get_coords([J]) - self.mesh.mb.get_coords(L) N_IJK = np.cross(JI, JK) / 2.0 test = np.dot(LJ, N_IJK) if test < 0.0: I, K = K, I JI = self.mesh.mb.get_coords([I]) - self.mesh.mb.get_coords( [J] ) JK = self.mesh.mb.get_coords([K]) - self.mesh.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) face_area = np.sqrt(np.dot(N_IJK, N_IJK)) h_L = geo.get_height(N_IJK, LJ) p_I = self.mpfad.mb.tag_get_data(self.node_pressure_tag, I) p_J = self.mpfad.mb.tag_get_data(self.node_pressure_tag, J) p_K = self.mpfad.mb.tag_get_data(self.node_pressure_tag, K) p_L = self.mpfad.mb.tag_get_data(self.node_pressure_tag, L) grad_normal = -2 * (p_J - p_L) * N_IJK grad_cross_I = (p_J - p_I) * ( (np.dot(tan_JK, LJ) / face_area ** 2) * N_IJK - (h_L / (face_area)) * tan_JK ) grad_cross_K = (p_K - p_J) * ( (np.dot(tan_JI, LJ) / face_area ** 2) * N_IJK - (h_L / (face_area)) * tan_JI ) grad_p = -(1 / (6 * vol_volume)) * ( grad_normal + grad_cross_I + grad_cross_K ) vol_centroid = np.asarray( self.mesh.mb.tag_get_data( self.mesh.volume_centre_tag, a_volume )[0] ) vol_perm = self.mesh.mb.tag_get_data( self.mesh.perm_tag, a_volume ).reshape([3, 3]) x, y, z = vol_centroid grad_p_bar = self.calculate_gradient(x, y, z, bmk) grads_p.append(np.dot(grad_p_bar, grad_p_bar)) # print(grad_p, grad_p_bar, grad_p - grad_p_bar) e = grad_p[0] - grad_p_bar err_norm = np.sqrt(np.dot(e, e)) # print(err_norm) err_grad.append(err_norm ** 2) for face in vol_faces: # x, y, z = self.mesh.mb.get_coords([face]) face_nodes = self.mesh.mtu.get_bridge_adjacencies(face, 2, 0) face_nodes_crds = self.mesh.mb.get_coords(face_nodes) area_vect = geo._area_vector( face_nodes_crds.reshape([3, 3]), vol_centroid )[0] unit_area_vec = area_vect / np.sqrt( np.dot(area_vect, area_vect) ) k_grad_p = np.dot(vol_perm, grad_p[0]) vel = -np.dot(k_grad_p, unit_area_vec) calc_vel = -np.dot( self.calculate_K_gradient(x, y, z, bmk), unit_area_vec ) err.append(abs(vel - calc_vel) ** 2) areas.append(np.sqrt(np.dot(area_vect, area_vect))) all_vels.append(calc_vel ** 2) norm_vel = np.sqrt(np.dot(err, areas) / np.dot(all_vels, areas)) norm_grad = np.sqrt(np.dot(err_grad, vols) / np.dot(grads_p, vols)) return norm_vel, norm_grad
def test_if_gradient_yields_correct_values(self): """Test if gradient yelds expeted values.""" self.node_pressure_tag = self.mpfad.mb.tag_get_handle( "Node Pressure", 1, types.MB_TYPE_DOUBLE, types.MB_TAG_SPARSE, True) self.mpfad.run_solver(LPEW3(self.mesh).interpolate) p_verts = [] for node in self.mesh.all_nodes: p_vert = self.mpfad.mb.tag_get_data(self.mpfad.dirichlet_tag, node) p_verts.append(p_vert[0]) self.mpfad.mb.tag_set_data(self.node_pressure_tag, self.mesh.all_nodes, p_verts) for a_volume in self.mesh.all_volumes: vol_faces = self.mesh.mtu.get_bridge_adjacencies(a_volume, 2, 2) vol_nodes = self.mesh.mtu.get_bridge_adjacencies(a_volume, 0, 0) vol_crds = self.mesh.mb.get_coords(vol_nodes) vol_crds = np.reshape(vol_crds, ([4, 3])) vol_volume = self.mesh.get_tetra_volume(vol_crds) I, J, K = self.mesh.mtu.get_bridge_adjacencies(vol_faces[0], 2, 0) L = list( set(vol_nodes).difference( set( self.mesh.mtu.get_bridge_adjacencies( vol_faces[0], 2, 0)))) JI = self.mesh.mb.get_coords([I]) - self.mesh.mb.get_coords([J]) JK = self.mesh.mb.get_coords([K]) - self.mesh.mb.get_coords([J]) LJ = self.mesh.mb.get_coords([J]) - self.mesh.mb.get_coords(L) N_IJK = np.cross(JI, JK) / 2.0 test = np.dot(LJ, N_IJK) if test < 0.0: I, K = K, I JI = self.mesh.mb.get_coords([I]) - self.mesh.mb.get_coords( [J]) JK = self.mesh.mb.get_coords([K]) - self.mesh.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) face_area = np.sqrt(np.dot(N_IJK, N_IJK)) h_L = geo.get_height(N_IJK, LJ) p_I = self.mpfad.mb.tag_get_data(self.node_pressure_tag, I) p_J = self.mpfad.mb.tag_get_data(self.node_pressure_tag, J) p_K = self.mpfad.mb.tag_get_data(self.node_pressure_tag, K) p_L = self.mpfad.mb.tag_get_data(self.node_pressure_tag, L) grad_normal = -2 * (p_J - p_L) * N_IJK grad_cross_I = (p_J - p_I) * ( (np.dot(tan_JK, LJ) / face_area**2) * N_IJK - (h_L / (face_area)) * tan_JK) grad_cross_K = (p_K - p_J) * ( (np.dot(tan_JI, LJ) / face_area**2) * N_IJK - (h_L / (face_area)) * tan_JI) grad_p = -(1 / (6 * vol_volume)) * (grad_normal + grad_cross_I + grad_cross_K) vol_centroid = np.asarray( self.mesh.mb.tag_get_data(self.mesh.volume_centre_tag, a_volume)[0]) vol_perm = self.mesh.mb.tag_get_data(self.mesh.perm_tag, a_volume).reshape([3, 3]) v = 0.0 for face in vol_faces: face_nodes = self.mesh.mtu.get_bridge_adjacencies(face, 2, 0) face_nodes_crds = self.mesh.mb.get_coords(face_nodes) area_vect = geo._area_vector(face_nodes_crds.reshape([3, 3]), vol_centroid)[0] unit_area_vec = area_vect / np.sqrt( np.dot(area_vect, area_vect)) k_grad_p = np.dot(vol_perm, grad_p[0]) vel = -np.dot(k_grad_p, unit_area_vec) v += vel * np.sqrt(np.dot(area_vect, area_vect))
def tag_velocity(self): self.tag_verts_pressure() velocities = [] for face in self.neumann_faces: face_mobility = self.mb.tag_get_data(self.face_mobility_tag, face)[0][0] 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") 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) velocity = face_mobility * face_flow * face_area velocities.append(velocity) self.mb.tag_set_data(self.velocity_tag, self.neumann_faces, velocities) velocities = [] dirichlet_faces = list(self.dirichlet_faces) for face in dirichlet_faces: face_mobility = self.mb.tag_get_data(self.face_mobility_tag, face)[0][0] # '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") 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.mb.tag_get_data(self.node_pressure_tag, I) g_J = self.mb.tag_get_data(self.node_pressure_tag, J) g_K = self.mb.tag_get_data(self.node_pressure_tag, K) K_L = self.mb.tag_get_data(self.perm_tag, left_volume).reshape([3, 3]) K_n_L = self.vmv_multiply(N_IJK, face_mobility * K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, face_mobility * K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, face_mobility * 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) p_vol = self.mb.tag_get_data(self.pressure_tag, left_volume) velocity = (D_JK * (g_I - g_J) - K_eq * (p_vol - g_J) + D_JI * (g_J - g_K)) velocities.append(velocity) vels = np.asarray(velocities).flatten() self.mb.tag_set_data(self.velocity_tag, dirichlet_faces, vels) velocities = [] left_vols = [] intern_faces = list(self.intern_faces) for face in intern_faces: face_mobility = self.mb.tag_get_data(self.face_mobility_tag, face)[0][0] 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, face_mobility * K_R, N_IJK) K_R_JI = self.vmv_multiply(N_IJK, face_mobility * K_R, tan_JI) K_R_JK = self.vmv_multiply(N_IJK, face_mobility * 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, face_mobility * K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, face_mobility * K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, face_mobility * 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 p_r = self.mb.tag_get_data(self.pressure_tag, right_volume) p_l = self.mb.tag_get_data(self.pressure_tag, left_volume) p_I = self.mb.tag_get_data(self.node_pressure_tag, I) p_J = self.mb.tag_get_data(self.node_pressure_tag, J) p_K = self.mb.tag_get_data(self.node_pressure_tag, K) velocity = K_eq * (p_r - p_l - D_JI * (p_I - p_J) - D_JK * (p_K - p_J)) velocities.append(velocity) left_vols.append(left_volume) velocities = np.asarray(velocities).flatten() self.mb.tag_set_data(self.velocity_tag, intern_faces, velocities) self.mb.tag_set_data(self.left_volume_tag, left_vols, np.repeat(1, len(left_vols)))
def run_solver(self, interpolation_method): """Run solver.""" self.get_mobility() 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_mobility = self.mb.tag_get_data(self.face_mobility_tag, face)[ 0 ][0] 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_mobility * face_flow * face_area # self.Q[id_volume] += -RHS self.Q[id_volume, 0] += -RHS id_volumes = [] all_LHS = [] antidiffusive_flux = {} for face in self.dirichlet_faces: face_mobility = self.mb.tag_get_data( self.face_mobility_tag, face )[0][0] # '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 # calc_grad(I, J, K, vol_left, vol_right=none) 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, face_mobility * K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, face_mobility * K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, face_mobility * 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) if id_volume not in antidiffusive_flux.keys(): antidiffusive_flux[id_volume] = [] fluxes = OrderedDict( { I: [g_I, D_JK], J: [g_J, -D_JK + D_JI - K_eq], K: [g_K, -D_JI], } ) antidiffusive_flux[id_volume].append(fluxes) # self.Q[id_volume] += -RHS self.Q[id_volume, 0] += -RHS # self.T_expanded[:len(self.volumes), len(self.volumes):len(self.u)] * self.u[len(self.volumes):] # self.mb.tag_set_data(self.flux_info_tag, face, # [D_JK, D_JI, K_eq, I, J, K, face_area]) i_id = self.expanded_matrix_node_ids[I] j_id = self.expanded_matrix_node_ids[J] k_id = self.expanded_matrix_node_ids[K] # self.T_expanded[i_id, id_volume] = D_JK self.T_expanded[id_volume, i_id] = D_JK # self.T_expanded[j_id, id_volume] = -D_JK + D_JI - K_eq self.T_expanded[id_volume, j_id] = -D_JK + D_JI - K_eq # self.T_expanded[k_id, id_volume] = -D_JI self.T_expanded[id_volume, k_id] = -D_JI self.T_expanded[i_id, i_id] = 1.0 self.T_expanded[j_id, j_id] = 1.0 self.T_expanded[k_id, k_id] = 1.0 all_cols = [] all_rows = [] all_values = [] self.ids = [] self.v_ids = [] self.ivalues = [] for face in self.intern_faces: face_mobility = self.mb.tag_get_data(self.face_mobility_tag, face)[ 0 ][0] 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, face_mobility * K_R, N_IJK) K_R_JI = self.vmv_multiply(N_IJK, face_mobility * K_R, tan_JI) K_R_JK = self.vmv_multiply(N_IJK, face_mobility * 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, face_mobility * K_L, N_IJK) K_L_JI = self.vmv_multiply(N_IJK, face_mobility * K_L, tan_JI) K_L_JK = self.vmv_multiply(N_IJK, face_mobility * 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) 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.T.InsertGlobalValues(self.ids, self.v_ids, self.ivalues) self.T.InsertGlobalValues(id_volumes, id_volumes, all_LHS) self.T.InsertGlobalValues(all_cols, all_rows, all_values) self.T.FillComplete() for i in range(len(self.volumes)): for j in range(len(self.volumes)): if self.T[i][j]: self.T_expanded[i, j] = self.T[i][j] _is, js, values = find(self.T_expanded) self.T_plus[ [i for i, j in zip(_is, js) if i != j], [j for i, j in zip(_is, js) if i != j], ] = np.asarray( [max(0, value) for i, j, value in zip(_is, js, values) if i != j] ) self.T_plus[_is, _is] = -self.T_plus[_is].sum(axis=1).transpose() self.T_minus = self.T_expanded - self.T_plus self.q = self.Q.tocsc() self.u[: len(self.volumes)] = spsolve(self.T_expanded[0: len(self.volumes), 0: len(self.volumes)], self.q) nodes_pressure = self.mb.tag_get_data( self.dirichlet_tag, self.dirichlet_nodes | self.neumann_nodes ) self.u[len(self.volumes):] = nodes_pressure[:, 0] residual = -self.T_minus * self.u self.T_plus_aux = self.T_plus _is, js, _ = find(self.T_plus) print("vai entrar no calculo do residuo") n = 0 self.mb.tag_set_data( self.pressure_tag, self.volumes, self.u[:len(self.volumes)] ) vols = [ self.vol_volumes.get(vol[0]) for vol in self.mb.tag_get_data( self.global_id_tag, self.volumes ) ] tol = np.dot(vols, abs(residual[:len(self.volumes)])) # while np.average(abs(residual[:len(self.volumes)])) > 1e-3: while tol > 1e-3: self.tag_verts_pressure() # its = list( # map(self.compute_vert_pressure, self.nodes_ws.keys()) # ) # import pdb; pdb.set_trace() # bs = {} # for item in its: # for key, value in item.items(): # if bs.get(key): # bs[key] = min(bs.get(key), value) # else: # pass # limiter = {key} # limiters = { # key: value for key, value in list( # map(self.compute_vert_pressure, self.nodes_ws.keys()) # ) # } self.grads = {} for volume in self.volumes: vol_id = self.mb.tag_get_data(self.global_id_tag, volume)[0][0] grad = self.get_grad(volume) self.grads.update({vol_id: {"grad": grad, "vol": volume}}) n += 1 # print("u_i max") self.u_maxs = {} [ self.u_maxs.update({ i: max( 0, self.u[i] + max( [ self.u[j] - self.u[i] for j in self.mb.tag_get_data( self.global_id_tag, self.mtu.get_bridge_adjacencies( self.volumes[i], 0, 3 ) ) if j != i ] ), ) }) for i in range(len(self.volumes)) ] # print("u_i min") self.u_mins = {} [ self.u_mins.update({ i: min( 0, self.u[i] + min( [ self.u[j] - self.u[i] for j in self.mb.tag_get_data( self.global_id_tag, self.mtu.get_bridge_adjacencies( self.volumes[i], 0, 3)) if j != i ] ), ) }) for i in range(len(self.volumes)) ] # print("u_j max") # print(f"Solution: u_max: \ # {max(self.u[:len(self.volumes)])} \ # u_min: {min(self.u[:len(self.volumes)])}") # print("calculo de slope limiter") rows = [] cols = [] alpha_ijs = [] [ ( rows.append(i), cols.append(j), alpha_ijs.append( self.compute_alpha(i, j) ), ) for i, j in zip(_is, js) if i != j ] # print(f"max alpha: {max(alpha_ijs)} min alpha: {min(alpha_ijs)}") # print("vai recalcular T_plus") t0 = time.time() new_vals = [ self.T_plus[i, j] * alpha for i, j, alpha in zip( rows, cols, alpha_ijs ) ] self.T_plus[rows, cols] = new_vals self.T_plus[ range(len(self.u)), range(len(self.u)) ] = self.T_plus.sum(axis=1).transpose() - self.T_plus.diagonal() # print("Refaz o assembly da matry com novos fluxos") self.T_expanded = self.T_minus + self.T_plus # print("calculo do termo fonte") _q = ( -self.T_expanded[: len(self.volumes), len(self.volumes):] * nodes_pressure ) # print("calculo de pressao u") self.u[: len(self.volumes)] = spsolve( self.T_expanded[: len(self.volumes), : len(self.volumes)], _q ) f = self.T_plus * self.u a_omega_u = - self.T_minus * self.u residual = a_omega_u + f tol = np.dot(vols, abs(residual[:len(self.volumes)])) # print(f"res: {np.average(abs(residual[:len(self.volumes)]))}") print(f"res: {tol}") self.mb.tag_set_data( self.pressure_tag, self.volumes, self.u[:len(self.volumes)] ) self.record_data(f'results_crr2.vtk') print("DONE!!!") import pdb; pdb.set_trace()