| [0b990d] | 1 | //
 | 
|---|
 | 2 | // distrect.cc
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1996 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit is distributed in the hope that it will be useful,
 | 
|---|
 | 17 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 18 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 19 | // GNU Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #include <iostream>
 | 
|---|
 | 29 | #include <iomanip>
 | 
|---|
 | 30 | #include <stdlib.h>
 | 
|---|
 | 31 | #include <math.h>
 | 
|---|
 | 32 | 
 | 
|---|
 | 33 | #include <util/misc/formio.h>
 | 
|---|
 | 34 | #include <util/keyval/keyval.h>
 | 
|---|
 | 35 | #include <math/scmat/dist.h>
 | 
|---|
 | 36 | #include <math/scmat/cmatrix.h>
 | 
|---|
 | 37 | #include <math/scmat/elemop.h>
 | 
|---|
 | 38 | 
 | 
|---|
 | 39 | using namespace std;
 | 
|---|
 | 40 | using namespace sc;
 | 
|---|
 | 41 | 
 | 
|---|
 | 42 | #define DEBUG 0
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 45 | 
 | 
|---|
 | 46 | static void
 | 
|---|
 | 47 | fail(const char *m)
 | 
|---|
 | 48 | {
 | 
|---|
 | 49 |   ExEnv::errn() << indent << "distrect.cc: error: " << m << endl;
 | 
|---|
 | 50 |   abort();
 | 
|---|
 | 51 | }
 | 
|---|
 | 52 | 
 | 
|---|
 | 53 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 54 | // DistSCMatrix member functions
 | 
|---|
 | 55 | 
 | 
|---|
 | 56 | static ClassDesc DistSCMatrix_cd(
 | 
|---|
 | 57 |   typeid(DistSCMatrix),"DistSCMatrix",1,"public SCMatrix",
 | 
|---|
 | 58 |   0, 0, 0);
 | 
|---|
 | 59 | 
 | 
|---|
 | 60 | DistSCMatrix::DistSCMatrix(const RefSCDimension&a,const RefSCDimension&b,
 | 
|---|
 | 61 |                            DistSCMatrixKit*k):
 | 
|---|
 | 62 |   SCMatrix(a,b,k)
 | 
|---|
 | 63 | {
 | 
|---|
 | 64 |   init_blocklist();
 | 
|---|
 | 65 | }
 | 
|---|
 | 66 | 
 | 
|---|
 | 67 | int
 | 
|---|
 | 68 | DistSCMatrix::block_to_node(int i, int j) const
 | 
|---|
 | 69 | {
 | 
|---|
 | 70 |   return (i*d2->blocks()->nblock() + j)%messagegrp()->n();
 | 
|---|
 | 71 | }
 | 
|---|
 | 72 | 
 | 
|---|
 | 73 | Ref<SCMatrixBlock>
 | 
|---|
 | 74 | DistSCMatrix::block_to_block(int i, int j) const
 | 
|---|
 | 75 | {
 | 
|---|
 | 76 |   int offset = i*d2->blocks()->nblock() + j;
 | 
|---|
 | 77 |   int nproc = messagegrp()->n();
 | 
|---|
 | 78 | 
 | 
|---|
 | 79 |   if ((offset%nproc) != messagegrp()->me()) return 0;
 | 
|---|
 | 80 | 
 | 
|---|
 | 81 |   SCMatrixBlockListIter I;
 | 
|---|
 | 82 |   for (I=blocklist->begin(); I!=blocklist->end(); I++) {
 | 
|---|
 | 83 |       if (I.block()->blocki == i && I.block()->blockj == j)
 | 
|---|
 | 84 |           return I.block();
 | 
|---|
 | 85 |     }
 | 
|---|
 | 86 | 
 | 
|---|
 | 87 |   ExEnv::errn() << indent << "DistSCMatrix::block_to_block: internal error" << endl;
 | 
|---|
 | 88 |   abort();
 | 
|---|
 | 89 |   return 0;
 | 
|---|
 | 90 | }
 | 
|---|
 | 91 | 
 | 
|---|
 | 92 | double *
 | 
|---|
 | 93 | DistSCMatrix::find_element(int i, int j) const
 | 
|---|
 | 94 | {
 | 
|---|
 | 95 |   int bi, oi;
 | 
|---|
 | 96 |   d1->blocks()->elem_to_block(i, bi, oi);
 | 
|---|
 | 97 | 
 | 
|---|
 | 98 |   int bj, oj;
 | 
|---|
 | 99 |   d2->blocks()->elem_to_block(j, bj, oj);
 | 
|---|
 | 100 | 
 | 
|---|
 | 101 |   Ref<SCMatrixRectBlock> blk
 | 
|---|
 | 102 |       = dynamic_cast<SCMatrixRectBlock*>(block_to_block(bi, bj).pointer());
 | 
|---|
 | 103 |   if (blk.nonnull()) {
 | 
|---|
 | 104 |       return &blk->data[oi*(blk->jend-blk->jstart)+oj];
 | 
|---|
 | 105 |     }
 | 
|---|
 | 106 |   else {
 | 
|---|
 | 107 |       return 0;
 | 
|---|
 | 108 |     }
 | 
|---|
 | 109 | }
 | 
|---|
 | 110 | 
 | 
|---|
 | 111 | int
 | 
|---|
 | 112 | DistSCMatrix::element_to_node(int i, int j) const
 | 
|---|
 | 113 | {
 | 
|---|
 | 114 |   int bi, oi;
 | 
|---|
 | 115 |   d1->blocks()->elem_to_block(i, bi, oi);
 | 
|---|
 | 116 | 
 | 
|---|
 | 117 |   int bj, oj;
 | 
|---|
 | 118 |   d2->blocks()->elem_to_block(j, bj, oj);
 | 
|---|
 | 119 | 
 | 
|---|
 | 120 |   return block_to_node(bi,bj);
 | 
|---|
 | 121 | }
 | 
|---|
 | 122 | 
 | 
|---|
 | 123 | void
 | 
|---|
 | 124 | DistSCMatrix::init_blocklist()
 | 
|---|
 | 125 | {
 | 
|---|
 | 126 |   int i, j, index;
 | 
|---|
 | 127 |   int me = messagegrp()->me();
 | 
|---|
 | 128 |   blocklist = new SCMatrixBlockList;
 | 
|---|
 | 129 |   for (i=0, index=0; i<d1->blocks()->nblock(); i++) {
 | 
|---|
 | 130 |       for (j=0; j<d2->blocks()->nblock(); j++, index++) {
 | 
|---|
 | 131 |           if (block_to_node(i,j) == me) {
 | 
|---|
 | 132 |               Ref<SCMatrixBlock> b
 | 
|---|
 | 133 |                   = new SCMatrixRectBlock(d1->blocks()->start(i),
 | 
|---|
 | 134 |                                           d1->blocks()->fence(i),
 | 
|---|
 | 135 |                                           d2->blocks()->start(j),
 | 
|---|
 | 136 |                                           d2->blocks()->fence(j));
 | 
|---|
 | 137 |               b->blocki = i;
 | 
|---|
 | 138 |               b->blockj = j;
 | 
|---|
 | 139 |               blocklist->append(b);
 | 
|---|
 | 140 |             }
 | 
|---|
 | 141 |         }
 | 
|---|
 | 142 |     }
 | 
|---|
 | 143 | }
 | 
|---|
 | 144 | 
 | 
|---|
 | 145 | DistSCMatrix::~DistSCMatrix()
 | 
|---|
 | 146 | {
 | 
|---|
 | 147 | }
 | 
|---|
 | 148 | 
 | 
|---|
 | 149 | double
 | 
