hypre/parcsr_ls/par_nodal_systems.c
2008-07-18 01:34:48 +00:00

1206 lines
35 KiB
C

/*BHEADER**********************************************************************
* Copyright (c) 2008, Lawrence Livermore National Security, LLC.
* Produced at the Lawrence Livermore National Laboratory.
* This file is part of HYPRE. See file COPYRIGHT for details.
*
* HYPRE is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License (as published by the Free
* Software Foundation) version 2.1 dated February 1999.
*
* $Revision$
***********************************************************************EHEADER*/
/******************************************************************************
*
*****************************************************************************/
/* following should be in a header file */
#include "headers.h"
/*==========================================================================*/
/*==========================================================================*/
/**
Generates nodal norm matrix for use with nodal systems version
{\bf Input files:}
headers.h
@return Error code.
@param A [IN]
coefficient matrix
@param AN_ptr [OUT]
nodal norm matrix
@see */
/*--------------------------------------------------------------------------*/
int
hypre_BoomerAMGCreateNodalA(hypre_ParCSRMatrix *A,
int num_functions,
int *dof_func,
int option,
int diag_option,
hypre_ParCSRMatrix **AN_ptr)
{
MPI_Comm comm = hypre_ParCSRMatrixComm(A);
hypre_CSRMatrix *A_diag = hypre_ParCSRMatrixDiag(A);
int *A_diag_i = hypre_CSRMatrixI(A_diag);
double *A_diag_data = hypre_CSRMatrixData(A_diag);
hypre_CSRMatrix *A_offd = hypre_ParCSRMatrixOffd(A);
int *A_offd_i = hypre_CSRMatrixI(A_offd);
double *A_offd_data = hypre_CSRMatrixData(A_offd);
int *A_diag_j = hypre_CSRMatrixJ(A_diag);
int *A_offd_j = hypre_CSRMatrixJ(A_offd);
int *row_starts = hypre_ParCSRMatrixRowStarts(A);
int *col_map_offd = hypre_ParCSRMatrixColMapOffd(A);
int num_variables = hypre_CSRMatrixNumRows(A_diag);
int num_nonzeros_offd = 0;
int num_cols_offd = 0;
hypre_ParCSRMatrix *AN;
hypre_CSRMatrix *AN_diag;
int *AN_diag_i;
int *AN_diag_j;
double *AN_diag_data;
hypre_CSRMatrix *AN_offd;
int *AN_offd_i;
int *AN_offd_j;
double *AN_offd_data;
int *col_map_offd_AN;
int *new_col_map_offd;
int *row_starts_AN;
int AN_num_nonzeros_diag = 0;
int AN_num_nonzeros_offd = 0;
int num_cols_offd_AN;
int new_num_cols_offd;
hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRMatrixCommPkg(A);
int num_sends;
int num_recvs;
int *send_procs;
int *send_map_starts;
int *send_map_elmts;
int *new_send_map_elmts;
int *recv_procs;
int *recv_vec_starts;
hypre_ParCSRCommPkg *comm_pkg_AN;
int *send_procs_AN;
int *send_map_starts_AN;
int *send_map_elmts_AN;
int *recv_procs_AN;
int *recv_vec_starts_AN;
int i, j, k, k_map;
int ierr = 0;
int index, row;
int start_index;
int num_procs;
int node, cnt;
int mode;
int new_send_elmts_size;
int global_num_nodes;
int num_nodes;
int num_fun2;
int *map_to_node;
int *map_to_map;
int *counter;
double sum;
double *data;
MPI_Comm_size(comm,&num_procs);
if (!comm_pkg)
{
hypre_MatvecCommPkgCreate(A);
comm_pkg = hypre_ParCSRMatrixCommPkg(A);
}
mode = fabs(option);
comm_pkg_AN = NULL;
col_map_offd_AN = NULL;
#ifdef HYPRE_NO_GLOBAL_PARTITION
row_starts_AN = hypre_CTAlloc(int, 2);
for (i=0; i < 2; i++)
{
row_starts_AN[i] = row_starts[i]/num_functions;
if (row_starts_AN[i]*num_functions < row_starts[i])
{
printf("nodes not properly aligned or incomplete info!\n");
return (87);
}
}
global_num_nodes = hypre_ParCSRMatrixGlobalNumRows(A)/num_functions;
#else
row_starts_AN = hypre_CTAlloc(int, num_procs+1);
for (i=0; i < num_procs+1; i++)
{
row_starts_AN[i] = row_starts[i]/num_functions;
if (row_starts_AN[i]*num_functions < row_starts[i])
{
printf("nodes not properly aligned or incomplete info!\n");
return (87);
}
}
global_num_nodes = row_starts_AN[num_procs];
#endif
num_nodes = num_variables/num_functions;
num_fun2 = num_functions*num_functions;
map_to_node = hypre_CTAlloc(int, num_variables);
AN_diag_i = hypre_CTAlloc(int, num_nodes+1);
counter = hypre_CTAlloc(int, num_nodes);
for (i=0; i < num_variables; i++)
map_to_node[i] = i/num_functions;
for (i=0; i < num_nodes; i++)
counter[i] = -1;
AN_num_nonzeros_diag = 0;
row = 0;
for (i=0; i < num_nodes; i++)
{
AN_diag_i[i] = AN_num_nonzeros_diag;
for (j=0; j < num_functions; j++)
{
for (k=A_diag_i[row]; k < A_diag_i[row+1]; k++)
{
k_map = map_to_node[A_diag_j[k]];
if (counter[k_map] < i)
{
counter[k_map] = i;
AN_num_nonzeros_diag++;
}
}
row++;
}
}
AN_diag_i[num_nodes] = AN_num_nonzeros_diag;
AN_diag_j = hypre_CTAlloc(int, AN_num_nonzeros_diag);
AN_diag_data = hypre_CTAlloc(double, AN_num_nonzeros_diag);
AN_diag = hypre_CSRMatrixCreate(num_nodes,num_nodes,AN_num_nonzeros_diag);
hypre_CSRMatrixI(AN_diag) = AN_diag_i;
hypre_CSRMatrixJ(AN_diag) = AN_diag_j;
hypre_CSRMatrixData(AN_diag) = AN_diag_data;
for (i=0; i < num_nodes; i++)
counter[i] = -1;
index = 0;
start_index = 0;
row = 0;
switch (mode)
{
case 1: /* frobenius norm */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_diag_i[row]; k < A_diag_i[row+1]; k++)
{
k_map = map_to_node[A_diag_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_diag_j[index] = k_map;
AN_diag_data[index] = A_diag_data[k]*A_diag_data[k];
index++;
}
else
{
AN_diag_data[counter[k_map]] +=
A_diag_data[k]*A_diag_data[k];
}
}
row++;
}
start_index = index;
}
for (i=0; i < AN_num_nonzeros_diag; i++)
AN_diag_data[i] = sqrt(AN_diag_data[i]);
}
break;
case 2: /* sum of abs. value of all elements in each block */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_diag_i[row]; k < A_diag_i[row+1]; k++)
{
k_map = map_to_node[A_diag_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_diag_j[index] = k_map;
AN_diag_data[index] = fabs(A_diag_data[k]);
index++;
}
else
{
AN_diag_data[counter[k_map]] += fabs(A_diag_data[k]);
}
}
row++;
}
start_index = index;
}
for (i=0; i < AN_num_nonzeros_diag; i++)
AN_diag_data[i] /= num_fun2;
}
break;
case 3: /* largest element of each block (sets true value - not abs. value) */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_diag_i[row]; k < A_diag_i[row+1]; k++)
{
k_map = map_to_node[A_diag_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_diag_j[index] = k_map;
AN_diag_data[index] = A_diag_data[k];
index++;
}
else
{
if (fabs(A_diag_data[k]) >
fabs(AN_diag_data[counter[k_map]]))
AN_diag_data[counter[k_map]] = A_diag_data[k];
}
}
row++;
}
start_index = index;
}
}
break;
case 4: /* inf. norm (row-sum) */
{
data = hypre_CTAlloc(double, AN_num_nonzeros_diag*num_functions);
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_diag_i[row]; k < A_diag_i[row+1]; k++)
{
k_map = map_to_node[A_diag_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_diag_j[index] = k_map;
data[index*num_functions + j] = fabs(A_diag_data[k]);
index++;
}
else
{
data[(counter[k_map])*num_functions + j] += fabs(A_diag_data[k]);
}
}
row++;
}
start_index = index;
}
for (i=0; i < AN_num_nonzeros_diag; i++)
{
AN_diag_data[i] = data[i*num_functions];
for (j=1; j< num_functions; j++)
{
AN_diag_data[i] = hypre_max( AN_diag_data[i],data[i*num_functions+j]);
}
}
hypre_TFree(data);
}
break;
case 6: /* sum of all elements in each block */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_diag_i[row]; k < A_diag_i[row+1]; k++)
{
k_map = map_to_node[A_diag_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_diag_j[index] = k_map;
AN_diag_data[index] = (A_diag_data[k]);
index++;
}
else
{
AN_diag_data[counter[k_map]] += (A_diag_data[k]);
}
}
row++;
}
start_index = index;
}
}
break;
}
if (diag_option ==1 )
{
/* make the diag entry the negative of the sum of off-diag entries (DO MORE BELOW) */
for (i=0; i < num_nodes; i++)
{
index = AN_diag_i[i];
sum = 0.0;
for (k = AN_diag_i[i]+1; k < AN_diag_i[i+1]; k++)
{
sum += AN_diag_data[k];
}
AN_diag_data[index] = -sum;
}
}
else if (diag_option == 2)
{
/* make all diagonal entries negative */
/* the diagonal is the first element listed in each row - */
for (i=0; i < num_nodes; i++)
{
index = AN_diag_i[i];
AN_diag_data[index] = - AN_diag_data[index];
}
}
num_nonzeros_offd = A_offd_i[num_variables];
AN_offd_i = hypre_CTAlloc(int, num_nodes+1);
num_cols_offd_AN = 0;
if (comm_pkg)
{
comm_pkg_AN = hypre_CTAlloc(hypre_ParCSRCommPkg,1);
hypre_ParCSRCommPkgComm(comm_pkg_AN) = comm;
num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg);
hypre_ParCSRCommPkgNumSends(comm_pkg_AN) = num_sends;
num_recvs = hypre_ParCSRCommPkgNumRecvs(comm_pkg);
hypre_ParCSRCommPkgNumRecvs(comm_pkg_AN) = num_recvs;
send_procs = hypre_ParCSRCommPkgSendProcs(comm_pkg);
send_map_starts = hypre_ParCSRCommPkgSendMapStarts(comm_pkg);
send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg);
recv_procs = hypre_ParCSRCommPkgRecvProcs(comm_pkg);
recv_vec_starts = hypre_ParCSRCommPkgRecvVecStarts(comm_pkg);
send_procs_AN = NULL;
send_map_elmts_AN = NULL;
if (num_sends)
{
send_procs_AN = hypre_CTAlloc(int,num_sends);
send_map_elmts_AN = hypre_CTAlloc(int,send_map_starts[num_sends]);
}
send_map_starts_AN = hypre_CTAlloc(int,num_sends+1);
recv_vec_starts_AN = hypre_CTAlloc(int,num_recvs+1);
recv_procs_AN = NULL;
if (num_recvs) recv_procs_AN = hypre_CTAlloc(int,num_recvs);
for (i=0; i < num_sends; i++)
send_procs_AN[i] = send_procs[i];
for (i=0; i < num_recvs; i++)
recv_procs_AN[i] = recv_procs[i];
send_map_starts_AN[0] = 0;
cnt = 0;
for (i=0; i < num_sends; i++)
{
k_map = send_map_starts[i];
if (send_map_starts[i+1]-k_map)
send_map_elmts_AN[cnt++] = send_map_elmts[k_map]/num_functions;
for (j=send_map_starts[i]+1; j < send_map_starts[i+1]; j++)
{
node = send_map_elmts[j]/num_functions;
if (node > send_map_elmts_AN[cnt-1])
send_map_elmts_AN[cnt++] = node;
}
send_map_starts_AN[i+1] = cnt;
}
hypre_ParCSRCommPkgSendProcs(comm_pkg_AN) = send_procs_AN;
hypre_ParCSRCommPkgSendMapStarts(comm_pkg_AN) = send_map_starts_AN;
hypre_ParCSRCommPkgSendMapElmts(comm_pkg_AN) = send_map_elmts_AN;
hypre_ParCSRCommPkgRecvProcs(comm_pkg_AN) = recv_procs_AN;
hypre_ParCSRCommPkgRecvVecStarts(comm_pkg_AN) = recv_vec_starts_AN;
}
num_cols_offd = hypre_CSRMatrixNumCols(A_offd);
if (num_cols_offd)
{
if (num_cols_offd > num_variables)
{
hypre_TFree(map_to_node);
map_to_node = hypre_CTAlloc(int,num_cols_offd);
}
num_cols_offd_AN = 1;
map_to_node[0] = col_map_offd[0]/num_functions;
for (i=1; i < num_cols_offd; i++)
{
map_to_node[i] = col_map_offd[i]/num_functions;
if (map_to_node[i] > map_to_node[i-1]) num_cols_offd_AN++;
}
if (num_cols_offd_AN > num_nodes)
{
hypre_TFree(counter);
counter = hypre_CTAlloc(int,num_cols_offd_AN);
}
map_to_map = NULL;
col_map_offd_AN = NULL;
map_to_map = hypre_CTAlloc(int, num_cols_offd);
col_map_offd_AN = hypre_CTAlloc(int,num_cols_offd_AN);
col_map_offd_AN[0] = map_to_node[0];
recv_vec_starts_AN[0] = 0;
cnt = 1;
for (i=0; i < num_recvs; i++)
{
for (j=recv_vec_starts[i]; j < recv_vec_starts[i+1]; j++)
{
node = map_to_node[j];
if (node > col_map_offd_AN[cnt-1])
{
col_map_offd_AN[cnt++] = node;
}
map_to_map[j] = cnt-1;
}
recv_vec_starts_AN[i+1] = cnt;
}
for (i=0; i < num_cols_offd_AN; i++)
counter[i] = -1;
AN_num_nonzeros_offd = 0;
row = 0;
for (i=0; i < num_nodes; i++)
{
AN_offd_i[i] = AN_num_nonzeros_offd;
for (j=0; j < num_functions; j++)
{
for (k=A_offd_i[row]; k < A_offd_i[row+1]; k++)
{
k_map = map_to_map[A_offd_j[k]];
if (counter[k_map] < i)
{
counter[k_map] = i;
AN_num_nonzeros_offd++;
}
}
row++;
}
}
AN_offd_i[num_nodes] = AN_num_nonzeros_offd;
}
AN_offd = hypre_CSRMatrixCreate(num_nodes,num_cols_offd_AN,
AN_num_nonzeros_offd);
hypre_CSRMatrixI(AN_offd) = AN_offd_i;
if (AN_num_nonzeros_offd)
{
AN_offd_j = hypre_CTAlloc(int, AN_num_nonzeros_offd);
AN_offd_data = hypre_CTAlloc(double, AN_num_nonzeros_offd);
hypre_CSRMatrixJ(AN_offd) = AN_offd_j;
hypre_CSRMatrixData(AN_offd) = AN_offd_data;
for (i=0; i < num_cols_offd_AN; i++)
counter[i] = -1;
index = 0;
row = 0;
AN_offd_i[0] = 0;
start_index = 0;
switch (mode)
{
case 1: /* frobenius norm */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_offd_i[row]; k < A_offd_i[row+1]; k++)
{
k_map = map_to_map[A_offd_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_offd_j[index] = k_map;
AN_offd_data[index] = A_offd_data[k]*A_offd_data[k];
index++;
}
else
{
AN_offd_data[counter[k_map]] +=
A_offd_data[k]*A_offd_data[k];
}
}
row++;
}
start_index = index;
}
for (i=0; i < AN_num_nonzeros_offd; i++)
AN_offd_data[i] = sqrt(AN_offd_data[i]);
}
break;
case 2: /* sum of abs. value of all elements in block */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_offd_i[row]; k < A_offd_i[row+1]; k++)
{
k_map = map_to_map[A_offd_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_offd_j[index] = k_map;
AN_offd_data[index] = fabs(A_offd_data[k]);
index++;
}
else
{
AN_offd_data[counter[k_map]] += fabs(A_offd_data[k]);
}
}
row++;
}
start_index = index;
}
for (i=0; i < AN_num_nonzeros_offd; i++)
AN_offd_data[i] /= num_fun2;
}
break;
case 3: /* largest element in each block (not abs. value ) */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_offd_i[row]; k < A_offd_i[row+1]; k++)
{
k_map = map_to_map[A_offd_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_offd_j[index] = k_map;
AN_offd_data[index] = A_offd_data[k];
index++;
}
else
{
if (fabs(A_offd_data[k]) >
fabs(AN_offd_data[counter[k_map]]))
AN_offd_data[counter[k_map]] = A_offd_data[k];
}
}
row++;
}
start_index = index;
}
}
break;
case 4: /* inf. norm (row-sum) */
{
data = hypre_CTAlloc(double, AN_num_nonzeros_offd*num_functions);
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_offd_i[row]; k < A_offd_i[row+1]; k++)
{
k_map = map_to_map[A_offd_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_offd_j[index] = k_map;
data[index*num_functions + j] = fabs(A_offd_data[k]);
index++;
}
else
{
data[(counter[k_map])*num_functions + j] += fabs(A_offd_data[k]);
}
}
row++;
}
start_index = index;
}
for (i=0; i < AN_num_nonzeros_offd; i++)
{
AN_offd_data[i] = data[i*num_functions];
for (j=1; j< num_functions; j++)
{
AN_offd_data[i] = hypre_max( AN_offd_data[i],data[i*num_functions+j]);
}
}
hypre_TFree(data);
}
break;
case 6: /* sum of value of all elements in block */
{
for (i=0; i < num_nodes; i++)
{
for (j=0; j < num_functions; j++)
{
for (k=A_offd_i[row]; k < A_offd_i[row+1]; k++)
{
k_map = map_to_map[A_offd_j[k]];
if (counter[k_map] < start_index)
{
counter[k_map] = index;
AN_offd_j[index] = k_map;
AN_offd_data[index] = (A_offd_data[k]);
index++;
}
else
{
AN_offd_data[counter[k_map]] += (A_offd_data[k]);
}
}
row++;
}
start_index = index;
}
}
break;
}
hypre_TFree(map_to_map);
}
if (diag_option ==1 )
{
/* make the diag entry the negative of the sum of off-diag entries (here we are adding the
off_diag contribution)*/
/* the diagonal is the first element listed in each row of AN_diag_data - */
for (i=0; i < num_nodes; i++)
{
sum = 0.0;
for (k = AN_offd_i[i]; k < AN_offd_i[i+1]; k++)
{
sum += AN_offd_data[k];
}
index = AN_diag_i[i];/* location of diag entry in data */
AN_diag_data[index] -= sum; /* subtract from current value */
}
}
AN = hypre_ParCSRMatrixCreate(comm, global_num_nodes, global_num_nodes,
row_starts_AN, row_starts_AN, num_cols_offd_AN,
AN_num_nonzeros_diag, AN_num_nonzeros_offd);
/* we already created the diag and offd matrices - so we don't need the ones
created above */
hypre_CSRMatrixDestroy(hypre_ParCSRMatrixDiag(AN));
hypre_CSRMatrixDestroy(hypre_ParCSRMatrixOffd(AN));
hypre_ParCSRMatrixDiag(AN) = AN_diag;
hypre_ParCSRMatrixOffd(AN) = AN_offd;
hypre_ParCSRMatrixColMapOffd(AN) = col_map_offd_AN;
hypre_ParCSRMatrixCommPkg(AN) = comm_pkg_AN;
new_num_cols_offd = num_functions*num_cols_offd_AN;
if (new_num_cols_offd > num_cols_offd)
{
new_col_map_offd = hypre_CTAlloc(int, new_num_cols_offd);
cnt = 0;
for (i=0; i < num_cols_offd_AN; i++)
{
for (j=0; j < num_functions; j++)
{
new_col_map_offd[cnt++] = num_functions*col_map_offd_AN[i]+j;
}
}
cnt = 0;
for (i=0; i < num_cols_offd; i++)
{
while (col_map_offd[i] > new_col_map_offd[cnt])
cnt++;
col_map_offd[i] = cnt++;
}
for (i=0; i < num_recvs+1; i++)
{
recv_vec_starts[i] = num_functions*recv_vec_starts_AN[i];
}
for (i=0; i < num_nonzeros_offd; i++)
{
j = A_offd_j[i];
A_offd_j[i] = col_map_offd[j];
}
hypre_ParCSRMatrixColMapOffd(A) = new_col_map_offd;
hypre_CSRMatrixNumCols(A_offd) = new_num_cols_offd;
hypre_TFree(col_map_offd);
}
hypre_TFree(map_to_node);
new_send_elmts_size = send_map_starts_AN[num_sends]*num_functions;
if (new_send_elmts_size > send_map_starts[num_sends])
{
new_send_map_elmts = hypre_CTAlloc(int,new_send_elmts_size);
cnt = 0;
send_map_starts[0] = 0;
for (i=0; i < num_sends; i++)
{
send_map_starts[i+1] = send_map_starts_AN[i+1]*num_functions;
for (j=send_map_starts_AN[i]; j < send_map_starts_AN[i+1]; j++)
{
for (k=0; k < num_functions; k++)
new_send_map_elmts[cnt++] = send_map_elmts_AN[j]*num_functions+k;
}
}
hypre_TFree(send_map_elmts);
hypre_ParCSRCommPkgSendMapElmts(comm_pkg) = new_send_map_elmts;
}
*AN_ptr = AN;
hypre_TFree(counter);
return (ierr);
}
/* This creates a scalar version of the CF_marker, dof_array and strength matrix (SN) */
int
hypre_BoomerAMGCreateScalarCFS(hypre_ParCSRMatrix *SN,
int *CFN_marker,
int *col_offd_SN_to_AN,
int num_functions,
int nodal,
int data,
int **dof_func_ptr,
int **CF_marker_ptr,
int **col_offd_S_to_A_ptr,
hypre_ParCSRMatrix **S_ptr)
{
MPI_Comm comm = hypre_ParCSRMatrixComm(SN);
hypre_ParCSRMatrix *S;
hypre_CSRMatrix *S_diag;
int *S_diag_i;
int *S_diag_j;
double *S_diag_data;
hypre_CSRMatrix *S_offd;
int *S_offd_i;
int *S_offd_j;
double *S_offd_data;
int *row_starts_S;
int *col_starts_S;
int *row_starts_SN = hypre_ParCSRMatrixRowStarts(SN);
int *col_starts_SN = hypre_ParCSRMatrixColStarts(SN);
hypre_CSRMatrix *SN_diag = hypre_ParCSRMatrixDiag(SN);
int *SN_diag_i = hypre_CSRMatrixI(SN_diag);
int *SN_diag_j = hypre_CSRMatrixJ(SN_diag);
double *SN_diag_data;
hypre_CSRMatrix *SN_offd = hypre_ParCSRMatrixOffd(SN);
int *SN_offd_i = hypre_CSRMatrixI(SN_offd);
int *SN_offd_j = hypre_CSRMatrixJ(SN_offd);
double *SN_offd_data;
int *CF_marker;
int *col_map_offd_SN = hypre_ParCSRMatrixColMapOffd(SN);
int *col_map_offd_S;
int *dof_func;
int num_nodes = hypre_CSRMatrixNumRows(SN_diag);
int num_variables;
hypre_ParCSRCommPkg *comm_pkg = hypre_ParCSRMatrixCommPkg(SN);
int num_sends;
int num_recvs;
int *send_procs;
int *send_map_starts;
int *send_map_elmts;
int *recv_procs;
int *recv_vec_starts;
hypre_ParCSRCommPkg *comm_pkg_S;
int *send_procs_S;
int *send_map_starts_S;
int *send_map_elmts_S;
int *recv_procs_S;
int *recv_vec_starts_S;
int *col_offd_S_to_A = NULL;
int num_coarse_nodes;
int i,j,k,k1,jj,cnt;
int row, start, end;
int num_procs;
int num_cols_offd_SN = hypre_CSRMatrixNumCols(SN_offd);
int num_cols_offd_S;
int SN_num_nonzeros_diag;
int SN_num_nonzeros_offd;
int S_num_nonzeros_diag;
int S_num_nonzeros_offd;
int global_num_vars;
int global_num_cols;
int global_num_nodes;
int ierr = 0;
MPI_Comm_size(comm, &num_procs);
num_variables = num_functions*num_nodes;
CF_marker = hypre_CTAlloc(int, num_variables);
if (nodal < 0)
{
cnt = 0;
num_coarse_nodes = 0;
for (i=0; i < num_nodes; i++)
{
if (CFN_marker[i] == 1) num_coarse_nodes++;
for (j=0; j < num_functions; j++)
CF_marker[cnt++] = CFN_marker[i];
}
dof_func = hypre_CTAlloc(int,num_coarse_nodes*num_functions);
cnt = 0;
for (i=0; i < num_nodes; i++)
{
if (CFN_marker[i] == 1)
{
for (k=0; k < num_functions; k++)
dof_func[cnt++] = k;
}
}
*dof_func_ptr = dof_func;
}
else
{
cnt = 0;
for (i=0; i < num_nodes; i++)
for (j=0; j < num_functions; j++)
CF_marker[cnt++] = CFN_marker[i];
}
*CF_marker_ptr = CF_marker;
#ifdef HYPRE_NO_GLOBAL_PARTITION
row_starts_S = hypre_CTAlloc(int,2);
for (i=0; i < 2; i++)
row_starts_S[i] = num_functions*row_starts_SN[i];
if (row_starts_SN != col_starts_SN)
{
col_starts_S = hypre_CTAlloc(int,2);
for (i=0; i < 2; i++)
col_starts_S[i] = num_functions*col_starts_SN[i];
}
else
{
col_starts_S = row_starts_S;
}
#else
row_starts_S = hypre_CTAlloc(int,num_procs+1);
for (i=0; i < num_procs+1; i++)
row_starts_S[i] = num_functions*row_starts_SN[i];
if (row_starts_SN != col_starts_SN)
{
col_starts_S = hypre_CTAlloc(int,num_procs+1);
for (i=0; i < num_procs+1; i++)
col_starts_S[i] = num_functions*col_starts_SN[i];
}
else
{
col_starts_S = row_starts_S;
}
#endif
SN_num_nonzeros_diag = SN_diag_i[num_nodes];
SN_num_nonzeros_offd = SN_offd_i[num_nodes];
global_num_nodes = hypre_ParCSRMatrixGlobalNumRows(SN);
global_num_cols = hypre_ParCSRMatrixGlobalNumCols(SN)*num_functions;
global_num_vars = global_num_nodes*num_functions;
S_num_nonzeros_diag = num_functions*SN_num_nonzeros_diag;
S_num_nonzeros_offd = num_functions*SN_num_nonzeros_offd;
num_cols_offd_S = num_functions*num_cols_offd_SN;
S = hypre_ParCSRMatrixCreate(comm, global_num_vars, global_num_cols,
row_starts_S, col_starts_S, num_cols_offd_S,
S_num_nonzeros_diag, S_num_nonzeros_offd);
S_diag = hypre_ParCSRMatrixDiag(S);
S_offd = hypre_ParCSRMatrixOffd(S);
S_diag_i = hypre_CTAlloc(int, num_variables+1);
S_offd_i = hypre_CTAlloc(int, num_variables+1);
S_diag_j = hypre_CTAlloc(int, S_num_nonzeros_diag);
hypre_CSRMatrixI(S_diag) = S_diag_i;
hypre_CSRMatrixJ(S_diag) = S_diag_j;
if (data)
{
SN_diag_data = hypre_CSRMatrixData(SN_diag);
S_diag_data = hypre_CTAlloc(double, S_num_nonzeros_diag);
hypre_CSRMatrixData(S_diag) = S_diag_data;
if (num_cols_offd_S)
{
SN_offd_data = hypre_CSRMatrixData(SN_offd);
S_offd_data = hypre_CTAlloc(double, S_num_nonzeros_offd);
hypre_CSRMatrixData(S_offd) = S_offd_data;
}
}
hypre_CSRMatrixI(S_offd) = S_offd_i;
if (comm_pkg)
{
comm_pkg_S = hypre_CTAlloc(hypre_ParCSRCommPkg,1);
hypre_ParCSRCommPkgComm(comm_pkg_S) = comm;
num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg);
hypre_ParCSRCommPkgNumSends(comm_pkg_S) = num_sends;
num_recvs = hypre_ParCSRCommPkgNumRecvs(comm_pkg);
hypre_ParCSRCommPkgNumRecvs(comm_pkg_S) = num_recvs;
send_procs = hypre_ParCSRCommPkgSendProcs(comm_pkg);
send_map_starts = hypre_ParCSRCommPkgSendMapStarts(comm_pkg);
send_map_elmts = hypre_ParCSRCommPkgSendMapElmts(comm_pkg);
recv_procs = hypre_ParCSRCommPkgRecvProcs(comm_pkg);
recv_vec_starts = hypre_ParCSRCommPkgRecvVecStarts(comm_pkg);
send_procs_S = NULL;
send_map_elmts_S = NULL;
if (num_sends)
{
send_procs_S = hypre_CTAlloc(int,num_sends);
send_map_elmts_S = hypre_CTAlloc(int,
num_functions*send_map_starts[num_sends]);
}
send_map_starts_S = hypre_CTAlloc(int,num_sends+1);
recv_vec_starts_S = hypre_CTAlloc(int,num_recvs+1);
recv_procs_S = NULL;
if (num_recvs) recv_procs_S = hypre_CTAlloc(int,num_recvs);
send_map_starts_S[0] = 0;
for (i=0; i < num_sends; i++)
{
send_procs_S[i] = send_procs[i];
send_map_starts_S[i+1] = num_functions*send_map_starts[i+1];
}
recv_vec_starts_S[0] = 0;
for (i=0; i < num_recvs; i++)
{
recv_procs_S[i] = recv_procs[i];
recv_vec_starts_S[i+1] = num_functions*recv_vec_starts[i+1];
}
cnt = 0;
for (i=0; i < send_map_starts[num_sends]; i++)
{
k1 = num_functions*send_map_elmts[i];
for (j=0; j < num_functions; j++)
{
send_map_elmts_S[cnt++] = k1+j;
}
}
hypre_ParCSRCommPkgSendProcs(comm_pkg_S) = send_procs_S;
hypre_ParCSRCommPkgSendMapStarts(comm_pkg_S) = send_map_starts_S;
hypre_ParCSRCommPkgSendMapElmts(comm_pkg_S) = send_map_elmts_S;
hypre_ParCSRCommPkgRecvProcs(comm_pkg_S) = recv_procs_S;
hypre_ParCSRCommPkgRecvVecStarts(comm_pkg_S) = recv_vec_starts_S;
hypre_ParCSRMatrixCommPkg(S) = comm_pkg_S;
}
if (num_cols_offd_S)
{
S_offd_j = hypre_CTAlloc(int, S_num_nonzeros_offd);
hypre_CSRMatrixJ(S_offd) = S_offd_j;
col_map_offd_S = hypre_CTAlloc(int, num_cols_offd_S);
cnt = 0;
for (i=0; i < num_cols_offd_SN; i++)
{
k1 = col_map_offd_SN[i]*num_functions;
for (j=0; j < num_functions; j++)
col_map_offd_S[cnt++] = k1+j;
}
hypre_ParCSRMatrixColMapOffd(S) = col_map_offd_S;
}
if (col_offd_SN_to_AN)
{
col_offd_S_to_A = hypre_CTAlloc(int, num_cols_offd_S);
cnt = 0;
for (i=0; i < num_cols_offd_SN; i++)
{
k1 = col_offd_SN_to_AN[i]*num_functions;
for (j=0; j < num_functions; j++)
col_offd_S_to_A[cnt++] = k1+j;
}
*col_offd_S_to_A_ptr = col_offd_S_to_A;
}
cnt = 0;
row = 0;
for (i=0; i < num_nodes; i++)
{
row++;
start = cnt;
for (j=SN_diag_i[i]; j < SN_diag_i[i+1]; j++)
{
jj = SN_diag_j[j];
if (data) S_diag_data[cnt] = SN_diag_data[j];
S_diag_j[cnt++] = jj*num_functions;
}
end = cnt;
S_diag_i[row] = cnt;
for (k1=1; k1 < num_functions; k1++)
{
row++;
for (k=start; k < end; k++)
{
if (data) S_diag_data[cnt] = S_diag_data[k];
S_diag_j[cnt++] = S_diag_j[k]+k1;
}
S_diag_i[row] = cnt;
}
}
cnt = 0;
row = 0;
for (i=0; i < num_nodes; i++)
{
row++;
start = cnt;
for (j=SN_offd_i[i]; j < SN_offd_i[i+1]; j++)
{
jj = SN_offd_j[j];
if (data) S_offd_data[cnt] = SN_offd_data[j];
S_offd_j[cnt++] = jj*num_functions;
}
end = cnt;
S_offd_i[row] = cnt;
for (k1=1; k1 < num_functions; k1++)
{
row++;
for (k=start; k < end; k++)
{
if (data) S_offd_data[cnt] = S_offd_data[k];
S_offd_j[cnt++] = S_offd_j[k]+k1;
}
S_offd_i[row] = cnt;
}
}
*S_ptr = S;
return (ierr);
}
/* This function just finds the scalaer CF_marker and dof_func */
int
hypre_BoomerAMGCreateScalarCF(int *CFN_marker,
int num_functions,
int num_nodes,
int **dof_func_ptr,
int **CF_marker_ptr)
{
int *CF_marker;
int *dof_func;
int num_variables;
int num_coarse_nodes;
int i,j,k,cnt;
int ierr = 0;
num_variables = num_functions*num_nodes;
CF_marker = hypre_CTAlloc(int, num_variables);
cnt = 0;
num_coarse_nodes = 0;
for (i=0; i < num_nodes; i++)
{
if (CFN_marker[i] == 1) num_coarse_nodes++;
for (j=0; j < num_functions; j++)
CF_marker[cnt++] = CFN_marker[i];
}
dof_func = hypre_CTAlloc(int,num_coarse_nodes*num_functions);
cnt = 0;
for (i=0; i < num_nodes; i++)
{
if (CFN_marker[i] == 1)
{
for (k=0; k < num_functions; k++)
dof_func[cnt++] = k;
}
}
*dof_func_ptr = dof_func;
*CF_marker_ptr = CF_marker;
return (ierr);
}