Esempio n. 1
0
    def get_grad(self, a_volume):
        vol_faces = self.mtu.get_bridge_adjacencies(a_volume, 2, 2)
        vol_nodes = self.mtu.get_bridge_adjacencies(a_volume, 0, 0)
        vol_crds = self.mb.get_coords(vol_nodes)
        vol_crds = np.reshape(vol_crds, ([4, 3]))
        vol_volume = self.mesh_data.get_tetra_volume(vol_crds)
        I, J, K = self.mtu.get_bridge_adjacencies(vol_faces[0], 2, 0)
        L = list(
            set(vol_nodes).difference(
                set(
                    self.mtu.get_bridge_adjacencies(
                        vol_faces[0], 2, 0
                    )
                )
            )
        )
        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.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.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)
        face_area = np.sqrt(np.dot(N_IJK, N_IJK))

        h_L = geo.get_height(N_IJK, LJ)

        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)
        p_L = self.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
        )
        return grad_p
Esempio n. 2
0
    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)
Esempio n. 3
0
    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
Esempio n. 4
0
    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))
Esempio n. 5
0
    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)))
Esempio n. 6
0
    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()