|---|
 | 150 | DistSCMatrix::get_element(int i,int j) const
 | 
|---|
 | 151 | {
 | 
|---|
 | 152 |   double res;
 | 
|---|
 | 153 |   double *e = find_element(i,j);
 | 
|---|
 | 154 |   if (e) {
 | 
|---|
 | 155 |       res = *e;
 | 
|---|
 | 156 |       messagegrp()->bcast(res, messagegrp()->me());
 | 
|---|
 | 157 |     }
 | 
|---|
 | 158 |   else {
 | 
|---|
 | 159 |       messagegrp()->bcast(res, element_to_node(i, j));
 | 
|---|
 | 160 |     }
 | 
|---|
 | 161 |   return res;
 | 
|---|
 | 162 | }
 | 
|---|
 | 163 | 
 | 
|---|
 | 164 | void
 | 
|---|
 | 165 | DistSCMatrix::set_element(int i,int j,double a)
 | 
|---|
 | 166 | {
 | 
|---|
 | 167 |   double *e = find_element(i,j);
 | 
|---|
 | 168 |   if (e) {
 | 
|---|
 | 169 |       *e = a;
 | 
|---|
 | 170 |     }
 | 
|---|
 | 171 | }
 | 
|---|
 | 172 | 
 | 
|---|
 | 173 | void
 | 
|---|
 | 174 | DistSCMatrix::accumulate_element(int i,int j,double a)
 | 
|---|
 | 175 | {
 | 
|---|
 | 176 |   double *e = find_element(i,j);
 | 
|---|
 | 177 |   if (e) {
 | 
|---|
 | 178 |       *e += a;
 | 
|---|
 | 179 |     }
 | 
|---|
 | 180 | }
 | 
|---|
 | 181 | 
 | 
|---|
 | 182 | SCMatrix *
 | 
|---|
 | 183 | DistSCMatrix::get_subblock(int br, int er, int bc, int ec)
 | 
|---|
 | 184 | {
 | 
|---|
 | 185 |   error("get_subblock");
 | 
|---|
 | 186 |   return 0;
 | 
|---|
 | 187 | }
 | 
|---|
 | 188 | 
 | 
|---|
 | 189 | void
 | 
|---|
 | 190 | DistSCMatrix::assign_subblock(SCMatrix*sb, int br, int er, int bc, int ec,
 | 
|---|
 | 191 |                               int source_br, int source_bc)
 | 
|---|
 | 192 | {
 | 
|---|
 | 193 |   error("assign_subblock");
 | 
|---|
 | 194 | }
 | 
|---|
 | 195 | 
 | 
|---|
 | 196 | void
 | 
|---|
 | 197 | DistSCMatrix::accumulate_subblock(SCMatrix*sb, int br, int er, int bc, int ec,
 | 
|---|
 | 198 |                                   int source_br, int source_bc)
 | 
|---|
 | 199 | {
 | 
|---|
 | 200 |   error("accumulate_subblock");
 | 
|---|
 | 201 | }
 | 
|---|
 | 202 | 
 | 
|---|
 | 203 | SCVector *
 | 
|---|
 | 204 | DistSCMatrix::get_row(int i)
 | 
|---|
 | 205 | {
 | 
|---|
 | 206 |   error("get_row");
 | 
|---|
 | 207 |   return 0;
 | 
|---|
 | 208 | }
 | 
|---|
 | 209 | 
 | 
|---|
 | 210 | void
 | 
|---|
 | 211 | DistSCMatrix::assign_row(SCVector *v, int i)
 | 
|---|
 | 212 | {
 | 
|---|
 | 213 |   error("assign_row");
 | 
|---|
 | 214 | }
 | 
|---|
 | 215 | 
 | 
|---|
 | 216 | void
 | 
|---|
 | 217 | DistSCMatrix::accumulate_row(SCVector *v, int i)
 | 
|---|
 | 218 | {
 | 
|---|
 | 219 |   error("accumulate_row");
 | 
|---|
 | 220 | }
 | 
|---|
 | 221 | 
 | 
|---|
 | 222 | SCVector *
 | 
|---|
 | 223 | DistSCMatrix::get_column(int i)
 | 
|---|
 | 224 | {
 | 
|---|
 | 225 |   double *col = new double[nrow()];
 | 
|---|
 | 226 |   
 | 
|---|
 | 227 |   Ref<SCMatrixSubblockIter> iter = local_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 228 |   for (iter->begin(); iter->ready(); iter->next()) {
 | 
|---|
 | 229 |     SCMatrixRectBlock *b = dynamic_cast<SCMatrixRectBlock*>(iter->block());
 | 
|---|
 | 230 |     if (b->jstart > i || b->jend <= i)
 | 
|---|
 | 231 |       continue;
 | 
|---|
 | 232 | 
 | 
|---|
 | 233 |     int joff = i-b->jstart;
 | 
|---|
 | 234 |     int jlen = b->jend-b->jstart;
 | 
|---|
 | 235 |     int ist = 0;
 | 
|---|
 | 236 |     
 | 
|---|
 | 237 |     for (int ii=b->istart; ii < b->iend; ii++,ist++)
 | 
|---|
 | 238 |       col[ii] = b->data[ist*jlen+joff];
 | 
|---|
 | 239 |   }
 | 
|---|
 | 240 |   
 | 
|---|
 | 241 |   SCVector * rcol = kit_->vector(rowdim());
 | 
|---|
 | 242 |   rcol->assign(col);
 | 
|---|
 | 243 | 
 | 
|---|
 | 244 |   delete[] col;
 | 
|---|
 | 245 | 
 | 
|---|
 | 246 |   return rcol;
 | 
|---|
 | 247 | }
 | 
|---|
 | 248 | 
 | 
|---|
 | 249 | void
 | 
|---|
 | 250 | DistSCMatrix::assign_column(SCVector *v, int i)
 | 
|---|
 | 251 | {
 | 
|---|
 | 252 |   error("assign_column");
 | 
|---|
 | 253 | }
 | 
|---|
 | 254 | 
 | 
|---|
 | 255 | void
 | 
|---|
 | 256 | DistSCMatrix::accumulate_column(SCVector *v, int i)
 | 
|---|
 | 257 | {
 | 
|---|
 | 258 |   error("accumulate_column");
 | 
|---|
 | 259 | }
 | 
|---|
 | 260 | 
 | 
|---|
 | 261 | void
 | 
|---|
 | 262 | DistSCMatrix::accumulate(const SCMatrix*a)
 | 
|---|
 | 263 | {
 | 
|---|
 | 264 |   // make sure that the argument is of the correct type
 | 
|---|
 | 265 |   const DistSCMatrix* la
 | 
|---|
 | 266 |     = require_dynamic_cast<const DistSCMatrix*>(a,"DistSCMatrix::accumulate");
 | 
|---|
 | 267 | 
 | 
|---|
 | 268 |   // make sure that the dimensions match
 | 
|---|
 | 269 |   if (!rowdim()->equiv(la->rowdim()) || !coldim()->equiv(la->coldim())) {
 | 
|---|
 | 270 |       ExEnv::errn() << indent << "DistSCMatrix::accumulate(SCMatrix*a): "
 | 
|---|
 | 271 |            << "dimensions don't match\n";
 | 
|---|
 | 272 |       abort();
 | 
|---|
 | 273 |     }
 | 
|---|
 | 274 | 
 | 
|---|
 | 275 |   SCMatrixBlockListIter i1, i2;
 | 
|---|
 | 276 |   for (i1=la->blocklist->begin(),i2=blocklist->begin();
 | 
|---|
 | 277 |        i1!=la->blocklist->end() && i2!=blocklist->end();
 | 
|---|
 | 278 |        i1++,i2++) {
 | 
|---|
 | 279 |       int n = i1.block()->ndat();
 | 
|---|
 | 280 |       if (n != i2.block()->ndat()) {
 | 
|---|
 | 281 |           ExEnv::errn() << indent
 | 
|---|
 | 282 |                << "DistSCMatrixListSubblockIter::accumulate block mismatch: "
 | 
|---|
 | 283 |                << "internal error" << endl;
 | 
|---|
 | 284 |           abort();
 | 
|---|
 | 285 |         }
 | 
|---|
 | 286 |       double *dat1 = i1.block()->dat();
 | 
|---|
 | 287 |       double *dat2 = i2.block()->dat();
 | 
|---|
 | 288 |       for (int i=0; i<n; i++) {
 | 
|---|
 | 289 |           dat2[i] += dat1[i];
 | 
|---|
 | 290 |         }
 | 
|---|
 | 291 |     }
 | 
|---|
 | 292 | }
 | 
