diff --git a/AUTOTEST/machine-tux.sh b/AUTOTEST/machine-tux.sh index eaaad440bc..86357710d9 100755 --- a/AUTOTEST/machine-tux.sh +++ b/AUTOTEST/machine-tux.sh @@ -61,7 +61,7 @@ mv -f check-case.??? $output_dir # Basic build and run tests mo="-j test" -ro="-ams -ij -sstruct -sstructmat -struct -structmat -lobpcg" +ro="-unit -ams -ij -sstruct -sstructmat -struct -structmat -lobpcg" eo="" co="" diff --git a/AUTOTEST/runtests-unit b/AUTOTEST/runtests-unit new file mode 100644 index 0000000000..87563e65d2 --- /dev/null +++ b/AUTOTEST/runtests-unit @@ -0,0 +1 @@ +TEST_unit/*.sh diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index 69b4ba7d30..3ccf5112d0 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -172,8 +172,39 @@ if(BUILD_TESTING) DEPENDS sstruct FAIL_REGULAR_EXPRESSION "Failed" ) + + # Unit tests + add_test(NAME test_unit + COMMAND ${BASH_PROGRAM} -c "\ + ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/runtest.sh \ + -atol ${HYPRE_CHECK_TOL} \ + -mpi \"${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG}\" \ + ${CMAKE_CURRENT_SOURCE_DIR}/TEST_unit/unit.sh && \ + ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/checktest.sh && \ + ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/cleantest.sh" + ) + set_tests_properties(test_unit PROPERTIES + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS test_csr_overlap + FAIL_REGULAR_EXPRESSION "Failed" + ) endif() +# Add unit_tests make target for convenience +add_custom_target(unit_tests + COMMAND ${CMAKE_COMMAND} -E echo "Running unit tests..." + COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/runtest.sh + -atol ${HYPRE_CHECK_TOL} + -mpi "${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG}" + ${CMAKE_CURRENT_SOURCE_DIR}/TEST_unit/unit.sh + COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/checktest.sh + COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/cleantest.sh + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS test_csr_overlap + COMMENT "Running unit tests" + VERBATIM +) + # Optional Fortran-based drivers if(HYPRE_ENABLE_FORTRAN) # Build Fortran wrapper object libraries to be linked into C drivers diff --git a/src/test/TEST_unit/unit.jobs b/src/test/TEST_unit/unit.jobs new file mode 100755 index 0000000000..6d4eef2834 --- /dev/null +++ b/src/test/TEST_unit/unit.jobs @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright (c) 1998 Lawrence Livermore National Security, LLC and other +# HYPRE Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +#============================================================================= +# Unit Test: CSR Overlap Extraction +# Tests various grid configurations and overlap orders +#============================================================================= + +mpirun -np 8 ./test_csr_overlap > unit.out.0 + diff --git a/src/test/TEST_unit/unit.sh b/src/test/TEST_unit/unit.sh new file mode 100755 index 0000000000..ebfade2b36 --- /dev/null +++ b/src/test/TEST_unit/unit.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# Copyright (c) 1998 Lawrence Livermore National Security, LLC and other +# HYPRE Project Developers. See the top-level COPYRIGHT file for details. +# +# SPDX-License-Identifier: (Apache-2.0 OR MIT) + +TNAME=`basename $0 .sh` +RTOL=$1 +ATOL=$2 + +#============================================================================= +# Check that all tests passed +#============================================================================= + +# Find all output files +OUTFILES=$(ls ${TNAME}.out.* 2>/dev/null | sort) + +if [ -z "$OUTFILES" ]; then + echo "No output files found matching ${TNAME}.out.*" >&2 + exit 1 +fi + +# Build mapping from output file to test driver from jobs file +declare -A DRIVER_MAP +if [ -f ${TNAME}.jobs ]; then + while IFS= read -r line; do + # Extract lines like: mpirun -np 8 ./test_csr_overlap > unit.out.0 + if echo "$line" | grep -qE ">\s*${TNAME}\.out\.[0-9]+"; then + DRIVER=$(echo "$line" | grep -oE "\./[a-zA-Z0-9_]+" | sed 's|^\./||') + OUTFILE=$(echo "$line" | grep -oE "${TNAME}\.out\.[0-9]+" | head -1) + if [ -n "$DRIVER" ] && [ -n "$OUTFILE" ]; then + DRIVER_MAP[$OUTFILE]=$DRIVER + fi + fi + done < ${TNAME}.jobs +fi + +# Check each output file for failures +TOTAL_PASSED=0 +TOTAL_FAILED=0 +FAILED_DETAILS="" + +for OUTFILE in $OUTFILES; do + if [ ! -f $OUTFILE ]; then + continue + fi + + # Count PASSED and FAILED messages + PASSED_COUNT=$(grep -c "PASSED" $OUTFILE 2>/dev/null || echo "0") + FAILED_COUNT=$(grep -c "FAILED" $OUTFILE 2>/dev/null || echo "0") + + # Strip whitespace + PASSED_COUNT=$(echo "$PASSED_COUNT" | tr -d '[:space:]') + FAILED_COUNT=$(echo "$FAILED_COUNT" | tr -d '[:space:]') + PASSED_COUNT=${PASSED_COUNT:-0} + FAILED_COUNT=${FAILED_COUNT:-0} + + TOTAL_PASSED=$((TOTAL_PASSED + PASSED_COUNT)) + TOTAL_FAILED=$((TOTAL_FAILED + FAILED_COUNT)) + + if [ "$FAILED_COUNT" -gt 0 ]; then + # Find which test(s) failed in this file + FAILED_TESTS=$(grep "^Test[0-9]" $OUTFILE | grep -v "PASSED" | sed 's/ (.*procs).*//' | sed 's/:.*//') + + # Get test driver for this output file + TEST_DRIVER="${DRIVER_MAP[$OUTFILE]}" + if [ -z "$TEST_DRIVER" ]; then + TEST_DRIVER="Unknown" + fi + + # Add to failed details + if [ -n "$FAILED_TESTS" ]; then + while IFS= read -r test; do + FAILED_DETAILS="${FAILED_DETAILS} - [${TEST_DRIVER}]: ${test}\n" + done <<< "$FAILED_TESTS" + fi + fi +done + +# Report failures if any +if [ "$TOTAL_FAILED" -gt 0 ]; then + echo "Failed test summary:" >&2 + echo -e "$FAILED_DETAILS" | sed '/^$/d' >&2 +fi + +if [ "$TOTAL_PASSED" -eq 0 ] && [ "$TOTAL_FAILED" -eq 0 ]; then + echo "No test results found in output files" >&2 +fi + +# Collect summary output from all output files +{ + for OUTFILE in $OUTFILES; do + if [ -f $OUTFILE ]; then + echo -e "# Output file: $OUTFILE\n" + # Extract test results (lines containing PASSED/FAILED) + grep -E "(PASSED|FAILED|Test[0-9])" $OUTFILE | head -20 + echo "" + fi + done +} > ${TNAME}.out + +# Verify we got results +OUTCOUNT=$(grep -c "PASSED\|FAILED" ${TNAME}.out 2>/dev/null || echo "0") +OUTCOUNT=$(echo "$OUTCOUNT" | tr -d '[:space:]') +OUTCOUNT=${OUTCOUNT:-0} +if [ "$OUTCOUNT" -eq 0 ]; then + echo "No test results found in output files" >&2 +fi + + diff --git a/src/test/test_csr_overlap.c b/src/test/test_csr_overlap.c index 0fb8e5862a..3665a89f85 100644 --- a/src/test/test_csr_overlap.c +++ b/src/test/test_csr_overlap.c @@ -8,16 +8,16 @@ /*-------------------------------------------------------------------------- * Test driver for overlap matrix extraction * - * This test file contains: - * 1. Unit tests for overlap extraction with small hard-coded matrices - * 2. Benchmarking with generated laplacian matrices + * This test file works according to the following modes: + * 0 - Unit tests for overlap extraction with small hard-coded matrices + * 1 - Overlap benchmarking with laplacian matrices + * 2 - Matrix/Matrix product benchmarking with laplacian matrices *--------------------------------------------------------------------------*/ #include #include #include #include -#include #include "HYPRE.h" #include "HYPRE_parcsr_mv.h" @@ -28,2176 +28,498 @@ #define CHECK_TOLERANCE 1.0e-10 /*-------------------------------------------------------------------------- - * Macro to print test result (PASSED/FAILED) on rank 0 + * Macros for test infrastructure *--------------------------------------------------------------------------*/ -#define PRINT_TEST_RESULT(my_id, error) \ +#define PRINT_TEST_RESULT(my_id, error, comm) \ do { \ - if ((my_id) == 0) \ - { \ - if ((error) == 0) \ - { \ - hypre_printf("PASSED\n"); \ - } \ - else \ - { \ - hypre_printf("FAILED\n"); \ - } \ - } \ + HYPRE_Int global_error = 0; \ + hypre_MPI_Allreduce(&(error), &global_error, 1, HYPRE_MPI_INT, hypre_MPI_MAX, comm); \ + if ((my_id) == 0) hypre_printf("%s\n", global_error ? "FAILED" : "PASSED"); \ + (error) = global_error; \ } while (0) +#define TEST_VARS() \ + hypre_ParCSRMatrix *A; hypre_OverlapData *overlap_data; hypre_CSRMatrix *A_local, *A_expected = NULL; \ + HYPRE_BigInt *col_map; HYPRE_Int num_cols_local, error = 0, test_my_id, my_id, num_procs; \ + MPI_Comm test_comm = MPI_COMM_NULL; + +#define TEST_SETUP(min_procs) \ + hypre_MPI_Comm_rank(comm, &my_id); hypre_MPI_Comm_size(comm, &num_procs); \ + if (num_procs >= min_procs) { \ + HYPRE_Int part = (my_id < min_procs) ? 1 : hypre_MPI_UNDEFINED; \ + hypre_MPI_Comm_split(comm, part, my_id, &test_comm); \ + } else { \ + if (my_id == 0) hypre_printf("%s: Skipping (requires at least %d processors)\n", __func__, min_procs); \ + hypre_MPI_Barrier(comm); return 0; \ + } \ + if (test_comm == hypre_MPI_COMM_NULL) { hypre_MPI_Barrier(comm); return 0; } \ + hypre_MPI_Comm_rank(test_comm, &test_my_id); \ + if (test_my_id == 0) hypre_printf("%s (%d procs): ", __func__, min_procs); + +#define TEST_OVERLAP(overlap_order) \ + if (!hypre_ParCSRMatrixCommPkg(A)) hypre_MatvecCommPkgCreate(A); \ + hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); \ + hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); \ + hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); + +#define TEST_CLEANUP() \ + if (A_expected) hypre_CSRMatrixDestroy(A_expected); \ + if (A_local) hypre_CSRMatrixDestroy(A_local); \ + if (col_map) hypre_TFree(col_map, HYPRE_MEMORY_HOST); \ + if (overlap_data) hypre_OverlapDataDestroy(overlap_data); \ + if (A) hypre_ParCSRMatrixDestroy(A); \ + if (test_comm != hypre_MPI_COMM_NULL) { PRINT_TEST_RESULT(test_my_id, error, test_comm); hypre_MPI_Comm_free(&test_comm); } \ + hypre_MPI_Barrier(comm); return error; + +#define TEST_PRINT_MATRICES(tag) \ + if (print_matrices && A_expected) { \ + char filename_expected[256]; \ + char filename_computed[256]; \ + hypre_sprintf(filename_expected, tag "_expected_ij.out.%05d", test_my_id); \ + hypre_sprintf(filename_computed, tag "_computed_ij.out.%05d", test_my_id); \ + hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); \ + hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); \ + } + +#define TEST_COMPARE_MATRICES(tag) \ + if (A_expected) { \ + TEST_PRINT_MATRICES(tag) \ + if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) { \ + hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); error = 1; \ + } } + /*-------------------------------------------------------------------------- - * Helper function to compare two CSR matrices - * Returns 0 if matrices are equal (within tolerance), 1 otherwise - * Uses Frobenius norm of the difference matrix + * Helper: Compare two CSR matrices using Frobenius norm *--------------------------------------------------------------------------*/ static HYPRE_Int CompareCSRMatrices(hypre_CSRMatrix *A, hypre_CSRMatrix *B, HYPRE_Real tol) { - HYPRE_Int num_rows_A = hypre_CSRMatrixNumRows(A); - HYPRE_Int num_cols_A = hypre_CSRMatrixNumCols(A); - HYPRE_Int num_rows_B = hypre_CSRMatrixNumRows(B); - HYPRE_Int num_cols_B = hypre_CSRMatrixNumCols(B); - hypre_CSRMatrix *diff; - HYPRE_Real fnorm_diff, fnorm_A; - HYPRE_Real rel_error; - - /* Check dimensions */ - if (num_rows_A != num_rows_B || num_cols_A != num_cols_B) + if (hypre_CSRMatrixNumRows(A) != hypre_CSRMatrixNumRows(B) || + hypre_CSRMatrixNumCols(A) != hypre_CSRMatrixNumCols(B)) { hypre_printf("Matrix dimensions mismatch: (%d x %d) vs (%d x %d)\n", - num_rows_A, num_cols_A, num_rows_B, num_cols_B); - return 1; - } - - /* Compute difference matrix: diff = A - B */ - diff = hypre_CSRMatrixAdd(1.0, A, -1.0, B); - if (!diff) - { - hypre_printf("Failed to compute difference matrix\n"); + hypre_CSRMatrixNumRows(A), hypre_CSRMatrixNumCols(A), + hypre_CSRMatrixNumRows(B), hypre_CSRMatrixNumCols(B)); return 1; } - - /* Compute Frobenius norm of difference */ - fnorm_diff = hypre_CSRMatrixFnorm(diff); - fnorm_A = hypre_CSRMatrixFnorm(A); - - /* Compute relative error */ - rel_error = (fnorm_A > 0.0) ? (fnorm_diff / fnorm_A) : fnorm_diff; - - /* Cleanup */ + hypre_CSRMatrix *diff = hypre_CSRMatrixAdd(1.0, A, -1.0, B); + if (!diff) { return 1; } + HYPRE_Real fnorm_diff = hypre_CSRMatrixFnorm(diff); + HYPRE_Real fnorm_A = hypre_CSRMatrixFnorm(A); + HYPRE_Real rel_error = (fnorm_A > 0.0) ? (fnorm_diff / fnorm_A) : fnorm_diff; hypre_CSRMatrixDestroy(diff); - - /* Check if relative error is within tolerance */ if (rel_error > tol) { - hypre_printf("Matrix comparison failed: ||A - B||_F / ||A||_F = %e (tolerance = %e)\n", - rel_error, tol); + hypre_printf("Matrix comparison failed: ||A - B||_F / ||A||_F = %e (tolerance = %e)\n", rel_error, + tol); return 1; } - return 0; } /*-------------------------------------------------------------------------- - * Create a CSR matrix from hard-coded values - * num_rows: number of rows - * num_cols: number of columns - * I: row pointer array (length num_rows+1) - * J: column index array (length nnz) - * data: value array (length nnz) + * Helper: Create CSR matrix from arrays *--------------------------------------------------------------------------*/ static hypre_CSRMatrix* -CreateCSRMatrixFromData(HYPRE_Int num_rows, HYPRE_Int num_cols, HYPRE_Int nnz, +CreateCSRMatrixFromData(HYPRE_Int nr, HYPRE_Int nc, HYPRE_Int nnz, HYPRE_Int *I, HYPRE_Int *J, HYPRE_Real *data) { - hypre_CSRMatrix *matrix; - HYPRE_Int i; - - matrix = hypre_CSRMatrixCreate(num_rows, num_cols, nnz); - hypre_CSRMatrixInitialize(matrix); - - /* Copy I array */ - for (i = 0; i <= num_rows; i++) - { - hypre_CSRMatrixI(matrix)[i] = I[i]; - } - - /* Copy J and data arrays */ - for (i = 0; i < nnz; i++) - { - hypre_CSRMatrixJ(matrix)[i] = J[i]; - hypre_CSRMatrixData(matrix)[i] = data[i]; - } - - hypre_CSRMatrixNumNonzeros(matrix) = nnz; - - return matrix; + hypre_CSRMatrix *m = hypre_CSRMatrixCreate(nr, nc, nnz); + hypre_CSRMatrixInitialize(m); + for (HYPRE_Int i = 0; i <= nr; i++) { hypre_CSRMatrixI(m)[i] = I[i]; } + for (HYPRE_Int i = 0; i < nnz; i++) { hypre_CSRMatrixJ(m)[i] = J[i]; hypre_CSRMatrixData(m)[i] = data[i]; } + hypre_CSRMatrixNumNonzeros(m) = nnz; + return m; } /*-------------------------------------------------------------------------- - * Create a simple 1D Laplacian matrix using GenerateLaplacian - * Global size: n, partitioned across num_procs processors (1D partitioning) + * Laplacian matrix creators *--------------------------------------------------------------------------*/ static hypre_ParCSRMatrix* -Create1DLaplacian(MPI_Comm comm, HYPRE_Int n, HYPRE_Int num_procs, HYPRE_Int my_id) +Create1DLaplacian(MPI_Comm comm, HYPRE_Int n, HYPRE_Int np, HYPRE_Int id) { - HYPRE_Real values[4]; - HYPRE_Int p, q, r; - HYPRE_Int P = num_procs, Q = 1, R = 1; - - /* Compute processor coordinates for 1D partitioning */ - p = my_id % P; - q = ((my_id - p) / P) % Q; - r = (my_id - p - P * q) / (P * Q); - - /* Set up 1D stencil values (tridiagonal) */ - values[0] = 2.0; /* diagonal */ - values[1] = -1.0; /* x-direction */ - values[2] = 0.0; /* y-direction (not used) */ - values[3] = 0.0; /* z-direction (not used) */ - - return GenerateLaplacian(comm, n, 1, 1, P, Q, R, p, q, r, values); + HYPRE_Real v[4] = {2.0, -1.0, 0.0, 0.0}; + return GenerateLaplacian(comm, n, 1, 1, np, 1, 1, id % np, 0, 0, v); } -/*-------------------------------------------------------------------------- - * Create a 2D Laplacian matrix using GenerateLaplacian - * Global size: nx x ny, partitioned across num_procs processors (1D partitioning) - *--------------------------------------------------------------------------*/ static hypre_ParCSRMatrix* -Create2DLaplacian(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int num_procs, HYPRE_Int my_id) +Create2DLaplacian(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int np, HYPRE_Int id) { - HYPRE_Real values[4]; - HYPRE_Int p, q, r; - HYPRE_Int P = num_procs, Q = 1, R = 1; - - /* Compute processor coordinates for 1D partitioning */ - p = my_id % P; - q = ((my_id - p) / P) % Q; - r = (my_id - p - P * q) / (P * Q); - - /* Set up 2D 5-point stencil values */ - values[0] = 4.0; /* diagonal */ - values[1] = -1.0; /* x-direction */ - values[2] = -1.0; /* y-direction */ - values[3] = 0.0; /* z-direction (not used) */ - - return GenerateLaplacian(comm, nx, ny, 1, P, Q, R, p, q, r, values); + HYPRE_Real v[4] = {4.0, -1.0, -1.0, 0.0}; + return GenerateLaplacian(comm, nx, ny, 1, np, 1, 1, id % np, 0, 0, v); } -/*-------------------------------------------------------------------------- - * Create a 2D Laplacian matrix using GenerateLaplacian with 2D partitioning - * Global size: nx x ny, partitioned across Px x Py processors (2D partitioning) - *--------------------------------------------------------------------------*/ static hypre_ParCSRMatrix* -Create2DLaplacian2DPart(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, - HYPRE_Int Px, HYPRE_Int Py, HYPRE_Int my_id) +Create2DLaplacian2DPart(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int Px, HYPRE_Int Py, + HYPRE_Int id) { - HYPRE_Real values[4]; - HYPRE_Int p, q, r; - HYPRE_Int P = Px, Q = Py, R = 1; - - /* Compute processor coordinates for 2D partitioning */ - p = my_id % P; - q = ((my_id - p) / P) % Q; - r = (my_id - p - P * q) / (P * Q); - - /* Set up 2D 5-point stencil values */ - values[0] = 4.0; /* diagonal */ - values[1] = -1.0; /* x-direction */ - values[2] = -1.0; /* y-direction */ - values[3] = 0.0; /* z-direction (not used) */ - - return GenerateLaplacian(comm, nx, ny, 1, P, Q, R, p, q, r, values); + HYPRE_Real v[4] = {4.0, -1.0, -1.0, 0.0}; + HYPRE_Int p = id % Px, q = (id / Px) % Py; + return GenerateLaplacian(comm, nx, ny, 1, Px, Py, 1, p, q, 0, v); } -/*-------------------------------------------------------------------------- - * Create a 3D Laplacian matrix using GenerateLaplacian with 3D partitioning - * Global size: nx x ny x nz, partitioned across Px x Py x Pz processors - *--------------------------------------------------------------------------*/ static hypre_ParCSRMatrix* Create3DLaplacian3DPart(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int nz, - HYPRE_Int Px, HYPRE_Int Py, HYPRE_Int Pz, HYPRE_Int my_id) + HYPRE_Int Px, HYPRE_Int Py, HYPRE_Int Pz, HYPRE_Int id) { - HYPRE_Real values[4]; - HYPRE_Int p, q, r; - HYPRE_Int P = Px, Q = Py, R = Pz; - - /* Compute processor coordinates for 3D partitioning */ - p = my_id % P; - q = ((my_id - p) / P) % Q; - r = (my_id - p - P * q) / (P * Q); - - /* Set up 3D 7-point stencil values */ - values[0] = 6.0; /* diagonal */ - values[1] = -1.0; /* x-direction */ - values[2] = -1.0; /* y-direction */ - values[3] = -1.0; /* z-direction */ - - return GenerateLaplacian(comm, nx, ny, nz, P, Q, R, p, q, r, values); + HYPRE_Real v[4] = {6.0, -1.0, -1.0, -1.0}; + HYPRE_Int p = id % Px, q = (id / Px) % Py, r = id / (Px * Py); + return GenerateLaplacian(comm, nx, ny, nz, Px, Py, Pz, p, q, r, v); } /*-------------------------------------------------------------------------- - * Unit test: 1D grid with 1D partitioning, overlap=1 - * Test case: 4x4 matrix on 2 processors + * Unit test: 1D grid with 1D partitioning, overlap=1 (4x4 matrix on 2 procs) *--------------------------------------------------------------------------*/ static HYPRE_Int Test1_Grid1D_Part1D_Overlap1(MPI_Comm comm, HYPRE_Int print_matrices) { - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 1; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 2 processors */ - if (num_procs >= 2) - { - participate = (my_id < 2) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test1_Grid1D_Part1D_Overlap1: Skipping (requires at least 2 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must wait for test to complete */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test1_Grid1D_Part1D_Overlap1 (2 procs): "); - } - - /* Create 4x4 1D Laplacian */ + TEST_VARS() + TEST_SETUP(2) A = Create1DLaplacian(test_comm, 4, 2, test_my_id); - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - - if (test_my_id == 0) - { - /* Proc 0: Extended domain is rows 0,1,2 with columns 0,1,2 - * Global matrix row 0: [2, -1] at columns [0,1] -> [2, -1] at local cols [0,1] - * Global matrix row 1: [-1, 2, -1] at columns [0,1,2] -> [-1, 2, -1] at local cols [0,1,2] - * Global matrix row 2: [-1, 2] at columns [1,2] -> [-1, 2] at local cols [1,2] - * Expected 3x3 matrix: - */ - HYPRE_Int I_expected[4] = {0, 2, 5, 7}; - HYPRE_Int J_expected[7] = {0, 1, /* row 0 (global 0): columns 0,1 (global 0,1) */ - 0, 1, 2, /* row 1 (global 1): columns 0,1,2 (global 0,1,2) */ - 1, 2 /* row 2 (global 2): columns 1,2 (global 1,2) */ - }; - HYPRE_Real data_expected[7] = {2.0, -1.0, /* row 0 */ - -1.0, 2.0, -1.0, /* row 1 */ - -1.0, 2.0 /* row 2 */ - }; - - A_expected = CreateCSRMatrixFromData(3, 3, 7, I_expected, J_expected, data_expected); - } - else if (test_my_id == 1) - { - /* Proc 1: Extended domain is rows 1,2,3 with columns 1,2,3 - * Expected 3x3 matrix: - */ - HYPRE_Int I_expected[4] = {0, 2, 5, 7}; - HYPRE_Int J_expected[7] = {0, 1, /* row 0 (global 1): columns 0,1 (global 1,2) */ - 0, 1, 2, /* row 1 (global 2): columns 0,1,2 (global 1,2,3) */ - 1, 2 /* row 2 (global 3): columns 1,2 (global 2,3) */ - }; - HYPRE_Real data_expected[7] = {2.0, -1.0, /* row 0 */ - -1.0, 2.0, -1.0, /* row 1 */ - -1.0, 2.0 /* row 2 */ - }; - - A_expected = CreateCSRMatrixFromData(3, 3, 7, I_expected, J_expected, data_expected); - } - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test1_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test1_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) - { - hypre_ParCSRMatrixDestroy(A); - } - - if (test_comm != MPI_COMM_NULL) - { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); - } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; + TEST_OVERLAP(1) + + /* 3x3 expected matrices - same for both procs */ + HYPRE_Int I[] = {0, 2, 5, 7}; + HYPRE_Int J[] = {0, 1, 0, 1, 2, 1, 2}; + HYPRE_Real D[] = {2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0}; + A_expected = CreateCSRMatrixFromData(3, 3, 7, I, J, D); + TEST_COMPARE_MATRICES("test1") + TEST_CLEANUP() } /*-------------------------------------------------------------------------- - * Unit test: 1D grid with 1D partitioning, overlap=2 - * Test case: 6x6 matrix on 3 processors + * Unit test: 1D grid with 1D partitioning, overlap=2 (6x6 matrix on 3 procs) *--------------------------------------------------------------------------*/ static HYPRE_Int Test2_Grid1D_Part1D_Overlap2(MPI_Comm comm, HYPRE_Int print_matrices) { - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 2; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 3 processors */ - if (num_procs >= 3) - { - participate = (my_id < 3) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test2_Grid1D_Part1D_Overlap2: Skipping (requires at least 3 processors)\n"); - } - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test2_Grid1D_Part1D_Overlap2 (3 procs): "); - } - - /* Create 6x6 1D Laplacian */ + TEST_VARS() + TEST_SETUP(3) A = Create1DLaplacian(test_comm, 6, 3, test_my_id); + TEST_OVERLAP(2) - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - - if (test_my_id == 0) - { - /* Proc 0: Owns rows 0,1. With overlap=2: - * - 1st hop: gets row 2 (from proc 1) - * - 2nd hop: gets row 3 (via row 2 from proc 1) - * Extended domain: rows 0,1,2,3 with columns 0,1,2,3. - * Expected 4x4 matrix: - */ - HYPRE_Int I_expected[5] = {0, 2, 5, 8, 10}; - HYPRE_Int J_expected[10] = {0, 1, /* row 0 (global 0): columns 0,1 */ - 0, 1, 2, /* row 1 (global 1): columns 0,1,2 */ - 1, 2, 3, /* row 2 (global 2): columns 1,2,3 */ - 2, 3 /* row 3 (global 3): columns 2,3 */ - }; - HYPRE_Real data_expected[10] = {2.0, -1.0, /* row 0 */ - -1.0, 2.0, -1.0, /* row 1 */ - -1.0, 2.0, -1.0, /* row 2 */ - -1.0, 2.0 /* row 3 */ - }; - - A_expected = CreateCSRMatrixFromData(4, 4, 10, I_expected, J_expected, data_expected); - } - else if (test_my_id == 1) - { - /* Proc 1: Owns rows 2,3. With overlap=2, should get rows 0,1 (from proc 0) and rows 4,5 (from proc 2) - * Extended domain (full): rows 0,1,2,3,4,5 with columns 0,1,2,3,4,5. - * Expected 6x6 matrix: - */ - HYPRE_Int I_expected[7] = {0, 2, 5, 8, 11, 14, 16}; - HYPRE_Int J_expected[16] = {0, 1, /* row 0 (global 0): columns 0,1 */ - 0, 1, 2, /* row 1 (global 1): columns 0,1,2 */ - 1, 2, 3, /* row 2 (global 2): columns 1,2,3 */ - 2, 3, 4, /* row 3 (global 3): columns 2,3,4 */ - 3, 4, 5, /* row 4 (global 4): columns 3,4,5 */ - 4, 5 /* row 5 (global 5): columns 4,5 */ - }; - HYPRE_Real data_expected[16] = {2.0, -1.0, /* row 0 */ - -1.0, 2.0, -1.0, /* row 1 */ - -1.0, 2.0, -1.0, /* row 2 */ - -1.0, 2.0, -1.0, /* row 3 */ - -1.0, 2.0, -1.0, /* row 4 */ - -1.0, 2.0 /* row 5 */ - }; - - A_expected = CreateCSRMatrixFromData(6, 6, 16, I_expected, J_expected, data_expected); - } - else if (test_my_id == 2) - { - /* Proc 2: Owns rows 4,5. With overlap=2: - * - 1st hop: gets row 3 (from proc 1) - * - 2nd hop: gets row 2 (via row 3 from proc 1) - * Extended domain: rows 2,3,4,5 with columns 2,3,4,5. - * Expected 4x4 matrix: - */ - HYPRE_Int I_expected[5] = {0, 2, 5, 8, 10}; - HYPRE_Int J_expected[10] = {0, 1, /* row 0 (global 2): columns 0,1 (global 2,3) */ - 0, 1, 2, /* row 1 (global 3): columns 0,1,2 (global 2,3,4) */ - 1, 2, 3, /* row 2 (global 4): columns 1,2,3 (global 3,4,5) */ - 2, 3 /* row 3 (global 5): columns 2,3 (global 4,5) */ - }; - HYPRE_Real data_expected[10] = {2.0, -1.0, /* row 0 */ - -1.0, 2.0, -1.0, /* row 1 */ - -1.0, 2.0, -1.0, /* row 2 */ - -1.0, 2.0 /* row 3 */ - }; - - A_expected = CreateCSRMatrixFromData(4, 4, 10, I_expected, J_expected, data_expected); - } - - if (A_expected) - { - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test2_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test2_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) + if (test_my_id == 0) { - hypre_OverlapDataDestroy(overlap_data); + HYPRE_Int I[] = {0, 2, 5, 8, 10}; + HYPRE_Int J[] = {0, 1, 0, 1, 2, 1, 2, 3, 2, 3}; + HYPRE_Real D[] = {2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0}; + A_expected = CreateCSRMatrixFromData(4, 4, 10, I, J, D); } - if (A) + else if (test_my_id == 1) { - hypre_ParCSRMatrixDestroy(A); + HYPRE_Int I[] = {0, 2, 5, 8, 11, 14, 16}; + HYPRE_Int J[] = {0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5}; + HYPRE_Real D[] = {2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0}; + A_expected = CreateCSRMatrixFromData(6, 6, 16, I, J, D); } - - if (test_comm != MPI_COMM_NULL) + else { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); + HYPRE_Int I[] = {0, 2, 5, 8, 10}; + HYPRE_Int J[] = {0, 1, 0, 1, 2, 1, 2, 3, 2, 3}; + HYPRE_Real D[] = {2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0}; + A_expected = CreateCSRMatrixFromData(4, 4, 10, I, J, D); } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; + TEST_COMPARE_MATRICES("test2") + TEST_CLEANUP() } /*-------------------------------------------------------------------------- - * Unit test: 1D grid with 1D partitioning, overlap=8 - * Test case: 8x8 matrix on 4 processors - * With overlap=8, each processor should gather the entire global matrix + * Unit test: 1D grid with 1D partitioning, overlap=8 (full gather, 8x8 on 4 procs) *--------------------------------------------------------------------------*/ static HYPRE_Int Test3_Grid1D_Part1D_Overlap8(MPI_Comm comm, HYPRE_Int print_matrices) { - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 8; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 4 processors */ - if (num_procs >= 4) - { - participate = (my_id < 4) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test3_Grid1D_Part1D_Overlap8: Skipping (requires at least 4 processors)\n"); - } - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test3_Grid1D_Part1D_Overlap8 (4 procs): "); - } - - /* Create 8x8 1D Laplacian */ + TEST_VARS() + TEST_SETUP(4) A = Create1DLaplacian(test_comm, 8, 4, test_my_id); + TEST_OVERLAP(8) + + HYPRE_Int I[] = {0, 2, 5, 8, 11, 14, 17, 20, 22}; + HYPRE_Int J[] = {0, 1, 0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6, 5, 6, 7, 6, 7}; + HYPRE_Real D[] = {2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0, -1.0, -1.0, 2.0}; + A_expected = CreateCSRMatrixFromData(8, 8, 22, I, J, D); + if (hypre_OverlapDataNumExtendedRows(overlap_data) != 8) { hypre_printf("Proc %d: Expected 8 extended rows, got %d\n", test_my_id, hypre_OverlapDataNumExtendedRows(overlap_data)); error = 1; } + TEST_COMPARE_MATRICES("test3") + TEST_CLEANUP() +} - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix - with overlap=8, all processors should have the full 8x8 matrix */ - { - hypre_CSRMatrix *A_expected = NULL; - HYPRE_Int num_extended = hypre_OverlapDataNumExtendedRows(overlap_data); - - /* Expected: full 8x8 matrix for all processors */ - HYPRE_Int I_expected[9] = {0, 2, 5, 8, 11, 14, 17, 20, 22}; - HYPRE_Int J_expected[22] = {0, 1, /* row 0: columns 0,1 */ - 0, 1, 2, /* row 1: columns 0,1,2 */ - 1, 2, 3, /* row 2: columns 1,2,3 */ - 2, 3, 4, /* row 3: columns 2,3,4 */ - 3, 4, 5, /* row 4: columns 3,4,5 */ - 4, 5, 6, /* row 5: columns 4,5,6 */ - 5, 6, 7, /* row 6: columns 5,6,7 */ - 6, 7 /* row 7: columns 6,7 */ - }; - HYPRE_Real data_expected[22] = {2.0, -1.0, /* row 0 */ - -1.0, 2.0, -1.0, /* row 1 */ - -1.0, 2.0, -1.0, /* row 2 */ - -1.0, 2.0, -1.0, /* row 3 */ - -1.0, 2.0, -1.0, /* row 4 */ - -1.0, 2.0, -1.0, /* row 5 */ - -1.0, 2.0, -1.0, /* row 6 */ - -1.0, 2.0 /* row 7 */ - }; - - A_expected = CreateCSRMatrixFromData(8, 8, 22, I_expected, J_expected, data_expected); - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test3_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test3_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - - /* Verify that we got all 8 rows */ - if (num_extended != 8) - { - hypre_printf("Proc %d: Expected 8 extended rows, got %d\n", test_my_id, num_extended); - error = 1; - } +/*-------------------------------------------------------------------------- + * Unit test: 2D grid with 1D partitioning, overlap=2 (4x4 grid on 2 procs) + *--------------------------------------------------------------------------*/ +static HYPRE_Int +Test4_Grid2D_Part1D_Overlap2(MPI_Comm comm, HYPRE_Int print_matrices) +{ + TEST_VARS() + TEST_SETUP(2) + A = Create2DLaplacian(test_comm, 4, 4, 2, test_my_id); + TEST_OVERLAP(2) + + HYPRE_Int I[] = {0, 3, 7, 11, 16, 20, 25, 28, 32, 36, 39, 44, 48, 53, 57, 61, 64}; + HYPRE_Int J[] = {0, 1, 2, 1, 0, 3, 8, 2, 0, 3, 4, 3, 1, 2, 5, 10, 4, 2, 5, 6, 5, 3, 4, 7, 12, 6, 4, 7, 7, 5, 6, 14, 8, 1, 9, 10, 9, 8, 11, 10, 3, 8, 11, 12, 11, 9, 10, 13, 12, 5, 10, 13, 14, 13, 11, 12, 15, 14, 7, 12, 15, 15, 13, 14}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0}; + A_expected = CreateCSRMatrixFromData(16, 16, 64, I, J, D); + TEST_COMPARE_MATRICES("test4") + TEST_CLEANUP() +} - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } +/*-------------------------------------------------------------------------- + * Unit test: 2D grid with 2D partitioning, overlap=1 (4x4 grid on 2x2 procs) + *--------------------------------------------------------------------------*/ +static HYPRE_Int +Test5_Grid2D_Part2D_Overlap1(MPI_Comm comm, HYPRE_Int print_matrices) +{ + TEST_VARS() + TEST_SETUP(4) + A = Create2DLaplacian2DPart(test_comm, 4, 4, 2, 2, test_my_id); + TEST_OVERLAP(1) - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) + if (test_my_id == 0) { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); + HYPRE_Int I[] = {0, 3, 7, 11, 16, 19, 22, 25, 28}; + HYPRE_Int J[] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 6, 1, 2, 3, 5, 7, 1, 4, 5, 3, 4, 5, 2, 6, 7, 3, 6, 7}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(8, 8, 28, I, J, D); } - if (overlap_data) + else if (test_my_id == 1) { - hypre_OverlapDataDestroy(overlap_data); + HYPRE_Int I[] = {0, 3, 6, 10, 13, 18, 22, 25, 28}; + HYPRE_Int J[] = {0, 1, 2, 0, 1, 4, 0, 2, 3, 4, 2, 3, 5, 1, 2, 4, 5, 6, 3, 4, 5, 7, 4, 6, 7, 5, 6, 7}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(8, 8, 28, I, J, D); } - if (A) + else if (test_my_id == 2) { - hypre_ParCSRMatrixDestroy(A); + HYPRE_Int I[] = {0, 3, 6, 10, 15, 18, 22, 25, 28}; + HYPRE_Int J[] = {0, 1, 2, 0, 1, 3, 0, 2, 3, 4, 1, 2, 3, 5, 6, 2, 4, 5, 3, 4, 5, 7, 3, 6, 7, 5, 6, 7}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(8, 8, 28, I, J, D); } - - if (test_comm != MPI_COMM_NULL) + else { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); + HYPRE_Int I[] = {0, 3, 6, 9, 12, 17, 21, 25, 28}; + HYPRE_Int J[] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 6, 0, 2, 4, 5, 6, 1, 4, 5, 7, 3, 4, 6, 7, 5, 6, 7}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(8, 8, 28, I, J, D); } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; + TEST_COMPARE_MATRICES("test5") + TEST_CLEANUP() } /*-------------------------------------------------------------------------- - * Unit test: 2D grid with 1D partitioning, overlap=2 - * Test case: 4x4 2D grid on 2 processors - * Tests overlap extraction for 2D problem with 1D processor layout + * Unit test: 2D grid with 2D partitioning, overlap=2 (4x4 grid on 2x2 procs) *--------------------------------------------------------------------------*/ static HYPRE_Int -Test4_Grid2D_Part1D_Overlap2(MPI_Comm comm, HYPRE_Int print_matrices) +Test6_Grid2D_Part2D_Overlap2(MPI_Comm comm, HYPRE_Int print_matrices) { - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 2; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 2 processors */ - if (num_procs >= 2) - { - participate = (my_id < 2) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test4_Grid2D_Part1D_Overlap2: Skipping (requires at least 2 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test4_Grid2D_Part1D_Overlap2 (2 procs): "); - } - - /* Create 4x4 2D Laplacian with 1D partitioning */ - A = Create2DLaplacian(test_comm, 4, 4, 2, test_my_id); - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - HYPRE_Int num_extended = hypre_OverlapDataNumExtendedRows(overlap_data); - - /* With overlap=2 on a 4x4 grid, both processors get the full 16x16 matrix */ - /* 2D 5-point stencil structure for 4x4 grid (row-major ordering) */ - HYPRE_Int I_expected[17] = {0, 3, 7, 11, 16, 20, 25, 28, 32, 36, 39, 44, 48, 53, 57, 61, 64}; - HYPRE_Int J_expected[64] = - { - 0, 1, 2, /* row 0 */ - 1, 0, 3, 8, /* row 1 */ - 2, 0, 3, 4, /* row 2 */ - 3, 1, 2, 5, 10, /* row 3 */ - 4, 2, 5, 6, /* row 4 */ - 5, 3, 4, 7, 12, /* row 5 */ - 6, 4, 7, /* row 6 */ - 7, 5, 6, 14, /* row 7 */ - 8, 1, 9, 10, /* row 8 */ - 9, 8, 11, /* row 9 */ - 10, 3, 8, 11, 12, /* row 10 */ - 11, 9, 10, 13, /* row 11 */ - 12, 5, 10, 13, 14, /* row 12 */ - 13, 11, 12, 15, /* row 13 */ - 14, 7, 12, 15, /* row 14 */ - 15, 13, 14 /* row 15 */ - }; - HYPRE_Real data_expected[64] = - { - 4.0, -1.0, -1.0, /* row 0 */ - 4.0, -1.0, -1.0, -1.0, /* row 1 */ - 4.0, -1.0, -1.0, -1.0, /* row 2 */ - 4.0, -1.0, -1.0, -1.0, -1.0, /* row 3 */ - 4.0, -1.0, -1.0, -1.0, /* row 4 */ - 4.0, -1.0, -1.0, -1.0, -1.0, /* row 5 */ - 4.0, -1.0, -1.0, /* row 6 */ - 4.0, -1.0, -1.0, -1.0, /* row 7 */ - 4.0, -1.0, -1.0, -1.0, /* row 8 */ - 4.0, -1.0, -1.0, /* row 9 */ - 4.0, -1.0, -1.0, -1.0, -1.0, /* row 10 */ - 4.0, -1.0, -1.0, -1.0, /* row 11 */ - 4.0, -1.0, -1.0, -1.0, -1.0, /* row 12 */ - 4.0, -1.0, -1.0, -1.0, /* row 13 */ - 4.0, -1.0, -1.0, -1.0, /* row 14 */ - 4.0, -1.0, -1.0 /* row 15 */ - }; - - A_expected = CreateCSRMatrixFromData(16, 16, 64, I_expected, J_expected, data_expected); - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test4_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test4_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) - { - hypre_ParCSRMatrixDestroy(A); - } - - if (test_comm != MPI_COMM_NULL) - { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); - } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; -} - -/*-------------------------------------------------------------------------- - * Unit test: 2D grid with 2D partitioning, overlap=2 - * Test case: 4x4 2D grid on 2x2 processor grid (4 processors) - * Tests overlap extraction for 2D problem with 2D processor layout - *--------------------------------------------------------------------------*/ -static HYPRE_Int -Test5_Grid2D_Part2D_Overlap1(MPI_Comm comm, HYPRE_Int print_matrices) -{ - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 1; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 4 processors */ - if (num_procs >= 4) - { - participate = (my_id < 4) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test5_Grid2D_Part2D_Overlap2: Skipping (requires at least 4 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test5_Grid2D_Part2D_Overlap1 (4 procs): "); - } - - /* Create 4x4 2D Laplacian with 2x2 processor partitioning */ - A = Create2DLaplacian2DPart(test_comm, 4, 4, 2, 2, test_my_id); - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - - if (!A_local) - { - hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); - error = 1; - } - else - { - HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); - HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); - - /* Expected matrices (8x8) for each process */ - if (num_rows_local == 8 && num_cols_local_actual == 8) - { - if (test_my_id == 0) - { - HYPRE_Int I_expected[9] = {0, 3, 7, 11, 16, 19, 22, 25, 28}; - HYPRE_Int J_expected[28] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 6, 1, 2, 3, 5, 7, 1, 4, 5, 3, 4, 5, 2, 6, 7, 3, 6, 7}; - HYPRE_Real data_expected[28] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(8, 8, 28, I_expected, J_expected, data_expected); - } - else if (test_my_id == 1) - { - HYPRE_Int I_expected[9] = {0, 3, 6, 10, 13, 18, 22, 25, 28}; - HYPRE_Int J_expected[28] = {0, 1, 2, 0, 1, 4, 0, 2, 3, 4, 2, 3, 5, 1, 2, 4, 5, 6, 3, 4, 5, 7, 4, 6, 7, 5, 6, 7}; - HYPRE_Real data_expected[28] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(8, 8, 28, I_expected, J_expected, data_expected); - } - else if (test_my_id == 2) - { - HYPRE_Int I_expected[9] = {0, 3, 6, 10, 15, 18, 22, 25, 28}; - HYPRE_Int J_expected[28] = {0, 1, 2, 0, 1, 3, 0, 2, 3, 4, 1, 2, 3, 5, 6, 2, 4, 5, 3, 4, 5, 7, 3, 6, 7, 5, 6, 7}; - HYPRE_Real data_expected[28] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(8, 8, 28, I_expected, J_expected, data_expected); - } - else if (test_my_id == 3) - { - HYPRE_Int I_expected[9] = {0, 3, 6, 9, 12, 17, 21, 25, 28}; - HYPRE_Int J_expected[28] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 6, 0, 2, 4, 5, 6, 1, 4, 5, 7, 3, 4, 6, 7, 5, 6, 7}; - HYPRE_Real data_expected[28] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(8, 8, 28, I_expected, J_expected, data_expected); - } - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 8 x 8)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - A_expected = NULL; - } - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test5_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test5_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) - { - hypre_ParCSRMatrixDestroy(A); - } - - if (test_comm != MPI_COMM_NULL) - { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); - } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; -} - -/*-------------------------------------------------------------------------- - * Unit test: 2D grid with 2D partitioning, overlap=2 - * Test case: 4x4 2D grid on 2x2 processor grid (4 processors) - * Tests overlap extraction for 2D problem with 2D processor layout and overlap=2 - *--------------------------------------------------------------------------*/ -static HYPRE_Int -Test6_Grid2D_Part2D_Overlap2(MPI_Comm comm, HYPRE_Int print_matrices) -{ - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 2; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 4 processors */ - if (num_procs >= 4) - { - participate = (my_id < 4) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test6_Grid2D_Part2D_Overlap2: Skipping (requires at least 4 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test6_Grid2D_Part2D_Overlap2 (4 procs): "); - } - - /* Create 4x4 2D Laplacian with 2x2 processor partitioning */ - { - A = Create2DLaplacian2DPart(test_comm, 4, 4, 2, 2, test_my_id); - } - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - - if (!A_local) - { - hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); - error = 1; - } - else - { - HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); - HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); - - /* Hard-coded expected matrices from test6_expected_csr.out files (13x13 matrices) */ - if (num_rows_local == 13 && num_cols_local_actual == 13) - { - if (test_my_id == 0) - { - HYPRE_Int I_expected[14] = {0, 3, 7, 11, 16, 20, 23, 28, 31, 35, 40, 43, 46, 49}; - HYPRE_Int J_expected[49] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 8, 1, 2, 3, 6, 9, 1, 4, - 5, 6, 4, 5, 7, 3, 4, 6, 7, 12, 5, 6, 7, 2, 8, 9, 10, 3, - 8, 9, 11, 12, 8, 10, 11, 9, 10, 11, 6, 9, 12 - }; - HYPRE_Real data_expected[49] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - 4.0 - }; - A_expected = CreateCSRMatrixFromData(13, 13, 49, I_expected, J_expected, data_expected); - } - else if (test_my_id == 1) - { - HYPRE_Int I_expected[14] = {0, 3, 7, 10, 15, 19, 22, 27, 31, 34, 39, 43, 46, 49}; - HYPRE_Int J_expected[49] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 1, 2, 3, 6, 8, 1, 4, - 5, 6, 4, 5, 7, 3, 4, 6, 7, 9, 5, 6, 7, 10, 3, 8, 9, - 6, 8, 9, 10, 11, 7, 9, 10, 12, 9, 11, 12, 10, 11, 12 - }; - HYPRE_Real data_expected[49] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0 - }; - A_expected = CreateCSRMatrixFromData(13, 13, 49, I_expected, J_expected, data_expected); - } - else if (test_my_id == 2) - { - HYPRE_Int I_expected[14] = {0, 3, 6, 10, 15, 18, 22, 27, 30, 34, 39, 42, 46, 49}; - HYPRE_Int J_expected[49] = {0, 1, 2, 0, 1, 3, 0, 2, 3, 5, 1, 2, 3, 4, 6, 3, 4, - 9, 2, 5, 6, 7, 3, 5, 6, 8, 9, 5, 7, 8, 6, 7, 8, 11, - 4, 6, 9, 10, 11, 9, 10, 12, 8, 9, 11, 12, 10, 11, 12 - }; - HYPRE_Real data_expected[49] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0 - }; - A_expected = CreateCSRMatrixFromData(13, 13, 49, I_expected, J_expected, data_expected); - } - else if (test_my_id == 3) - { - HYPRE_Int I_expected[14] = {0, 3, 6, 9, 14, 18, 21, 26, 29, 33, 38, 42, 46, 49}; - HYPRE_Int J_expected[49] = {0, 3, 6, 1, 2, 3, 1, 2, 4, 0, 1, 3, 4, 9, 2, 3, 4, - 10, 5, 6, 7, 0, 5, 6, 8, 9, 5, 7, 8, 6, 7, 8, 11, 3, - 6, 9, 10, 11, 4, 9, 10, 12, 8, 9, 11, 12, 10, 11, 12 - }; - HYPRE_Real data_expected[49] = - { - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, 4.0, -1.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0 - }; - A_expected = CreateCSRMatrixFromData(13, 13, 49, I_expected, J_expected, data_expected); - } - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 13 x 13)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - A_expected = NULL; - } - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test6_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test6_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) - { - hypre_ParCSRMatrixDestroy(A); - } - - if (test_comm != MPI_COMM_NULL) - { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); - } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; -} - -/*-------------------------------------------------------------------------- - * Unit test: 2D grid with 2D partitioning, overlap=3 - * Test case: 4x4 2D grid on 2x2 processor grid (4 processors) - * Tests overlap extraction for 2D problem with 2D processor layout and overlap=3 - *--------------------------------------------------------------------------*/ -static HYPRE_Int -Test7_Grid2D_Part2D_Overlap3(MPI_Comm comm, HYPRE_Int print_matrices) -{ - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 3; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 4 processors */ - if (num_procs >= 4) - { - participate = (my_id < 4) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test7_Grid2D_Part2D_Overlap3: Skipping (requires at least 4 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test7_Grid2D_Part2D_Overlap3 (4 procs): "); - } - - /* Create 4x4 2D Laplacian with 2x2 processor partitioning */ + TEST_VARS() + TEST_SETUP(4) A = Create2DLaplacian2DPart(test_comm, 4, 4, 2, 2, test_my_id); - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap (external) matrix */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - - if (!A_local) - { - hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); - error = 1; - } - else - { - HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); - HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); - - /* Hard-coded expected matrices from test7_expected_csr.out files (15x15 matrices) */ - if (num_rows_local == 15 && num_cols_local_actual == 15) - { - if (test_my_id == 0) - { - HYPRE_Int I_expected[16] = {0, 3, 7, 11, 16, 20, 23, 28, 32, 36, 41, 44, 48, 53, 56, 59}; - HYPRE_Int J_expected[59] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 8, 1, 2, 3, 6, 9, 1, 4, 5, 6, 4, 5, - 7, 3, 4, 6, 7, 12, 5, 6, 7, 13, 2, 8, 9, 10, 3, 8, 9, 11, 12, 8, 10, - 11, 9, 10, 11, 14, 6, 9, 12, 13, 14, 7, 12, 13, 11, 12, 14 - }; - HYPRE_Real data_expected[59] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, -1.0, 4.0, - -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(15, 15, 59, I_expected, J_expected, data_expected); - } - else if (test_my_id == 1) - { - HYPRE_Int I_expected[16] = {0, 3, 7, 11, 16, 20, 23, 28, 32, 35, 40, 43, 48, 52, 56, 59}; - HYPRE_Int J_expected[59] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 8, 1, 2, 3, 6, 9, 1, 4, 5, 6, 4, 5, - 7, 3, 4, 6, 7, 11, 5, 6, 7, 12, 2, 8, 9, 3, 8, 9, 10, 11, 9, 10, 13, - 6, 9, 11, 12, 13, 7, 11, 12, 14, 10, 11, 13, 14, 12, 13, 14 - }; - HYPRE_Real data_expected[59] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(15, 15, 59, I_expected, J_expected, data_expected); - } - else if (test_my_id == 2) - { - HYPRE_Int I_expected[16] = {0, 3, 7, 11, 16, 19, 24, 27, 31, 36, 39, 43, 48, 52, 56, 59}; - HYPRE_Int J_expected[59] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 7, 1, 2, 3, 5, 8, 1, 4, 5, 3, 4, 5, - 6, 11, 5, 6, 12, 2, 7, 8, 9, 3, 7, 8, 10, 11, 7, 9, 10, 8, 9, 10, - 13, 5, 8, 11, 12, 13, 6, 11, 12, 14, 10, 11, 13, 14, 12, 13, 14 - }; - HYPRE_Real data_expected[59] = - { - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(15, 15, 59, I_expected, J_expected, data_expected); - } - else if (test_my_id == 3) - { - HYPRE_Int I_expected[16] = {0, 3, 6, 11, 15, 18, 23, 27, 31, 36, 39, 43, 48, 52, 56, 59}; - HYPRE_Int J_expected[59] = {0, 2, 3, 1, 2, 7, 0, 1, 2, 5, 8, 0, 3, 4, 5, 3, 4, 6, 2, 3, 5, - 6, 11, 4, 5, 6, 12, 1, 7, 8, 9, 2, 7, 8, 10, 11, 7, 9, 10, 8, 9, - 10, 13, 5, 8, 11, 12, 13, 6, 11, 12, 14, 10, 11, 13, 14, 12, 13, 14 - }; - HYPRE_Real data_expected[59] = - { - 4.0, -1.0, -1.0, 4.0, - -1.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - 4.0, -1.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, 4.0, -1.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0, -1.0, - -1.0, -1.0, 4.0 - }; - A_expected = CreateCSRMatrixFromData(15, 15, 59, I_expected, J_expected, data_expected); - } - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 15 x 15)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - A_expected = NULL; - } - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test7_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test7_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) - { - hypre_ParCSRMatrixDestroy(A); - } - - if (test_comm != MPI_COMM_NULL) - { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); - } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; -} - -/*-------------------------------------------------------------------------- - * Unit test: 3D grid with 3D partitioning, overlap=1 - * Test case: 3x3x3 3D grid on 2x2x2 processor grid (8 processors) - * Tests overlap extraction for 3D problem with 3D processor layout and overlap=1 - *--------------------------------------------------------------------------*/ -static HYPRE_Int -Test8_Grid3D_Part3D_Overlap1(MPI_Comm comm, HYPRE_Int print_matrices) -{ - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 1; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 8 processors */ - if (num_procs >= 8) - { - participate = (my_id < 8) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else - { - if (my_id == 0) - { - hypre_printf("Test8_Grid3D_Part3D_Overlap1: Skipping (requires at least 8 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; - } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) - { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; - } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) - { - hypre_printf("Test8_Grid3D_Part3D_Overlap1 (8 procs): "); - } - - /* Create 3x3x3 3D Laplacian with 2x2x2 processor partitioning */ - A = Create3DLaplacian3DPart(test_comm, 3, 3, 3, 2, 2, 2, test_my_id); - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) - { - hypre_MatvecCommPkgCreate(A); - } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap rows */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); - - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); - - /* Create expected matrix and compare */ - { - hypre_CSRMatrix *A_expected = NULL; - HYPRE_Int test_my_id; - hypre_MPI_Comm_rank(test_comm, &test_my_id); - - if (!A_local) - { - hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); - error = 1; - } - else - { - HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); - HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); - - /* Hard-coded expected matrices from test8_expected_csr.out files */ - if (test_my_id == 0) - { - /* 20x20, nnz=92 */ - if (num_rows_local == 20 && num_cols_local_actual == 20) - { - HYPRE_Int I_expected[21] = {0, 4, 9, 14, 20, 25, 31, 37, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92}; - HYPRE_Int J_expected[92] = {0, 1, 2, 4, 0, 1, 3, 5, 8, 0, 2, 3, 6, 12, 1, 2, 3, 7, 9, 13, - 0, 4, 5, 6, 16, 1, 4, 5, 7, 10, 17, 2, 4, 6, 7, 14, 18, 3, 5, - 6, 7, 11, 15, 19, 1, 8, 9, 10, 3, 8, 9, 11, 5, 8, 10, 11, 7, 9, - 10, 11, 2, 12, 13, 14, 3, 12, 13, 15, 6, 12, 14, 15, 7, 13, 14, - 15, 4, 16, 17, 18, 5, 16, 17, 19, 6, 16, 18, 19, 7, 17, 18, 19 - }; - HYPRE_Real data_expected[92] = - { - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(20, 20, 92, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 20 x 20)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 1) - { - /* 12x12, nnz=48 */ - if (num_rows_local == 12 && num_cols_local_actual == 12) - { - HYPRE_Int I_expected[13] = {0, 4, 8, 12, 16, 20, 25, 30, 36, 39, 42, 45, 48}; - HYPRE_Int J_expected[48] = {0, 1, 2, 4, 0, 1, 3, 5, 0, 2, 3, 6, 1, 2, 3, 7, 0, 4, 5, 6, - 1, 4, 5, 7, 8, 2, 4, 6, 7, 10, 3, 5, 6, 7, 9, 11, 5, 8, 9, - 7, 8, 9, 6, 10, 11, 7, 10, 11 - }; - HYPRE_Real data_expected[48] = - { - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, 6.0, - -1.0, -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(12, 12, 48, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 12 x 12)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 2) - { - /* 12x12, nnz=48 */ - if (num_rows_local == 12 && num_cols_local_actual == 12) - { - HYPRE_Int I_expected[13] = {0, 4, 8, 12, 16, 20, 25, 30, 36, 39, 42, 45, 48}; - HYPRE_Int J_expected[48] = {0, 1, 2, 4, 0, 1, 3, 5, 0, 2, 3, 6, 1, 2, 3, 7, - 0, 4, 5, 6, 1, 4, 5, 7, 8, 2, 4, 6, 7, 10, 3, 5, - 6, 7, 9, 11, 5, 8, 9, 7, 8, 9, 6, 10, 11, 7, 10, 11 - }; - HYPRE_Real data_expected[48] = - { - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, 6.0, - -1.0, -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(12, 12, 48, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 12 x 12)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 3) - { - /* 7x7, nnz=23 */ - if (num_rows_local == 7 && num_cols_local_actual == 7) - { - HYPRE_Int I_expected[8] = {0, 3, 6, 9, 12, 16, 21, 23}; - HYPRE_Int J_expected[23] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 5, 0, 2, 4, 5, 1, 3, 4, 5, 6, 5, 6}; - HYPRE_Real data_expected[23] = - { - 6.0, -1.0, -1.0, -1.0, - 6.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(7, 7, 23, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 7 x 7)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 4) - { - /* 12x12, nnz=48 */ - if (num_rows_local == 12 && num_cols_local_actual == 12) - { - HYPRE_Int I_expected[13] = {0, 4, 8, 12, 16, 20, 25, 30, 36, 39, 42, 45, 48}; - HYPRE_Int J_expected[48] = {0, 1, 2, 4, 0, 1, 3, 5, 0, 2, 3, 6, 1, 2, 3, 7, - 0, 4, 5, 6, 1, 4, 5, 7, 8, 2, 4, 6, 7, 10, 3, 5, - 6, 7, 9, 11, 5, 8, 9, 7, 8, 9, 6, 10, 11, 7, 10, 11 - }; - HYPRE_Real data_expected[48] = - { - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, 6.0, - -1.0, -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(12, 12, 48, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 12 x 12)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 5) - { - /* 7x7, nnz=23 */ - if (num_rows_local == 7 && num_cols_local_actual == 7) - { - HYPRE_Int I_expected[8] = {0, 3, 6, 9, 12, 16, 21, 23}; - HYPRE_Int J_expected[23] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 5, - 0, 2, 4, 5, 1, 3, 4, 5, 6, 5, 6 - }; - HYPRE_Real data_expected[23] = - { - 6.0, -1.0, -1.0, -1.0, - 6.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(7, 7, 23, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 7 x 7)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 6) - { - /* 7x7, nnz=23 */ - if (num_rows_local == 7 && num_cols_local_actual == 7) - { - HYPRE_Int I_expected[8] = {0, 3, 6, 9, 12, 16, 21, 23}; - HYPRE_Int J_expected[23] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 5, - 0, 2, 4, 5, 1, 3, 4, 5, 6, 5, 6 - }; - HYPRE_Real data_expected[23] = - { - 6.0, -1.0, -1.0, -1.0, - 6.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(7, 7, 23, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 7 x 7)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else if (test_my_id == 7) - { - /* 4x4, nnz=10 */ - if (num_rows_local == 4 && num_cols_local_actual == 4) - { - HYPRE_Int I_expected[5] = {0, 2, 4, 6, 10}; - HYPRE_Int J_expected[10] = {0, 3, 1, 3, 2, 3, 0, 1, 2, 3}; - HYPRE_Real data_expected[10] = - { - 6.0, -1.0, 6.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(4, 4, 10, I_expected, J_expected, data_expected); - } - else - { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 4 x 4)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - } - } - else - { - hypre_printf("Proc %d: Unexpected processor ID (expected 0-7)\n", test_my_id); - error = 1; - A_expected = NULL; - } - - if (A_expected) - { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test8_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test8_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); - } - } - } - - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) - { - hypre_ParCSRMatrixDestroy(A); - } - - if (test_comm != MPI_COMM_NULL) - { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); - } - - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; -} - -/*-------------------------------------------------------------------------- - * Unit test: 3D grid with 3D partitioning, overlap=6 (full domain coverage) - * Test case: 3x3x3 3D grid on 2x2x2 processor grid (8 processors) - * Tests overlap extraction for 3D problem with 3D processor layout and overlap=6 - * With overlap=6, all processors should have the full global matrix (27x27) - *--------------------------------------------------------------------------*/ -static HYPRE_Int -Test9_Grid3D_Part3D_Overlap6(MPI_Comm comm, HYPRE_Int print_matrices) -{ - hypre_ParCSRMatrix *A; - hypre_OverlapData *overlap_data; - hypre_CSRMatrix *A_local; - HYPRE_BigInt *col_map; - HYPRE_Int num_cols_local; - HYPRE_Int error = 0; - HYPRE_Int overlap_order = 6; - HYPRE_Int test_my_id, my_id, num_procs; - MPI_Comm test_comm = MPI_COMM_NULL; - HYPRE_Int participate = 0; - - hypre_MPI_Comm_rank(comm, &my_id); - hypre_MPI_Comm_size(comm, &num_procs); - - /* Create subcommunicator with first 8 processors */ - if (num_procs >= 8) - { - participate = (my_id < 8) ? 1 : hypre_MPI_UNDEFINED; - hypre_MPI_Comm_split(comm, participate, my_id, &test_comm); - } - else + TEST_OVERLAP(2) + + if (test_my_id == 0) { - if (my_id == 0) - { - hypre_printf("Test9_Grid3D_Part3D_Overlap6: Skipping (requires at least 8 processors)\n"); - } - hypre_MPI_Barrier(comm); - return 0; + HYPRE_Int I[] = {0, 3, 7, 11, 16, 20, 23, 28, 31, 35, 40, 43, 46, 49}; + HYPRE_Int J[] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 8, 1, 2, 3, 6, 9, 1, 4, 5, 6, 4, 5, 7, 3, 4, 6, 7, 12, 5, 6, 7, 2, 8, 9, 10, 3, 8, 9, 11, 12, 8, 10, 11, 9, 10, 11, 6, 9, 12}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(13, 13, 49, I, J, D); } - - /* Only participating processes run the test */ - if (test_comm == MPI_COMM_NULL) + else if (test_my_id == 1) { - /* Non-participating processes must still synchronize */ - hypre_MPI_Barrier(comm); - return 0; + HYPRE_Int I[] = {0, 3, 7, 10, 15, 19, 22, 27, 31, 34, 39, 43, 46, 49}; + HYPRE_Int J[] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 1, 2, 3, 6, 8, 1, 4, 5, 6, 4, 5, 7, 3, 4, 6, 7, 9, 5, 6, 7, 10, 3, 8, 9, 6, 8, 9, 10, 11, 7, 9, 10, 12, 9, 11, 12, 10, 11, 12}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(13, 13, 49, I, J, D); } - - hypre_MPI_Comm_rank(test_comm, &test_my_id); - if (test_my_id == 0) + else if (test_my_id == 2) { - hypre_printf("Test9_Grid3D_Part3D_Overlap6 (8 procs): "); + HYPRE_Int I[] = {0, 3, 6, 10, 15, 18, 22, 27, 30, 34, 39, 42, 46, 49}; + HYPRE_Int J[] = {0, 1, 2, 0, 1, 3, 0, 2, 3, 5, 1, 2, 3, 4, 6, 3, 4, 9, 2, 5, 6, 7, 3, 5, 6, 8, 9, 5, 7, 8, 6, 7, 8, 11, 4, 6, 9, 10, 11, 9, 10, 12, 8, 9, 11, 12, 10, 11, 12}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(13, 13, 49, I, J, D); } - - /* Create 3x3x3 3D Laplacian with 2x2x2 processor partitioning */ - A = Create3DLaplacian3DPart(test_comm, 3, 3, 3, 2, 2, 2, test_my_id); - - /* Compute overlap */ - if (!hypre_ParCSRMatrixCommPkg(A)) + else { - hypre_MatvecCommPkgCreate(A); + HYPRE_Int I[] = {0, 3, 6, 9, 14, 18, 21, 26, 29, 33, 38, 42, 46, 49}; + HYPRE_Int J[] = {0, 3, 6, 1, 2, 3, 1, 2, 4, 0, 1, 3, 4, 9, 2, 3, 4, 10, 5, 6, 7, 0, 5, 6, 8, 9, 5, 7, 8, 6, 7, 8, 11, 3, 6, 9, 10, 11, 4, 9, 10, 12, 8, 9, 11, 12, 10, 11, 12}; + HYPRE_Real D[] = {4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(13, 13, 49, I, J, D); } - hypre_ParCSRMatrixComputeOverlap(A, overlap_order, &overlap_data); - - /* Get overlap rows */ - hypre_ParCSRMatrixGetExternalMatrix(A, overlap_data); + TEST_COMPARE_MATRICES("test6") + TEST_CLEANUP() +} - /* Extract local overlap matrix */ - hypre_ParCSRMatrixCreateExtendedMatrix(A, overlap_data, &A_local, &col_map, &num_cols_local); +/*-------------------------------------------------------------------------- + * Unit test: 2D grid with 2D partitioning, overlap=3 + * Test case: 4x4 2D grid on 2x2 processor grid (4 processors) + * Tests overlap extraction for 2D problem with 2D processor layout and overlap=3 + *--------------------------------------------------------------------------*/ +static HYPRE_Int +Test7_Grid2D_Part2D_Overlap3(MPI_Comm comm, HYPRE_Int print_matrices) +{ + TEST_VARS() + TEST_SETUP(4) + A = Create2DLaplacian2DPart(test_comm, 4, 4, 2, 2, test_my_id); + TEST_OVERLAP(3) - /* Create expected matrix and compare */ + if (!A_local) { hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); error = 1; } + else { - hypre_CSRMatrix *A_expected = NULL; - - if (!A_local) - { - hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); - error = 1; - } - else + HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); + HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); + if (num_rows_local == 15 && num_cols_local_actual == 15) { - HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); - HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); - - /* All processors should have the same 27x27 matrix (full domain coverage) */ - if (num_rows_local == 27 && num_cols_local_actual == 27) + if (test_my_id == 0) { - /* Same expected matrix for all 8 processors */ - HYPRE_Int I_expected[28] = {0, 4, 9, 14, 20, 25, 31, 37, 44, 48, 53, 58, 64, 68, 73, - 78, 84, 88, 93, 97, 102, 107, 113, 117, 122, 126, 131, 135}; - HYPRE_Int J_expected[135] = {0, 1, 2, 4, 0, 1, 3, 5, 8, 0, 2, 3, 6, 12, 1, 2, 3, 7, 9, 13, - 0, 4, 5, 6, 18, 1, 4, 5, 7, 10, 19, 2, 4, 6, 7, 14, 20, 3, 5, - 6, 7, 11, 15, 21, 1, 8, 9, 10, 3, 8, 9, 11, 16, 5, 8, 10, 11, - 22, 7, 9, 10, 11, 17, 23, 2, 12, 13, 14, 3, 12, 13, 15, 16, 6, - 12, 14, 15, 24, 7, 13, 14, 15, 17, 25, 9, 13, 16, 17, 11, 15, - 16, 17, 26, 4, 18, 19, 20, 5, 18, 19, 21, 22, 6, 18, 20, 21, 24, - 7, 19, 20, 21, 23, 25, 10, 19, 22, 23, 11, 21, 22, 23, 26, 14, - 20, 24, 25, 15, 21, 24, 25, 26, 17, 23, 25, 26}; - HYPRE_Real data_expected[135] = { - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, -1.0, 6.0, -1.0, - -1.0, -1.0, -1.0, 6.0, - -1.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - 6.0, -1.0, -1.0, -1.0, - -1.0, 6.0, -1.0, -1.0, - -1.0, -1.0, 6.0 - }; - A_expected = CreateCSRMatrixFromData(27, 27, 135, I_expected, J_expected, data_expected); + HYPRE_Int I[16] = {0, 3, 7, 11, 16, 20, 23, 28, 32, 36, 41, 44, 48, 53, 56, 59}; + HYPRE_Int J[59] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 8, 1, 2, 3, 6, 9, 1, 4, 5, 6, 4, 5, 7, 3, 4, 6, 7, 12, 5, 6, 7, 13, 2, 8, 9, 10, 3, 8, 9, 11, 12, 8, 10, 11, 9, 10, 11, 14, 6, 9, 12, 13, 14, 7, 12, 13, 11, 12, 14}; + HYPRE_Real D[59] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(15, 15, 59, I, J, D); } - else + else if (test_my_id == 1) { - hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 27 x 27)\n", - test_my_id, num_rows_local, num_cols_local_actual); - error = 1; - A_expected = NULL; + HYPRE_Int I[16] = {0, 3, 7, 11, 16, 20, 23, 28, 32, 35, 40, 43, 48, 52, 56, 59}; + HYPRE_Int J[59] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 8, 1, 2, 3, 6, 9, 1, 4, 5, 6, 4, 5, 7, 3, 4, 6, 7, 11, 5, 6, 7, 12, 2, 8, 9, 3, 8, 9, 10, 11, 9, 10, 13, 6, 9, 11, 12, 13, 7, 11, 12, 14, 10, 11, 13, 14, 12, 13, 14}; + HYPRE_Real D[59] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(15, 15, 59, I, J, D); } - - if (A_expected) + else if (test_my_id == 2) { - if (print_matrices) - { - char filename_expected[256]; - char filename_computed[256]; - hypre_sprintf(filename_expected, "test9_expected_ij.out.%05d", test_my_id); - hypre_sprintf(filename_computed, "test9_computed_ij.out.%05d", test_my_id); - hypre_CSRMatrixPrintIJ(A_expected, 0, 0, filename_expected); - hypre_CSRMatrixPrintIJ(A_local, 0, 0, filename_computed); - } - if (CompareCSRMatrices(A_expected, A_local, CHECK_TOLERANCE) != 0) - { - hypre_printf("Proc %d: Extracted matrix does not match expected matrix\n", test_my_id); - error = 1; - } - hypre_CSRMatrixDestroy(A_expected); + HYPRE_Int I[16] = {0, 3, 7, 11, 16, 19, 24, 27, 31, 36, 39, 43, 48, 52, 56, 59}; + HYPRE_Int J[59] = {0, 1, 2, 0, 1, 3, 4, 0, 2, 3, 7, 1, 2, 3, 5, 8, 1, 4, 5, 3, 4, 5, 6, 11, 5, 6, 12, 2, 7, 8, 9, 3, 7, 8, 10, 11, 7, 9, 10, 8, 9, 10, 13, 5, 8, 11, 12, 13, 6, 11, 12, 14, 10, 11, 13, 14, 12, 13, 14}; + HYPRE_Real D[59] = {4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(15, 15, 59, I, J, D); + } + else if (test_my_id == 3) + { + HYPRE_Int I[16] = {0, 3, 6, 11, 15, 18, 23, 27, 31, 36, 39, 43, 48, 52, 56, 59}; + HYPRE_Int J[59] = {0, 2, 3, 1, 2, 7, 0, 1, 2, 5, 8, 0, 3, 4, 5, 3, 4, 6, 2, 3, 5, 6, 11, 4, 5, 6, 12, 1, 7, 8, 9, 2, 7, 8, 10, 11, 7, 9, 10, 8, 9, 10, 13, 5, 8, 11, 12, 13, 6, 11, 12, 14, 10, 11, 13, 14, 12, 13, 14}; + HYPRE_Real D[59] = {4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0, -1.0, -1.0, -1.0, 4.0}; + A_expected = CreateCSRMatrixFromData(15, 15, 59, I, J, D); } } + else { hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 15 x 15)\n", test_my_id, num_rows_local, num_cols_local_actual); error = 1; } + TEST_COMPARE_MATRICES("test7") } - /* Cleanup */ - if (A_local) - { - hypre_CSRMatrixDestroy(A_local); - } - if (col_map) - { - hypre_TFree(col_map, HYPRE_MEMORY_HOST); - } - if (overlap_data) - { - hypre_OverlapDataDestroy(overlap_data); - } - if (A) + TEST_CLEANUP() +} + +/*-------------------------------------------------------------------------- + * Unit test: 3D grid with 3D partitioning, overlap=1 + * Test case: 3x3x3 3D grid on 2x2x2 processor grid (8 processors) + * Tests overlap extraction for 3D problem with 3D processor layout and overlap=1 + *--------------------------------------------------------------------------*/ +static HYPRE_Int +Test8_Grid3D_Part3D_Overlap1(MPI_Comm comm, HYPRE_Int print_matrices) +{ + TEST_VARS() + TEST_SETUP(8) + A = Create3DLaplacian3DPart(test_comm, 3, 3, 3, 2, 2, 2, test_my_id); + TEST_OVERLAP(1) + if (!A_local) { hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); error = 1; } + else { - hypre_ParCSRMatrixDestroy(A); + HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); + HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); + if (test_my_id == 0 && num_rows_local == 20 && num_cols_local_actual == 20) + { + HYPRE_Int I[21] = {0, 4, 9, 14, 20, 25, 31, 37, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92}; + HYPRE_Int J[92] = {0, 1, 2, 4, 0, 1, 3, 5, 8, 0, 2, 3, 6, 12, 1, 2, 3, 7, 9, 13, 0, 4, 5, 6, 16, 1, 4, 5, 7, 10, 17, 2, 4, 6, 7, 14, 18, 3, 5, 6, 7, 11, 15, 19, 1, 8, 9, 10, 3, 8, 9, 11, 5, 8, 10, 11, 7, 9, 10, 11, 2, 12, 13, 14, 3, 12, 13, 15, 6, 12, 14, 15, 7, 13, 14, 15, 4, 16, 17, 18, 5, 16, 17, 19, 6, 16, 18, 19, 7, 17, 18, 19}; + HYPRE_Real D[92] = {6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(20, 20, 92, I, J, D); + } + else if (test_my_id == 1 && num_rows_local == 12 && num_cols_local_actual == 12) + { + HYPRE_Int I[13] = {0, 4, 8, 12, 16, 20, 25, 30, 36, 39, 42, 45, 48}; + HYPRE_Int J[48] = {0, 1, 2, 4, 0, 1, 3, 5, 0, 2, 3, 6, 1, 2, 3, 7, 0, 4, 5, 6, 1, 4, 5, 7, 8, 2, 4, 6, 7, 10, 3, 5, 6, 7, 9, 11, 5, 8, 9, 7, 8, 9, 6, 10, 11, 7, 10, 11}; + HYPRE_Real D[48] = {6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(12, 12, 48, I, J, D); + } + else if (test_my_id == 2 && num_rows_local == 12 && num_cols_local_actual == 12) + { + HYPRE_Int I[13] = {0, 4, 8, 12, 16, 20, 25, 30, 36, 39, 42, 45, 48}; + HYPRE_Int J[48] = {0, 1, 2, 4, 0, 1, 3, 5, 0, 2, 3, 6, 1, 2, 3, 7, 0, 4, 5, 6, 1, 4, 5, 7, 8, 2, 4, 6, 7, 10, 3, 5, 6, 7, 9, 11, 5, 8, 9, 7, 8, 9, 6, 10, 11, 7, 10, 11}; + HYPRE_Real D[48] = {6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(12, 12, 48, I, J, D); + } + else if (test_my_id == 3 && num_rows_local == 7 && num_cols_local_actual == 7) + { + HYPRE_Int I[8] = {0, 3, 6, 9, 12, 16, 21, 23}; + HYPRE_Int J[23] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 5, 0, 2, 4, 5, 1, 3, 4, 5, 6, 5, 6}; + HYPRE_Real D[23] = {6.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(7, 7, 23, I, J, D); + } + else if (test_my_id == 4 && num_rows_local == 12 && num_cols_local_actual == 12) + { + HYPRE_Int I[13] = {0, 4, 8, 12, 16, 20, 25, 30, 36, 39, 42, 45, 48}; + HYPRE_Int J[48] = {0, 1, 2, 4, 0, 1, 3, 5, 0, 2, 3, 6, 1, 2, 3, 7, 0, 4, 5, 6, 1, 4, 5, 7, 8, 2, 4, 6, 7, 10, 3, 5, 6, 7, 9, 11, 5, 8, 9, 7, 8, 9, 6, 10, 11, 7, 10, 11}; + HYPRE_Real D[48] = {6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(12, 12, 48, I, J, D); + } + else if (test_my_id == 5 && num_rows_local == 7 && num_cols_local_actual == 7) + { + HYPRE_Int I[8] = {0, 3, 6, 9, 12, 16, 21, 23}; + HYPRE_Int J[23] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 5, 0, 2, 4, 5, 1, 3, 4, 5, 6, 5, 6}; + HYPRE_Real D[23] = {6.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(7, 7, 23, I, J, D); + } + else if (test_my_id == 6 && num_rows_local == 7 && num_cols_local_actual == 7) + { + HYPRE_Int I[8] = {0, 3, 6, 9, 12, 16, 21, 23}; + HYPRE_Int J[23] = {0, 1, 4, 0, 1, 5, 2, 3, 4, 2, 3, 5, 0, 2, 4, 5, 1, 3, 4, 5, 6, 5, 6}; + HYPRE_Real D[23] = {6.0, -1.0, -1.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(7, 7, 23, I, J, D); + } + else if (test_my_id == 7 && num_rows_local == 4 && num_cols_local_actual == 4) + { + HYPRE_Int I[5] = {0, 2, 4, 6, 10}; + HYPRE_Int J[10] = {0, 3, 1, 3, 2, 3, 0, 1, 2, 3}; + HYPRE_Real D[10] = {6.0, -1.0, 6.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(4, 4, 10, I, J, D); + } + else if (test_my_id >= 0 && test_my_id <= 7) + { + hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d\n", test_my_id, num_rows_local, + num_cols_local_actual); + error = 1; + } + else { hypre_printf("Proc %d: Unexpected processor ID (expected 0-7)\n", test_my_id); error = 1; } + TEST_COMPARE_MATRICES("test8") } - if (test_comm != MPI_COMM_NULL) + TEST_CLEANUP() +} + +/*-------------------------------------------------------------------------- + * Unit test: 3D grid with 3D partitioning, overlap=6 (full domain coverage) + * Test case: 3x3x3 3D grid on 2x2x2 processor grid (8 processors) + * Tests overlap extraction for 3D problem with 3D processor layout and overlap=6 + * With overlap=6, all processors should have the full global matrix (27x27) + *--------------------------------------------------------------------------*/ +static HYPRE_Int +Test9_Grid3D_Part3D_Overlap6(MPI_Comm comm, HYPRE_Int print_matrices) +{ + TEST_VARS() + TEST_SETUP(8) + A = Create3DLaplacian3DPart(test_comm, 3, 3, 3, 2, 2, 2, test_my_id); + TEST_OVERLAP(6) + if (!A_local) { hypre_printf("Proc %d: Failed to extract local overlap matrix\n", test_my_id); error = 1; } + else { - PRINT_TEST_RESULT(test_my_id, error); - hypre_MPI_Comm_free(&test_comm); + HYPRE_Int num_rows_local = hypre_CSRMatrixNumRows(A_local); + HYPRE_Int num_cols_local_actual = hypre_CSRMatrixNumCols(A_local); + if (num_rows_local == 27 && num_cols_local_actual == 27) + { + HYPRE_Int I[28] = {0, 4, 9, 14, 20, 25, 31, 37, 44, 48, 53, 58, 64, 68, 73, 78, 84, 88, 93, 97, 102, 107, 113, 117, 122, 126, 131, 135}; + HYPRE_Int J[135] = {0, 1, 2, 4, 0, 1, 3, 5, 8, 0, 2, 3, 6, 12, 1, 2, 3, 7, 9, 13, 0, 4, 5, 6, 18, 1, 4, 5, 7, 10, 19, 2, 4, 6, 7, 14, 20, 3, 5, 6, 7, 11, 15, 21, 1, 8, 9, 10, 3, 8, 9, 11, 16, 5, 8, 10, 11, 22, 7, 9, 10, 11, 17, 23, 2, 12, 13, 14, 3, 12, 13, 15, 16, 6, 12, 14, 15, 24, 7, 13, 14, 15, 17, 25, 9, 13, 16, 17, 11, 15, 16, 17, 26, 4, 18, 19, 20, 5, 18, 19, 21, 22, 6, 18, 20, 21, 24, 7, 19, 20, 21, 23, 25, 10, 19, 22, 23, 11, 21, 22, 23, 26, 14, 20, 24, 25, 15, 21, 24, 25, 26, 17, 23, 25, 26}; + HYPRE_Real D[135] = {6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0, -1.0, -1.0, -1.0, -1.0, 6.0}; + A_expected = CreateCSRMatrixFromData(27, 27, 135, I, J, D); + } + else { hypre_printf("Proc %d: Unexpected matrix dimensions: %d x %d (expected 27 x 27)\n", test_my_id, num_rows_local, num_cols_local_actual); error = 1; } + TEST_COMPARE_MATRICES("test9") } - /* Synchronize all processes before returning */ - hypre_MPI_Barrier(comm); - - return error; + TEST_CLEANUP() } /*-------------------------------------------------------------------------- @@ -2215,7 +537,7 @@ BenchmarkOverlap(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int nz, HYPRE_BigInt *col_map; HYPRE_Int num_cols_local; HYPRE_Real time_start, time_end, time_overlap, time_extract; - HYPRE_Int num_extended, num_local, num_overlap; + HYPRE_Int num_extended, num_overlap; hypre_MPI_Comm_rank(comm, &my_id); hypre_MPI_Comm_size(comm, &num_procs); @@ -2309,8 +631,7 @@ BenchmarkOverlap(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int nz, /* Gather statistics */ num_extended = hypre_OverlapDataNumExtendedRows(overlap_data); - num_local = hypre_OverlapDataNumLocalRows(overlap_data); - num_overlap = hypre_OverlapDataNumOverlapRows(overlap_data); + num_overlap = hypre_OverlapDataNumOverlapRows(overlap_data); if (my_id == 0) { @@ -2338,7 +659,7 @@ BenchmarkOverlap(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int nz, for (i = 0; i < num_procs; i++) { hypre_printf(" %3d %8d %8d %10d\n", - i, local_extended[i], local_overlap[i], local_nnz[i]); + i, local_extended[i], local_overlap[i], local_nnz[i]); } } @@ -2356,16 +677,239 @@ BenchmarkOverlap(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int nz, return 0; } +/*-------------------------------------------------------------------------- + * Benchmark: Generate laplacian and compute matrix powers via matrix-matrix multiplication + * Computes A^overlap_order using repeated matrix-matrix products + * This serves as a reference for the new overlap capabilities + *--------------------------------------------------------------------------*/ +static HYPRE_Int +BenchmarkMatMat(MPI_Comm comm, HYPRE_Int nx, HYPRE_Int ny, HYPRE_Int nz, + HYPRE_Int Px, HYPRE_Int Py, HYPRE_Int Pz, + HYPRE_Int overlap_order, HYPRE_Int print_matrices) +{ + HYPRE_Int my_id, num_procs; + hypre_ParCSRMatrix *A; + hypre_ParCSRMatrix *A_power; + hypre_ParCSRMatrix **buffer; + HYPRE_Real time_start, time_end, time_total; + HYPRE_Int i; + + hypre_MPI_Comm_rank(comm, &my_id); + hypre_MPI_Comm_size(comm, &num_procs); + + if (my_id == 0) + { + hypre_printf("\nBenchmark: Matrix-Matrix Multiplication (A^%d)\n", overlap_order + 1); + hypre_printf(" Problem size: %d x %d x %d\n", nx, ny, nz); + hypre_printf(" Processor grid: %d x %d x %d\n", Px, Py, Pz); + hypre_printf(" Overlap order: %d (computes A^%d)\n", overlap_order, overlap_order + 1); + } + + /* Generate laplacian using GenerateLaplacian */ + { + HYPRE_Real *values; + HYPRE_Int p, q, r; + + /* Compute processor coordinates */ + p = my_id % Px; + q = ((my_id - p) / Px) % Py; + r = (my_id - p - Px * q) / (Px * Py); + + /* Set up 7-point stencil values */ + values = hypre_CTAlloc(HYPRE_Real, 4, HYPRE_MEMORY_HOST); + if (nx > 1) + { + values[0] += 2.0; + values[1] = -1.0; + } + if (ny > 1) + { + values[0] += 2.0; + values[2] = -1.0; + } + if (nz > 1) + { + values[0] += 2.0; + values[3] = -1.0; + } + + A = GenerateLaplacian(comm, nx, ny, nz, Px, Py, Pz, p, q, r, values); + + hypre_TFree(values, HYPRE_MEMORY_HOST); + } + + /* Print original matrix if requested */ + if (print_matrices) + { + char filename[256]; + hypre_sprintf(filename, "benchmark_matmat_original_ij.out"); + hypre_ParCSRMatrixPrintIJ(A, 0, 0, filename); + if (my_id == 0) + { + hypre_printf(" Printed original matrix to %s.\n", filename); + } + } + + /* Ensure communication package exists */ + if (!hypre_ParCSRMatrixCommPkg(A)) + { + hypre_MatvecCommPkgCreate(A); + } + + /* Allocate array to track intermediate matrices for cleanup */ + buffer = hypre_TAlloc(hypre_ParCSRMatrix*, overlap_order, HYPRE_MEMORY_HOST); + for (i = 0; i < overlap_order; i++) + { + buffer[i] = NULL; + } + + /* Compute A^(overlap_order+1) */ + time_start = hypre_MPI_Wtime(); + + HYPRE_Int exponent = overlap_order + 1; + HYPRE_Int buffer_idx = 0; + hypre_ParCSRMatrix *temp, *base = A; + + /* Binary exponentiation: process exponent bit by bit */ + A_power = NULL; + while (exponent > 0) + { + if (exponent % 2 == 1) + { + /* Current bit is 1: multiply result by current base */ + if (A_power == NULL) + { + /* First multiplication: result = base (which is A initially) */ + A_power = base; + } + else + { + /* Multiply result by base */ + temp = hypre_ParCSRMatMat(A_power, base); + /* Store old A_power in buffer for cleanup (if not original A) */ + if (A_power != A) + { + if (buffer_idx < overlap_order) + { + buffer[buffer_idx++] = A_power; + } + else + { + /* Buffer full: destroy old A_power immediately */ + hypre_ParCSRMatrixDestroy(A_power); + } + } + A_power = temp; + } + } + + /* Square the base for next bit: base = base^2 */ + if (exponent > 1) + { + temp = hypre_ParCSRMatMat(base, base); + /* Store old base in buffer for cleanup (if not original A) */ + if (base != A) + { + if (buffer_idx < overlap_order) + { + buffer[buffer_idx++] = base; + } + else + { + /* Buffer full: destroy old base immediately */ + hypre_ParCSRMatrixDestroy(base); + } + } + base = temp; + } + + exponent /= 2; + } + + hypre_MPI_Barrier(comm); + time_end = hypre_MPI_Wtime(); + time_total = time_end - time_start; + + /* Print result matrix if requested */ + if (print_matrices) + { + char filename[256]; + hypre_sprintf(filename, "benchmark_matmat_power_ij.out.%05d", my_id); + hypre_ParCSRMatrixPrintIJ(A_power, 0, 0, filename); + if (my_id == 0) + { + hypre_printf(" Printed A^%d matrix to %s.\n", overlap_order + 1, filename); + } + } + + /* Gather statistics */ + { + HYPRE_Int i; + HYPRE_Int *local_nnz = hypre_TAlloc(HYPRE_Int, num_procs, HYPRE_MEMORY_HOST); + HYPRE_Int *local_rows = hypre_TAlloc(HYPRE_Int, num_procs, HYPRE_MEMORY_HOST); + HYPRE_Int nnz_local = hypre_CSRMatrixNumNonzeros(hypre_ParCSRMatrixDiag(A_power)) + + hypre_CSRMatrixNumNonzeros(hypre_ParCSRMatrixOffd(A_power)); + HYPRE_Int num_rows_local = hypre_ParCSRMatrixNumRows(A_power); + + hypre_MPI_Gather(&nnz_local, 1, HYPRE_MPI_INT, local_nnz, 1, HYPRE_MPI_INT, 0, comm); + hypre_MPI_Gather(&num_rows_local, 1, HYPRE_MPI_INT, local_rows, 1, HYPRE_MPI_INT, 0, comm); + + if (my_id == 0) + { + hypre_printf(" Total matrix-matrix multiplication time: %e seconds\n", time_total); + hypre_printf("\n Per-processor statistics:\n"); + hypre_printf(" Proc Local Rows Local NNZ\n"); + for (i = 0; i < num_procs; i++) + { + hypre_printf(" %3d %8d %10d\n", i, local_rows[i], local_nnz[i]); + } + } + + hypre_TFree(local_nnz, HYPRE_MEMORY_HOST); + hypre_TFree(local_rows, HYPRE_MEMORY_HOST); + } + + /* Cleanup: destroy all intermediate matrices and final result */ + /* Destroy all intermediate matrices stored in buffer */ + for (i = 0; i < overlap_order; i++) + { + if (buffer[i] != NULL) + { + hypre_ParCSRMatrixDestroy(buffer[i]); + } + } + + /* Destroy final base if it's not the original A and not the same as A_power */ + if (base != A && base != A_power) + { + hypre_ParCSRMatrixDestroy(base); + } + + /* Destroy final result A_power if it's not the original A */ + if (A_power != A) + { + hypre_ParCSRMatrixDestroy(A_power); + } + + /* Destroy original matrix A */ + hypre_ParCSRMatrixDestroy(A); + + /* Free the buffer array */ + hypre_TFree(buffer, HYPRE_MEMORY_HOST); + + return 0; +} + /*-------------------------------------------------------------------------- * Main function *--------------------------------------------------------------------------*/ -int -main(int argc, char *argv[]) +hypre_int +main(hypre_int argc, char *argv[]) { MPI_Comm comm; HYPRE_Int my_id, num_procs; HYPRE_Int error = 0; - HYPRE_Int test_mode = 1; /* 1=unit tests, 0=benchmark */ + HYPRE_Int test_mode = 0; /* 0=unit tests, 1=benchmark, 2=benchmark-matmat */ HYPRE_Int nx, ny, nz; HYPRE_Int Px, Py, Pz; HYPRE_Int overlap_order = 1; @@ -2378,7 +922,11 @@ main(int argc, char *argv[]) hypre_MPI_Comm_rank(comm, &my_id); hypre_MPI_Comm_size(comm, &num_procs); - HYPRE_Init(); + HYPRE_Initialize(); + + /* Default to CPU execution */ + HYPRE_SetMemoryLocation(HYPRE_MEMORY_HOST); + HYPRE_SetExecutionPolicy(HYPRE_EXEC_HOST); /* Parse command line */ i = 1; @@ -2388,7 +936,12 @@ main(int argc, char *argv[]) { if (strcmp(argv[i], "-benchmark") == 0) { - test_mode = 0; + test_mode = 1; + i++; + } + else if (strcmp(argv[i], "-benchmark-matmat") == 0) + { + test_mode = 2; i++; } else if (strcmp(argv[i], "-n") == 0) @@ -2421,16 +974,15 @@ main(int argc, char *argv[]) { hypre_printf("Usage: %s [options]\n", argv[0]); hypre_printf("Options:\n"); - hypre_printf(" -benchmark : Run benchmark instead of unit tests\n"); + hypre_printf(" -benchmark : Run overlap extraction benchmark\n"); + hypre_printf(" -benchmark-matmat : Run matrix-matrix multiplication benchmark (A^overlap_order)\n"); hypre_printf(" -n : Problem size (default: 20 20 20)\n"); hypre_printf(" -P : Processor grid (default: 2 2 2)\n"); - hypre_printf(" -ov : Overlap order (default: 1)\n"); + hypre_printf(" -ov : Overlap order / matrix power (default: 1)\n"); hypre_printf(" -print : Print expected and computed matrices to .ij files\n"); hypre_printf(" -h, -help : Print this help\n"); } - HYPRE_Finalize(); - hypre_MPI_Finalize(); - return 0; + goto end; } else { @@ -2442,7 +994,7 @@ main(int argc, char *argv[]) } } - if (test_mode) + if (!test_mode) { /* Run unit tests */ if (my_id == 0) @@ -2475,7 +1027,7 @@ main(int argc, char *argv[]) } } } - else + else if (test_mode == 1) { /* Run Warmup */ if (my_id == 0) @@ -2484,10 +1036,23 @@ main(int argc, char *argv[]) } BenchmarkOverlap(comm, 10 * num_procs, 10, 10, num_procs, 1, 1, 0, 0); - /* Run Benchmark */ + /* Run Overlap Benchmark */ BenchmarkOverlap(comm, nx, ny, nz, Px, Py, Pz, overlap_order, print_matrices); } + else if (test_mode == 2) + { + /* Run Warmup */ + if (my_id == 0) + { + hypre_printf("\nWarmup phase..."); + } + BenchmarkMatMat(comm, 10 * num_procs, 10, 10, num_procs, 1, 1, 1, 0); + + /* Run Matrix-Matrix Multiplication Benchmark */ + BenchmarkMatMat(comm, nx, ny, nz, Px, Py, Pz, overlap_order, print_matrices); + } +end: HYPRE_Finalize(); hypre_MPI_Finalize();