|
IFPACK Development
|
00001 /*@HEADER 00002 // *********************************************************************** 00003 // 00004 // Ifpack: Object-Oriented Algebraic Preconditioner Package 00005 // Copyright (2009) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 00028 */ 00029 00030 #include "Numbering_dh.h" 00031 #include "Mat_dh.h" 00032 #include "Hash_i_dh.h" 00033 #include "Mem_dh.h" 00034 #include "shellSort_dh.h" 00035 #include "Parser_dh.h" 00036 00037 00038 #undef __FUNC__ 00039 #define __FUNC__ "Numbering_dhCreate" 00040 void 00041 Numbering_dhCreate (Numbering_dh * numb) 00042 { 00043 START_FUNC_DH 00044 struct _numbering_dh *tmp = 00045 (struct _numbering_dh *) MALLOC_DH (sizeof (struct _numbering_dh)); 00046 CHECK_V_ERROR; 00047 *numb = tmp; 00048 00049 tmp->size = 0; 00050 tmp->first = 0; 00051 tmp->m = 0; 00052 tmp->num_ext = 0; 00053 tmp->num_extLo = 0; 00054 tmp->num_extHi = 0; 00055 tmp->idx_ext = NULL; 00056 tmp->idx_extLo = NULL; 00057 tmp->idx_extHi = NULL; 00058 tmp->idx_ext = NULL; 00059 tmp->debug = Parser_dhHasSwitch (parser_dh, "-debug_Numbering"); 00060 END_FUNC_DH} 00061 00062 #undef __FUNC__ 00063 #define __FUNC__ "Numbering_dhDestroy" 00064 void 00065 Numbering_dhDestroy (Numbering_dh numb) 00066 { 00067 START_FUNC_DH if (numb->global_to_local != NULL) 00068 { 00069 Hash_i_dhDestroy (numb->global_to_local); 00070 CHECK_V_ERROR; 00071 } 00072 if (numb->idx_ext != NULL) 00073 { 00074 FREE_DH (numb->idx_ext); 00075 CHECK_V_ERROR; 00076 } 00077 FREE_DH (numb); 00078 CHECK_V_ERROR; 00079 END_FUNC_DH} 00080 00081 00082 /* 00083 The internal indices are numbered 0 to nlocal-1 so they do not 00084 need to be sorted. The external indices are sorted so that 00085 the indices from a given processor are stored contiguously. 00086 Then in the matvec, no reordering of the data is needed. 00087 */ 00088 00089 #undef __FUNC__ 00090 #define __FUNC__ "Numbering_dhSetup" 00091 void 00092 Numbering_dhSetup (Numbering_dh numb, Mat_dh mat) 00093 { 00094 START_FUNC_DH int i, len, *cval = mat->cval; 00095 int num_ext, num_extLo, num_extHi; 00096 int m = mat->m, size; 00097 Hash_i_dh global_to_local_hash; 00098 int first = mat->beg_row, last = first + m; 00099 int *idx_ext; 00100 int data; 00101 /* int debug = false; */ 00102 00103 /* if (logFile != NULL && numb->debug) debug = true; */ 00104 00105 numb->first = first; 00106 numb->m = m; 00107 00108 /* Allocate space for look-up tables */ 00109 00110 /* initial guess: there are at most 'm' external indices */ 00111 numb->size = size = m; 00112 Hash_i_dhCreate (&(numb->global_to_local), m); 00113 CHECK_V_ERROR; 00114 00115 global_to_local_hash = numb->global_to_local; 00116 idx_ext = numb->idx_ext = (int *) MALLOC_DH (size * sizeof (int)); 00117 CHECK_V_ERROR; 00118 00119 /* find all external indices; at the end of this block, 00120 idx_ext[] will contain an unsorted list of external indices. 00121 */ 00122 len = mat->rp[m]; 00123 num_ext = num_extLo = num_extHi = 0; 00124 for (i = 0; i < len; i++) 00125 { /* for each nonzero "index" in the matrix */ 00126 int index = cval[i]; 00127 00128 /* Only interested in external indices */ 00129 if (index < first || index >= last) 00130 { 00131 00132 /* if index hasn't been previously inserted, do so now. */ 00133 data = Hash_i_dhLookup (global_to_local_hash, cval[i]); 00134 CHECK_V_ERROR; 00135 00136 if (data == -1) 00137 { /* index hasn't been inserted, so do so now */ 00138 00139 /* reallocate idx_ext array if we're out of 00140 space. The global_to_local hash table may also need 00141 to be enlarged, but the hash object will take care of that. 00142 */ 00143 if (m + num_ext >= size) 00144 { 00145 int newSize = size * 1.5; /* heuristic */ 00146 int *tmp = (int *) MALLOC_DH (newSize * sizeof (int)); 00147 CHECK_V_ERROR; 00148 memcpy (tmp, idx_ext, size * sizeof (size)); 00149 FREE_DH (idx_ext); 00150 CHECK_V_ERROR; 00151 size = numb->size = newSize; 00152 numb->idx_ext = idx_ext = tmp; 00153 SET_INFO ("reallocated ext_idx[]"); 00154 } 00155 00156 /* insert external index */ 00157 Hash_i_dhInsert (global_to_local_hash, index, num_ext); 00158 CHECK_V_ERROR; 00159 idx_ext[num_ext] = index; 00160 00161 num_ext++; 00162 if (index < first) 00163 { 00164 num_extLo++; 00165 } 00166 else 00167 { 00168 num_extHi++; 00169 } 00170 } 00171 } 00172 } 00173 00174 numb->num_ext = num_ext; 00175 numb->num_extLo = num_extLo; 00176 numb->num_extHi = num_extHi; 00177 numb->idx_extLo = idx_ext; 00178 numb->idx_extHi = idx_ext + num_extLo; 00179 00180 /* sort the list of external indices, then redo the hash 00181 table; the table is used to convert external indices 00182 in Numbering_dhGlobalToLocal() 00183 */ 00184 shellSort_int (num_ext, idx_ext); 00185 00186 Hash_i_dhReset (global_to_local_hash); 00187 CHECK_V_ERROR; 00188 for (i = 0; i < num_ext; i++) 00189 { 00190 Hash_i_dhInsert (global_to_local_hash, idx_ext[i], i + m); 00191 CHECK_V_ERROR; 00192 } 00193 END_FUNC_DH} 00194 00195 #undef __FUNC__ 00196 #define __FUNC__ "Numbering_dhGlobalToLocal" 00197 void 00198 Numbering_dhGlobalToLocal (Numbering_dh numb, int len, 00199 int *global, int *local) 00200 { 00201 START_FUNC_DH int i; 00202 int first = numb->first; 00203 int last = first + numb->m; 00204 int data; 00205 Hash_i_dh global_to_local = numb->global_to_local; 00206 00207 for (i = 0; i < len; i++) 00208 { 00209 int idxGlobal = global[i]; 00210 if (idxGlobal >= first && idxGlobal < last) 00211 { 00212 local[i] = idxGlobal - first; 00213 /* note: for matvec setup, numb->num_extLo = 0. */ 00214 } 00215 else 00216 { 00217 data = Hash_i_dhLookup (global_to_local, idxGlobal); 00218 CHECK_V_ERROR; 00219 if (data == -1) 00220 { 00221 sprintf (msgBuf_dh, "global index %i not found in map\n", 00222 idxGlobal); 00223 SET_V_ERROR (msgBuf_dh); 00224 } 00225 else 00226 { 00227 local[i] = data; 00228 } 00229 } 00230 } 00231 END_FUNC_DH}
1.7.4