|---|
 | 293 | 
 | 
|---|
 | 294 | void
 | 
|---|
 | 295 | DistSCMatrix::accumulate(const SymmSCMatrix*a)
 | 
|---|
 | 296 | {
 | 
|---|
 | 297 |   // make sure that the argument is of the correct type
 | 
|---|
 | 298 |   const DistSymmSCMatrix* la
 | 
|---|
 | 299 |     = require_dynamic_cast<const DistSymmSCMatrix*>(a,"DistSCMatrix::accumulate");
 | 
|---|
 | 300 | 
 | 
|---|
 | 301 |   // make sure that the dimensions match
 | 
|---|
 | 302 |   if (!rowdim()->equiv(la->dim()) || !coldim()->equiv(la->dim())) {
 | 
|---|
 | 303 |       ExEnv::errn() << indent << "DistSCMatrix::accumulate(SCMatrix*a): "
 | 
|---|
 | 304 |            << "dimensions don't match\n";
 | 
|---|
 | 305 |       abort();
 | 
|---|
 | 306 |     }
 | 
|---|
 | 307 | 
 | 
|---|
 | 308 |   Ref<SCMatrixSubblockIter> I = ((SymmSCMatrix*)a)->all_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 309 |   for (I->begin(); I->ready(); I->next()) {
 | 
|---|
 | 310 |       Ref<SCMatrixBlock> block = I->block();
 | 
|---|
 | 311 |       if (DEBUG)
 | 
|---|
 | 312 |           ExEnv::outn() << messagegrp()->me() << ": "
 | 
|---|
 | 313 |                << block->class_name()
 | 
|---|
 | 314 |                << "(" << block->blocki << ", " << block->blockj << ")"
 | 
|---|
 | 315 |                << endl;
 | 
|---|
 | 316 |       // see if i've got this block
 | 
|---|
 | 317 |       Ref<SCMatrixBlock> localblock
 | 
|---|
 | 318 |           = block_to_block(block->blocki,block->blockj);
 | 
|---|
 | 319 |       if (localblock.nonnull()) {
 | 
|---|
 | 320 |           // the diagonal blocks require special handling
 | 
|---|
 | 321 |           if (block->blocki == block->blockj) {
 | 
|---|
 | 322 |               int n = rowblocks()->size(block->blocki);
 | 
|---|
 | 323 |               double *dat1 = block->dat();
 | 
|---|
 | 324 |               double *dat2 = localblock->dat();
 | 
|---|
 | 325 |               for (int i=0; i<n; i++) {
 | 
|---|
 | 326 |                   for (int j=0; j<i; j++) {
 | 
|---|
 | 327 |                       double tmp = *dat1;
 | 
|---|
 | 328 |                       dat2[i*n+j] += tmp;
 | 
|---|
 | 329 |                       dat2[j*n+i] += tmp;
 | 
|---|
 | 330 |                       dat1++;
 | 
|---|
 | 331 |                     }
 | 
|---|
 | 332 |                   dat2[i*n+i] = *dat1++;
 | 
|---|
 | 333 |                 }
 | 
|---|
 | 334 |             }
 | 
|---|
 | 335 |           else {
 | 
|---|
 | 336 |               int n = block->ndat();
 | 
|---|
 | 337 |               double *dat1 = block->dat();
 | 
|---|
 | 338 |               double *dat2 = localblock->dat();
 | 
|---|
 | 339 |               for (int i=0; i<n; i++) {
 | 
|---|
 | 340 |                   dat2[i] += dat1[i];
 | 
|---|
 | 341 |                 }
 | 
|---|
 | 342 |             }
 | 
|---|
 | 343 |         }
 | 
|---|
 | 344 |       // now for the transpose
 | 
|---|
 | 345 |       if (block->blocki != block->blockj) {
 | 
|---|
 | 346 |           localblock = block_to_block(block->blockj,block->blocki);
 | 
|---|
 | 347 |           if (localblock.nonnull()) {
 | 
|---|
 | 348 |               int nr = rowblocks()->size(block->blocki);
 | 
|---|
 | 349 |               int nc = rowblocks()->size(block->blockj);
 | 
|---|
 | 350 |               double *dat1 = block->dat();
 | 
|---|
 | 351 |               double *dat2 = localblock->dat();
 | 
|---|
 | 352 |               for (int i=0; i<nr; i++) {
 | 
|---|
 | 353 |                   for (int j=0; j<nc; j++) {
 | 
|---|
 | 354 |                       dat2[j*nr+i] += *dat1++;
 | 
|---|
 | 355 |                     }
 | 
|---|
 | 356 |                 }
 | 
|---|
 | 357 |             }
 | 
|---|
 | 358 |         }
 | 
|---|
 | 359 |     }
 | 
|---|
 | 360 | }
 | 
|---|
 | 361 | 
 | 
|---|
 | 362 | void
 | 
|---|
 | 363 | DistSCMatrix::accumulate(const DiagSCMatrix*a)
 | 
|---|
 | 364 | {
 | 
|---|
 | 365 |   // make sure that the argument is of the correct type
 | 
|---|
 | 366 |   const DistDiagSCMatrix* la
 | 
|---|
 | 367 |     = require_dynamic_cast<const DistDiagSCMatrix*>(a,"DistSCMatrix::accumulate");
 | 
|---|
 | 368 | 
 | 
|---|
 | 369 |   // make sure that the dimensions match
 | 
|---|
 | 370 |   if (!rowdim()->equiv(la->dim()) || !coldim()->equiv(la->dim())) {
 | 
|---|
 | 371 |       ExEnv::errn() << indent << "DistSCMatrix::accumulate(SCMatrix*a): "
 | 
|---|
 | 372 |            << "dimensions don't match\n";
 | 
|---|
 | 373 |       abort();
 | 
|---|
 | 374 |     }
 | 
|---|
 | 375 | 
 | 
|---|
 | 376 |   Ref<SCMatrixSubblockIter> I = ((DiagSCMatrix*)a)->all_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 377 |   for (I->begin(); I->ready(); I->next()) {
 | 
|---|
 | 378 |       Ref<SCMatrixBlock> block = I->block();
 | 
|---|
 | 379 |       // see if i've got this block
 | 
|---|
 | 380 |       Ref<SCMatrixBlock> localblock
 | 
|---|
 | 381 |           = block_to_block(block->blocki,block->blockj);
 | 
|---|
 | 382 |       if (localblock.nonnull()) {
 | 
|---|
 | 383 |           int n = rowblocks()->size(block->blocki);
 | 
|---|
 | 384 |           double *dat1 = block->dat();
 | 
|---|
 | 385 |           double *dat2 = localblock->dat();
 | 
|---|
 | 386 |           for (int i=0; i<n; i++) {
 | 
|---|
 | 387 |               dat2[i*n+i] += *dat1++;
 | 
|---|
 | 388 |             }
 | 
|---|
 | 389 |         }
 | 
|---|
 | 390 |     }
 | 
|---|
 | 391 | }
 | 
|---|
 | 392 | 
 | 
|---|
 | 393 | void
 | 
|---|
 | 394 | DistSCMatrix::accumulate(const SCVector*a)
 | 
|---|
 | 395 | {
 | 
|---|
 | 396 |   // make sure that the argument is of the correct type
 | 
|---|
 | 397 |   const DistSCVector* la
 | 
|---|
 | 398 |     = require_dynamic_cast<const DistSCVector*>(a,"DistSCMatrix::accumulate");
 | 
|---|
 | 399 | 
 | 
|---|
 | 400 |   // make sure that the dimensions match
 | 
|---|
 | 401 |   if (!((rowdim()->equiv(la->dim()) && coldim()->n() == 1)
 | 
|---|
 | 402 |         || (coldim()->equiv(la->dim()) && rowdim()->n() == 1))) {
 | 
|---|
 | 403 |       ExEnv::errn() << indent << "DistSCMatrix::accumulate(SCVector*a): "
 | 
|---|
 | 404 |            << "dimensions don't match\n";
 | 
|---|
 | 405 |       abort();
 | 
|---|
 | 406 |     }
 | 
|---|
 | 407 | 
 | 
|---|
 | 408 |   SCMatrixBlockListIter I, J;
 | 
|---|
 | 409 |   for (I = blocklist->begin(), J = la->blocklist->begin();
 | 
|---|
 | 410 |        I != blocklist->end() && J != la->blocklist->end();
 | 
|---|
 | 411 |        I++,J++) {
 | 
|---|
 | 412 |       int n = I.block()->ndat();
 | 
|---|
 | 413 |       if (n != J.block()->ndat()) {
 | 
|---|
 | 414 |           ExEnv::errn() << indent << "DistSCMatrix::accumulate(SCVector*a): "
 | 
|---|
 | 415 |                << "block lists do not match" << endl;
 | 
|---|
 | 416 |           abort();
 | 
|---|
 | 417 |         }
 | 
|---|
 | 418 |       double *dati = I.block()->dat();
 | 
|---|
 | 419 |       double *datj = J.block()->dat();
 | 
|---|
 | 420 |       for (int i=0; i<n; i++) dati[i] += datj[i];
 | 
|---|
 | 421 |     }
 | 
|---|
 | 422 | }
 | 
|---|
 | 423 | 
 | 
|---|
 | 424 | void
 | 
|---|
 | 425 | DistSCMatrix::accumulate_product_rr(SCMatrix*pa,SCMatrix*pb)
 | 
|---|
 | 426 | {
 | 
|---|
 | 427 |   const char* name = "DistSCMatrix::accumulate_product_rr";
 | 
|---|
 | 428 |   // make sure that the arguments are of the correct type
 | 
|---|
 | 429 |   DistSCMatrix* a = require_dynamic_cast<DistSCMatrix*>(pa,name);
 | 
|---|
 | 430 |   DistSCMatrix* b = require_dynamic_cast<DistSCMatrix*>(pb,name);
 | 
|---|
 | 431 | 
 | 
|---|
 | 432 |   // make sure that the dimensions match
 | 
|---|
 | 433 |   if (!rowdim()->equiv(a->rowdim()) || !coldim()->equiv(b->coldim()) ||
 | 
|---|
 | 434 |       !a->coldim()->equiv(b->rowdim())) {
 | 
|---|
 | 435 |       ExEnv::errn() << indent
 | 
|---|
 | 436 |            << "DistSCMatrix::accumulate_product_rr(SCMatrix*a,SCMatrix*b): "
 | 
|---|
 | 437 |            << "dimensions don't match\n";
 | 
|---|
 | 438 |       ExEnv::err0() << indent << "rowdim():" << endl;
 | 
|---|
 | 439 |       rowdim().print();
 | 
|---|
 | 440 |       ExEnv::err0() << indent << "coldim():" << endl;
 | 
|---|
 | 441 |       coldim().print();
 | 
|---|
 | 442 |       ExEnv::err0() << indent << "a->rowdim():" << endl;
 | 
|---|
 | 443 |       a->rowdim().print();
 | 
|---|
 | 444 |       ExEnv::err0() << indent << "a->coldim():" << endl;
 | 
|---|
 | 445 |       a->coldim().print();
 | 
|---|
 | 446 |       ExEnv::err0() << indent << "b->rowdim():" << endl;
 | 
|---|
 | 447 |       b->rowdim().print();
 | 
|---|
 | 448 |       ExEnv::err0() << indent << "b->coldim():" << endl;
 | 
|---|
 | 449 |       b->coldim().print();
 | 
|---|
 | 450 |       abort();
 | 
|---|
 | 451 |     }
 | 
|---|
 | 452 | 
 | 
|---|
 | 453 |   // i need this in row form and a in row form
 | 
|---|
 | 454 |   create_vecform(Row);
 | 
|---|
 | 455 |   vecform_zero();
 | 
|---|
 | 456 |   a->create_vecform(Row);
 | 
|---|
 | 457 |   a->vecform_op(CopyToVec);
 | 
|---|
 | 458 | 
 | 
|---|
 | 459 |   Ref<SCMatrixSubblockIter> I = b->all_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 460 |   for (I->begin(); I->ready(); I->next()) {
 | 
|---|
 | 461 |       Ref<SCMatrixRectBlock> blk
 | 
|---|
 | 462 |           = dynamic_cast<SCMatrixRectBlock*>(I->block());
 | 
|---|
 | 463 |       int kk,k,jj,j,i,nj;
 | 
|---|
 | 464 |       nj = blk->jend - blk->jstart;
 | 
|---|
 | 465 |       double *data = blk->data;
 | 
|---|
 | 466 |       for (i=0; i<nvec; i++) {
 | 
|---|
 | 467 |           double *veci = vec[i];
 | 
|---|
 | 468 |           double *aveci = a->vec[i];
 | 
|---|
 | 469 |           for (j=blk->jstart,jj=0; j<blk->jend; j++,jj++) {
 | 
|---|
 | 470 |               double tmp = 0.0;
 | 
|---|
 | 471 |               for (k=blk->istart,kk=0; k<blk->iend; k++,kk++) {
 | 
|---|
 | 472 |                   tmp += aveci[k] * data[kk*nj+jj];
 | 
|---|
 | 473 |                 }
 | 
|---|
 | 474 |               veci[j] += tmp;
 | 
|---|
 | 475 |             }
 | 
|---|
 | 476 |         }
 | 
|---|
 | 477 |     }
 | 
|---|
 | 478 | 
 | 
|---|
 | 479 |   vecform_op(AccumFromVec);
 | 
|---|
 | 480 |   delete_vecform();
 | 
|---|
 | 481 |   a->delete_vecform();
 | 
|---|
 | 482 | }
 | 
|---|
 | 483 | 
 | 
|---|
 | 484 | void
 | 
|---|
 | 485 | DistSCMatrix::create_vecform(Form f, int nvectors)
 | 
|---|
 | 486 | {
 | 
|---|
 | 487 |   // determine with rows/cols go on this node
 | 
|---|
 | 488 |   form = f;
 | 
|---|
 | 489 |   int nproc = messagegrp()->n();
 | 
|---|
 | 490 |   int me = messagegrp()->me();
 | 
|---|
 | 491 |   int n1=0, n2=0;
 | 
|---|
 | 492 |   if (form == Row) { n1 = nrow(); n2 = ncol(); }
 | 
|---|
 | 493 |   if (form == Col) { n1 = ncol(); n2 = nrow(); }
 | 
|---|
 | 494 |   if (nvectors == -1) {
 | 
|---|
 | 495 |       nvec = n1/nproc;
 | 
|---|
 | 496 |       vecoff = nvec*me;
 | 
|---|
 | 497 |       int nremain = n1%nproc;
 | 
|---|
 | 498 |       if (me < nremain) {
 | 
|---|
 | 499 |           vecoff += me;
 | 
|---|
 | 500 |           nvec++;
 | 
|---|
 | 501 |         }
 | 
|---|
 | 502 |       else {
 | 
|---|
 | 503 |           vecoff += nremain;
 | 
|---|
 | 504 |         }
 | 
|---|
 | 505 |     }
 | 
|---|
 | 506 |   else {
 | 
|---|
 | 507 |       nvec = nvectors;
 | 
|---|
 | 508 |       vecoff = 0;
 | 
|---|
 | 509 |     }
 | 
|---|
 | 510 | 
 | 
|---|
 | 511 |   // allocate storage
 | 
|---|
 | 512 |   vec = new double*[nvec];
 | 
|---|
 | 513 |   vec[0] = new double[nvec*n2];
 | 
|---|
 | 514 |   int i;
 | 
|---|
 | 515 |   for (i=1; i<nvec; i++) {
 | 
|---|
 | 516 |       vec[i] = &vec[0][i*n2];
 | 
|---|
 | 517 |     }
 | 
|---|
 | 518 | }
 | 
|---|
 | 519 | 
 | 
|---|
 | 520 | void
 | 
|---|
 | 521 | DistSCMatrix::vecform_zero()
 | 
|---|
 | 522 | {
 | 
|---|
 | 523 |   int n=0;
 | 
|---|
 | 524 |   if (form == Row) { n = nvec * ncol(); }
 | 
|---|
 | 525 |   if (form == Col) { n = nvec * nrow(); }
 | 
|---|
 | 526 | 
 | 
|---|
 | 527 |   double *dat = vec[0];
 | 
|---|
 | 528 |   for (int i=0; i<n; i++) dat[i] = 0.0;
 | 
|---|
 | 529 | }
 | 
|---|
 | 530 | 
 | 
|---|
 | 531 | void
 | 
|---|
 | 532 | DistSCMatrix::delete_vecform()
 | 
|---|
 | 533 | {
 | 
|---|
 | 534 |   delete[] vec[0];
 | 
|---|
 | 535 |   delete[] vec;
 | 
|---|
 | 536 |   vec = 0;
 | 
|---|
 | 537 |   nvec = 0;
 | 
|---|
 | 538 | }
 | 
|---|
 | 539 | 
 | 
|---|
 | 540 | void
 | 
|---|
 | 541 | DistSCMatrix::vecform_op(VecOp op, int *ivec)
 | 
|---|
 | 542 | {
 | 
|---|
 | 543 |   Ref<SCMatrixSubblockIter> i;
 | 
|---|
 | 544 |   if (op == CopyToVec || op == AccumToVec) {
 | 
|---|
 | 545 |       i = all_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 546 |     }
 | 
|---|
 | 547 |   else {
 | 
|---|
 | 548 |       if (op == CopyFromVec) assign(0.0);
 | 
|---|
 | 549 |       i = all_blocks(SCMatrixSubblockIter::Accum);
 | 
|---|
 | 550 |     }
 | 
|---|
 | 551 |   for (i->begin(); i->ready(); i->next()) {
 | 
|---|
 | 552 |       Ref<SCMatrixRectBlock> b = dynamic_cast<SCMatrixRectBlock*>(i->block());
 | 
|---|
 | 553 |       if (DEBUG)
 | 
|---|
 | 554 |           ExEnv::outn() << messagegrp()->me() << ": "
 | 
|---|
 | 555 |                << "got block " << b->blocki << ' ' << b->blockj << endl;
 | 
|---|
 | 556 |       int b1start, b2start, b1end, b2end;
 | 
|---|
 | 557 |       if (form == Row) {
 | 
|---|
 | 558 |           b1start = b->istart;
 | 
|---|
 | 559 |           b2start = b->jstart;
 | 
|---|
 | 560 |           b1end = b->iend;
 | 
|---|
 | 561 |           b2end = b->jend;
 | 
|---|
 | 562 |         }
 | 
|---|
 | 563 |       else {
 | 
|---|
 | 564 |           b1start = b->jstart;
 | 
|---|
 | 565 |           b2start = b->istart;
 | 
|---|
 | 566 |           b1end = b->jend;
 | 
|---|
 | 567 |           b2end = b->iend;
 | 
|---|
 | 568 |         }
 | 
|---|
 | 569 |       int nbj = b->jend - b->jstart;
 | 
|---|
 | 570 |       int start, end;
 | 
|---|
 | 571 |       if (ivec) {
 | 
|---|
 | 572 |           start = b1start;
 | 
|---|
 | 573 |           end = b1end;
 | 
|---|
 | 574 |         }
 | 
|---|
 | 575 |       else {
 | 
|---|
 | 576 |           start = b1start > vecoff ? b1start : vecoff;
 | 
|---|
 | 577 |           end = b1end > vecoff+nvec ? vecoff+nvec : b1end;
 | 
|---|
 | 578 |         }
 | 
|---|
 | 579 |       double *dat = b->data;
 | 
|---|
 | 580 |       int off = -b1start;
 | 
|---|
 | 581 |       for (int j=start; j<end; j++) {
 | 
|---|
 | 582 |           double *vecj;
 | 
|---|
 | 583 |           if (ivec) {
 | 
|---|
 | 584 |               vecj = 0;
 | 
|---|
 | 585 |               for (int ii=0; ii<nvec; ii++) {
 | 
|---|
 | 586 |                   if (ivec[ii] == j) { vecj = vec[ii]; break; }
 | 
|---|
 | 587 |                 }
 | 
|---|
 | 588 |               if (!vecj) continue;
 | 
|---|
 | 589 |               if (DEBUG)
 | 
|---|
 | 590 |                   ExEnv::outn() << messagegrp()->me() << ": getting ["
 | 
|---|
 | 591 |                                << j << ","
 | 
|---|
 | 592 |                                << b2start << "-" << b2end << ")" << endl;
 | 
|---|
 | 593 |             }
 | 
|---|
 | 594 |           else {
 | 
|---|
 | 595 |               vecj = vec[j-vecoff];
 | 
|---|
 | 596 |             }
 | 
|---|
 | 597 |           for (int k=b2start; k<b2end; k++) {
 | 
|---|
 | 598 |               int blockoffset;
 | 
|---|
 | 599 |               if (DEBUG)
 | 
|---|
 | 600 |                   ExEnv::outn() << messagegrp()->me() << ": "
 | 
|---|
 | 601 |                        << "using vec[" << j-vecoff << "]"
 | 
|---|
 | 602 |                        << "[" << k << "]" << endl;
 | 
|---|
 | 603 |               if (form == Row) {
 | 
|---|
 | 604 |                   blockoffset = (j+off)*nbj+k - b2start;
 | 
|---|
 | 605 |                   if (DEBUG)
 | 
|---|
 | 606 |                       ExEnv::outn() << messagegrp()->me() << ": "
 | 
|---|
 | 607 |                            << "Row datum offset is "
 | 
|---|
 | 608 |                            << "(" << j << "+" << off << ")*" << nbj << "+" << k
 | 
|---|
 | 609 |                            << "-" << b2start
 | 
|---|
 | 610 |                            << " = " << blockoffset << "(" << b->ndat() << ") "
 | 
|---|
 | 611 |                            << " -> " << dat[blockoffset] << endl;
 | 
|---|
 | 612 |                 }
 | 
|---|
 | 613 |               else {
 | 
|---|
 | 614 |                   blockoffset = (k-b2start)*nbj+j+off; 
 | 
|---|
 | 615 |                 }
 | 
|---|
 | 616 |               if (blockoffset >= b->ndat()) {
 | 
|---|
 | 617 |                   fail("bad offset");
 | 
|---|
 | 618 |                 }
 | 
|---|
 | 619 |               double *datum = &dat[blockoffset];
 | 
|---|
 | 620 |               if (op == CopyToVec) {
 | 
|---|
 | 621 |                   if (DEBUG)
 | 
|---|
 | 622 |                       ExEnv::outn() << messagegrp()->me() << ": "
 | 
|---|
 | 623 |                            << "copying " << *datum << " "
 | 
|---|
 | 624 |                            << "to " << j << " " << k << endl;
 | 
|---|
 | 625 |                   vecj[k] = *datum;
 | 
|---|
 | 626 |                 }
 | 
|---|
 | 627 |               else if (op == CopyFromVec) {
 | 
|---|
 | 628 |                   *datum = vecj[k];
 | 
|---|
 | 629 |                 }
 | 
|---|
 | 630 |               else if (op == AccumToVec) {
 | 
|---|
 | 631 |                   vecj[k] += *datum;
 | 
|---|
 | 632 |                 }
 | 
|---|
 | 633 |               else if (op == AccumFromVec) {
 | 
|---|
 | 634 |                   *datum += vecj[k];
 | 
|---|
 | 635 |                 }
 | 
|---|
 | 636 |             }
 | 
|---|
 | 637 |         }
 | 
|---|
 | 638 |     }
 | 
|---|
 | 639 | }
 | 
|---|
 | 640 | 
 | 
|---|
 | 641 | // does the outer product a x b.  this must have rowdim() == a->dim() and
 | 
|---|
 | 642 | // coldim() == b->dim()
 | 
|---|
 | 643 | void
 | 
|---|
 | 644 | DistSCMatrix::accumulate_outer_product(SCVector*a,SCVector*b)
 | 
|---|
 | 645 | {
 | 
|---|
 | 646 |   const char* name = "DistSCMatrix::accumulate_outer_product";
 | 
|---|
 | 647 |   // make sure that the arguments are of the correct type
 | 
|---|
 | 648 |   DistSCVector* la = require_dynamic_cast<DistSCVector*>(a,name);
 | 
|---|
 | 649 |   DistSCVector* lb = require_dynamic_cast<DistSCVector*>(b,name);
 | 
|---|
 | 650 | 
 | 
|---|
 | 651 |   // make sure that the dimensions match
 | 
|---|
 | 652 |   if (!rowdim()->equiv(la->dim()) || !coldim()->equiv(lb->dim())) {
 | 
|---|
 | 653 |       ExEnv::errn() << indent
 | 
|---|
 | 654 |            << "DistSCMatrix::accumulate_outer_product(SCVector*a,SCVector*b): "
 | 
|---|
 | 655 |            << "dimensions don't match\n";
 | 
|---|
 | 656 |       abort();
 | 
|---|
 | 657 |     }
 | 
|---|
 | 658 | 
 | 
|---|
 | 659 |   Ref<SCMatrixSubblockIter> I = a->all_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 660 |   Ref<SCMatrixSubblockIter> J = b->all_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 661 |   for (I->begin(); I->ready(); I->next()) {
 | 
|---|
 | 662 |       Ref<SCVectorSimpleBlock> vi
 | 
|---|
 | 663 |           = dynamic_cast<SCVectorSimpleBlock*>(I->block());
 | 
|---|
 | 664 |       int ni = vi->iend - vi->istart;
 | 
|---|
 | 665 |       for (J->begin(); J->ready(); J->next()) {
 | 
|---|
 | 666 |           Ref<SCVectorSimpleBlock> vj
 | 
|---|
 | 667 |               = dynamic_cast<SCVectorSimpleBlock*>(J->block());
 | 
|---|
 | 668 |           Ref<SCMatrixRectBlock> rij
 | 
|---|
 | 669 |               = dynamic_cast<SCMatrixRectBlock*>(block_to_block(vi->blocki,
 | 
|---|
 | 670 |                                                        vj->blocki).pointer());
 | 
|---|
 | 671 |           // if the block is held locally sum in the outer prod contrib
 | 
|---|
 | 672 |           if (rij.nonnull()) {
 | 
|---|
 | 673 |               int nj = vj->iend - vj->istart;
 | 
|---|
 | 674 |               double *dat = rij->data;
 | 
|---|
 | 675 |               for (int i=0; i<ni; i++) {
 | 
|---|
 | 676 |                   for (int j=0; j<nj; j++) {
 | 
|---|
 | 677 |                       *dat += vi->data[i]*vj->data[j];
 | 
|---|
 | 678 |                     }
 | 
|---|
 | 679 |                 }
 | 
|---|
 | 680 |             }
 | 
|---|
 | 681 |         }
 | 
|---|
 | 682 |     }
 | 
|---|
 | 683 | }
 | 
|---|
 | 684 | 
 | 
|---|
 | 685 | void
 | 
|---|
 | 686 | DistSCMatrix::transpose_this()
 | 
|---|
 | 687 | {
 | 
|---|
 | 688 |   RefSCDimension tmp = d1;
 | 
|---|
 | 689 |   d1 = d2;
 | 
|---|
 | 690 |   d2 = tmp;
 | 
|---|
 | 691 | 
 | 
|---|
 | 692 |   Ref<SCMatrixBlockList> oldlist = blocklist;
 | 
|---|
 | 693 |   init_blocklist();
 | 
|---|
 | 694 | 
 | 
|---|
 | 695 |   assign(0.0);
 | 
|---|
 | 696 | 
 | 
|---|
 | 697 |   Ref<SCMatrixSubblockIter> I
 | 
|---|
 | 698 |       = new DistSCMatrixListSubblockIter(SCMatrixSubblockIter::Read,
 | 
|---|
 | 699 |                                          oldlist,
 | 
|---|
 | 700 |                                          messagegrp());
 | 
|---|
 | 701 |   for (I->begin(); I->ready(); I->next()) {
 | 
|---|
 | 702 |       Ref<SCMatrixRectBlock> remote
 | 
|---|
 | 703 |           = dynamic_cast<SCMatrixRectBlock*>(I->block());
 | 
|---|
 | 704 |       Ref<SCMatrixRectBlock> local
 | 
|---|
 | 705 |           = dynamic_cast<SCMatrixRectBlock*>(block_to_block(remote->blockj,
 | 
|---|
 | 706 |                                                     remote->blocki).pointer());
 | 
|---|
 | 707 |       if (local.nonnull()) {
 | 
|---|
 | 708 |           int ni = local->iend - local->istart;
 | 
|---|
 | 709 |           int nj = local->jend - local->jstart;
 | 
|---|
 | 710 |           for (int i=0; i<ni; i++) {
 | 
|---|
 | 711 |               for (int j=0; j<nj; j++) {
 | 
|---|
 | 712 |                   local->data[i*nj+j] = remote->data[j*ni+i];
 | 
|---|
 | 713 |                 }
 | 
|---|
 | 714 |             }
 | 
|---|
 | 715 |         }
 | 
|---|
 | 716 |     }
 | 
|---|
 | 717 |   
 | 
|---|
 | 718 | }
 | 
|---|
 | 719 | 
 | 
|---|
 | 720 | double
 | 
|---|
 | 721 | DistSCMatrix::invert_this()
 | 
|---|
 | 722 | {
 | 
|---|
 | 723 |   if (nrow() != ncol()) {
 | 
|---|
 | 724 |       ExEnv::errn() << indent << "DistSCMatrix::invert_this: matrix is not square\n";
 | 
|---|
 | 725 |       abort();
 | 
|---|
 | 726 |     }
 | 
|---|
 | 727 |   RefSymmSCMatrix refs = kit()->symmmatrix(d1);
 | 
|---|
 | 728 |   refs->assign(0.0);
 | 
|---|
 | 729 |   refs->accumulate_symmetric_product(this);
 | 
|---|
 | 730 |   double determ2 = refs->invert_this();
 | 
|---|
 | 731 |   transpose_this();
 | 
|---|
 | 732 |   RefSCMatrix reft = copy();
 | 
|---|
 | 733 |   assign(0.0);
 | 
|---|
 | 734 |   ((SCMatrix*)this)->accumulate_product(reft.pointer(), refs.pointer());
 | 
|---|
 | 735 |   return sqrt(fabs(determ2));
 | 
|---|
 | 736 | }
 | 
|---|
 | 737 | 
 | 
|---|
 | 738 | void
 | 
|---|
 | 739 | DistSCMatrix::gen_invert_this()
 | 
|---|
 | 740 | {
 | 
|---|
 | 741 |   invert_this();
 | 
|---|
 | 742 | }
 | 
|---|
 | 743 | 
 | 
|---|
 | 744 | double
 | 
|---|
 | 745 | DistSCMatrix::determ_this()
 | 
|---|
 | 746 | {
 | 
|---|
 | 747 |   if (nrow() != ncol()) {
 | 
|---|
 | 748 |     ExEnv::errn() << indent << "DistSCMatrix::determ_this: matrix is not square\n";
 | 
|---|
 | 749 |     abort();
 | 
|---|
 | 750 |   }
 | 
|---|
 | 751 |   return invert_this();
 | 
|---|
 | 752 | }
 | 
|---|
 | 753 | 
 | 
|---|
 | 754 | double
 | 
|---|
 | 755 | DistSCMatrix::trace()
 | 
|---|
 | 756 | {
 | 
|---|
 | 757 |   if (nrow() != ncol()) {
 | 
|---|
 | 758 |     ExEnv::errn() << indent << "DistSCMatrix::trace: matrix is not square\n";
 | 
|---|
 | 759 |     abort();
 | 
|---|
 | 760 |   }
 | 
|---|
 | 761 | 
 | 
|---|
 | 762 |   double ret=0.0;
 | 
|---|
 | 763 |   Ref<SCMatrixSubblockIter> I = local_blocks(SCMatrixSubblockIter::Read);
 | 
|---|
 | 764 |   for (I->begin(); I->ready(); I->next()) {
 | 
|---|
 | 765 |       Ref<SCMatrixRectBlock> b = dynamic_cast<SCMatrixRectBlock*>(I->block());
 | 
|---|
 | 766 |       if (b->blocki == b->blockj) {
 | 
|---|
 | 767 |           int ni = b->iend-b->istart;
 | 
|---|
 | 768 |           for (int i=0; i<ni; i++) {
 | 
|---|
 | 769 |               ret += b->data[i*ni+i];
 | 
|---|
 | 770 |             }
 | 
|---|
 | 771 |         }
 | 
|---|
 | 772 |     }
 | 
|---|
 | 773 |   messagegrp()->sum(ret);
 | 
|---|
 | 774 |   
 | 
|---|
 | 775 |   return ret;
 | 
|---|
 | 776 | }
 | 
|---|
 | 777 | 
 | 
|---|
 | 778 | double
 | 
|---|
 | 779 | DistSCMatrix::solve_this(SCVector*v)
 | 
|---|
 | 780 | {
 | 
|---|
 | 781 |   error("no solve_this");
 | 
|---|
 | 782 |   
 | 
|---|
 | 783 |   // make sure that the dimensions match
 | 
|---|
 | 784 |   if (!rowdim()->equiv(v->dim())) {
 | 
|---|
 | 785 |       ExEnv::errn() << indent << "DistSCMatrix::solve_this(SCVector*v): "
 | 
|---|
 | 786 |            << "dimensions don't match\n";
 | 
|---|
 | 787 |       abort();
 | 
|---|
 | 788 |     }
 | 
|---|
 | 789 | 
 | 
|---|
 | 790 |   return 0.0;
 | 
|---|
 | 791 | }
 | 
|---|
 | 792 | 
 | 
|---|
 | 793 | void
 | 
|---|
 | 794 | DistSCMatrix::schmidt_orthog(SymmSCMatrix *S, int nc)
 | 
|---|
 | 795 | {
 | 
|---|
 | 796 |   error("no schmidt_orthog");
 | 
|---|
 | 797 | }
 | 
|---|
 | 798 | 
 | 
|---|
 | 799 | int
 | 
|---|
 | 800 | DistSCMatrix::schmidt_orthog_tol(SymmSCMatrix *S, double tol, double *res)
 | 
|---|
 | 801 | {
 | 
|---|
 | 802 |   error("no schmidt_orthog_tol");
 | 
|---|
 | 803 |   return 0;
 | 
|---|
 | 804 | }
 | 
|---|
 | 805 | 
 | 
|---|
 | 806 | void
 | 
|---|
 | 807 | DistSCMatrix::element_op(const Ref<SCElementOp>& op)
 | 
|---|
 | 808 | {
 | 
|---|
 | 809 |   SCMatrixBlockListIter i;
 | 
|---|
 | 810 |   for (i = blocklist->begin(); i != blocklist->end(); i++) {
 | 
|---|
 | 811 | //       ExEnv::outn() << "rect elemop processing a block of type "
 | 
|---|
 | 812 | //            << i.block()->class_name() << endl;
 | 
|---|
 | 813 |       op->process_base(i.block());
 | 
|---|
 | 814 |     }
 | 
|---|
 | 815 |   if (op->has_collect()) op->collect(messagegrp());
 | 
|---|
 | 816 | }
 | 
|---|
 | 817 | 
 | 
|---|
 | 818 | void
 | 
|---|
 | 819 | DistSCMatrix::element_op(const Ref<SCElementOp2>& op,
 | 
|---|
 | 820 |                           SCMatrix* m)
 | 
|---|
 | 821 | {
 | 
|---|
 | 822 |   DistSCMatrix *lm
 | 
|---|
 | 823 |       = require_dynamic_cast<DistSCMatrix*>(m,"DistSCMatrix::element_op");
 | 
|---|
 | 824 | 
 | 
|---|
 | 825 |   if (!rowdim()->equiv(lm->rowdim()) || !coldim()->equiv(lm->coldim())) {
 | 
|---|
 | 826 |       ExEnv::errn() << indent << "DistSCMatrix: bad element_op\n";
 | 
|---|
 | 827 |       abort();
 | 
|---|
 | 828 |     }
 | 
|---|
 | 829 |   SCMatrixBlockListIter i, j;
 | 
|---|
 | 830 |   for (i = blocklist->begin(), j = lm->blocklist->begin();
 | 
|---|
 | 831 |        i != blocklist->end();
 | 
|---|
 | 832 |        i++, j++) {
 | 
|---|
 | 833 |       op->process_base(i.block(), j.block());
 | 
|---|
 | 834 |     }
 | 
|---|
 | 835 |   if (op->has_collect()) op->collect(messagegrp());
 | 
|---|
 | 836 | }
 | 
|---|
 | 837 | 
 | 
|---|
 | 838 | void
 | 
|---|
 | 839 | DistSCMatrix::element_op(const Ref<SCElementOp3>& op,
 | 
|---|
 | 840 |                           SCMatrix* m,SCMatrix* n)
 | 
|---|
 | 841 | {
 | 
|---|
 | 842 |   DistSCMatrix *lm
 | 
|---|
 | 843 |       = require_dynamic_cast<DistSCMatrix*>(m,"DistSCMatrix::element_op");
 | 
|---|
 | 844 |   DistSCMatrix *ln
 | 
|---|
 | 845 |       = require_dynamic_cast<DistSCMatrix*>(n,"DistSCMatrix::element_op");
 | 
|---|
 | 846 | 
 | 
|---|
 | 847 |   if (!rowdim()->equiv(lm->rowdim()) || !coldim()->equiv(lm->coldim()) ||
 | 
|---|
 | 848 |       !rowdim()->equiv(ln->rowdim()) || !coldim()->equiv(ln->coldim())) {
 | 
|---|
 | 849 |       ExEnv::errn() << indent << "DistSCMatrix: bad element_op\n";
 | 
|---|
 | 850 |       abort();
 | 
|---|
 | 851 |     }
 | 
|---|
 | 852 |   SCMatrixBlockListIter i, j, k;
 | 
|---|
 | 853 |   for (i = blocklist->begin(),
 | 
|---|
 | 854 |            j = lm->blocklist->begin(),
 | 
|---|
 | 855 |            k = ln->blocklist->begin();
 | 
|---|
 | 856 |        i != blocklist->end();
 | 
|---|
 | 857 |        i++, j++, k++) {
 | 
|---|
 | 858 |       op->process_base(i.block(), j.block(), k.block());
 | 
|---|
 | 859 |     }
 | 
|---|
 | 860 |   if (op->has_collect()) op->collect(messagegrp());
 | 
|---|
 | 861 | }
 | 
|---|
 | 862 | 
 | 
|---|
 | 863 | void
 | 
|---|
 | 864 | DistSCMatrix::vprint(const char *title, ostream& os, int prec) const
 | 
|---|
 | 865 | {
 | 
|---|
 | 866 |   // cast so the non const vprint member can be called
 | 
|---|
 | 867 |   ((DistSCMatrix*)this)->vprint(title,os,prec);
 | 
|---|
 | 868 | }
 | 
|---|
 | 869 | 
 | 
|---|
 | 870 | void
 | 
|---|
 | 871 | DistSCMatrix::vprint(const char *title, ostream& os, int prec)
 | 
|---|
 | 872 | {
 | 
|---|
 | 873 |   int i,j;
 | 
|---|
 | 874 |   int lwidth;
 | 
|---|
 | 875 |   double max=this->maxabs();
 | 
|---|
 | 876 | 
 | 
|---|
 | 877 |   int me = messagegrp()->me();
 | 
|---|
 | 878 | 
 | 
|---|
 | 879 |   max = (max==0.0) ? 1.0 : log10(max);
 | 
|---|
 | 880 |   if (max < 0.0) max=1.0;
 | 
|---|
 | 881 | 
 | 
|---|
 | 882 |   lwidth = prec+5+(int) max;
 | 
|---|
 | 883 | 
 | 
|---|
 | 884 |   os.setf(ios::fixed,ios::floatfield); os.precision(prec);
 | 
|---|
 | 885 |   os.setf(ios::right,ios::adjustfield);
 | 
|---|
 | 886 | 
 | 
|---|
 | 887 |   if (messagegrp()->me() == 0) {
 | 
|---|
 | 888 |       if (title) os << endl << indent << title << endl;
 | 
|---|
 | 889 |       else os << endl;
 | 
|---|
 | 890 |     }
 | 
|---|
 | 891 | 
 | 
|---|
 | 892 |   if (nrow()==0 || ncol()==0) {
 | 
|---|
 | 893 |       if (me == 0) os << indent << "empty matrix\n";
 | 
|---|
 | 894 |       return;
 | 
|---|
 | 895 |     }
 | 
|---|
 | 896 | 
 | 
|---|
 | 897 |   create_vecform(Row);
 | 
|---|
 | 898 |   vecform_op(CopyToVec);
 | 
|---|
 | 899 | 
 | 
|---|
 | 900 |   int nc = ncol();
 | 
|---|
 | 901 | 
 | 
|---|
 | 902 |   int tmp = 0;
 | 
|---|
 | 903 |   if (me != 0) {
 | 
|---|
 | 904 |       messagegrp()->recv(me-1, tmp);
 | 
|---|
 | 905 |     }
 | 
|---|
 | 906 |   else {
 | 
|---|
 | 907 |       os << indent;
 | 
|---|
 | 908 |       for (i=0; i<nc; i++) os << setw(lwidth) << i;
 | 
|---|
 | 909 |       os << endl;
 | 
|---|
 | 910 |     }
 | 
|---|
 | 911 |   for (i=0; i<nvec; i++) {
 | 
|---|
 | 912 |       os << indent << setw(5) << i+vecoff;
 | 
|---|
 | 913 |       for (j=0; j<nc; j++) os << setw(lwidth) << vec[i][j];
 | 
|---|
 | 914 |       os << endl;
 | 
|---|
 | 915 |     }
 | 
|---|
 | 916 |   if (messagegrp()->n() > 1) {
 | 
|---|
 | 917 |       // send the go ahead to the next node
 | 
|---|
 | 918 |       int dest = me+1;
 | 
|---|
 | 919 |       if (dest == messagegrp()->n()) dest = 0;
 | 
|---|
 | 920 |       messagegrp()->send(dest, tmp);
 | 
|---|
 | 921 |       // make node zero wait on the last node
 | 
|---|
 | 922 |       if (me == 0) messagegrp()->recv(messagegrp()->n()-1, tmp);
 | 
|---|
 | 923 |     }
 | 
|---|
 | 924 | 
 | 
|---|
 | 925 |   delete_vecform();
 | 
|---|
 | 926 | }
 | 
|---|
 | 927 | 
 | 
|---|
 | 928 | Ref<SCMatrixSubblockIter>
 | 
|---|
 | 929 | DistSCMatrix::local_blocks(SCMatrixSubblockIter::Access access)
 | 
|---|
 | 930 | {
 | 
|---|
 | 931 |   return new SCMatrixListSubblockIter(access, blocklist);
 | 
|---|
 | 932 | }
 | 
|---|
 | 933 | 
 | 
|---|
 | 934 | Ref<SCMatrixSubblockIter>
 | 
|---|
 | 935 | DistSCMatrix::all_blocks(SCMatrixSubblockIter::Access access)
 | 
|---|
 | 936 | {
 | 
|---|
 | 937 |   return new DistSCMatrixListSubblockIter(access, blocklist, messagegrp());
 | 
|---|
 | 938 | }
 | 
|---|
 | 939 | 
 | 
|---|
 | 940 | void
 | 
|---|
 | 941 | DistSCMatrix::error(const char *msg)
 | 
|---|
 | 942 | {
 | 
|---|
 | 943 |   ExEnv::errn() << "DistSCMatrix: error: " << msg << endl;
 | 
|---|
 | 944 | }
 | 
|---|
 | 945 | 
 | 
|---|
 | 946 | Ref<DistSCMatrixKit>
 | 
|---|
 | 947 | DistSCMatrix::skit()
 | 
|---|
 | 948 | {
 | 
|---|
 | 949 |   return dynamic_cast<DistSCMatrixKit*>(kit().pointer());
 | 
|---|
 | 950 | }
 | 
|---|
 | 951 | 
 | 
|---|
 | 952 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 953 | 
 | 
|---|
 | 954 | // Local Variables:
 | 
|---|
 | 955 | // mode: c++
 | 
|---|
 | 956 | // c-file-style: "CLJ"
 | 
|---|
 | 957 | // End:
 | 
|---|