// // distdiag.cc // // Copyright (C) 1996 Limit Point Systems, Inc. // // Author: Curtis Janssen // Maintainer: LPS // // This file is part of the SC Toolkit. // // The SC Toolkit is free software; you can redistribute it and/or modify // it under the terms of the GNU Library General Public License as published by // the Free Software Foundation; either version 2, or (at your option) // any later version. // // The SC Toolkit is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Library General Public License for more details. // // You should have received a copy of the GNU Library General Public License // along with the SC Toolkit; see the file COPYING.LIB. If not, write to // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. // // The U.S. Government is granted a limited license as per AL 91-7. // #include #include #include #include #include #include #include using namespace std; using namespace sc; #define DEBUG 0 ///////////////////////////////////////////////////////////////////////////// // DistDiagSCMatrix member functions static ClassDesc DistDiagSCMatrix_cd( typeid(DistDiagSCMatrix),"DistDiagSCMatrix",1,"public DiagSCMatrix", 0, 0, 0); DistDiagSCMatrix::DistDiagSCMatrix(const RefSCDimension&a,DistSCMatrixKit*k): DiagSCMatrix(a,k) { init_blocklist(); } int DistDiagSCMatrix::block_to_node(int i) const { return (i)%messagegrp()->n(); } Ref DistDiagSCMatrix::block_to_block(int i) const { int offset = i; int nproc = messagegrp()->n(); if ((offset%nproc) != messagegrp()->me()) return 0; SCMatrixBlockListIter I; for (I=blocklist->begin(); I!=blocklist->end(); I++) { if (I.block()->blocki == i) return I.block(); } ExEnv::errn() << indent << "DistDiagSCMatrix::block_to_block: internal error" << endl; abort(); return 0; } double * DistDiagSCMatrix::find_element(int i) const { int bi, oi; d->blocks()->elem_to_block(i, bi, oi); if (DEBUG) ExEnv::outn() << messagegrp()->me() << ": " << "find_element(" << i << "): " << "block = " << bi << ", " << "offset = " << oi << endl; Ref blk; blk << block_to_block(bi); if (blk.nonnull()) { if (DEBUG) ExEnv::outn() << messagegrp()->me() << ": ndat = " << blk->ndat() << endl; if (oi >= blk->ndat()) { ExEnv::errn() << messagegrp()->me() << ": DistDiagSCMatrix::find_element" << ": internal error" << endl; abort(); } return &blk->dat()[oi]; } else { if (DEBUG) ExEnv::outn() << messagegrp()->me() << ": can't find" << endl; return 0; } } int DistDiagSCMatrix::element_to_node(int i) const { int bi, oi; d->blocks()->elem_to_block(i, bi, oi); return block_to_node(bi); } void DistDiagSCMatrix::init_blocklist() { int i; int nproc = messagegrp()->n(); int me = messagegrp()->me(); blocklist = new SCMatrixBlockList; SCMatrixBlock *b; for (i=0; iblocks()->nblock(); i++) { if (i%nproc != me) continue; b = new SCMatrixDiagBlock(d->blocks()->start(i), d->blocks()->fence(i), d->blocks()->start(i)); b->blocki = i; b->blockj = i; blocklist->insert(b); } } DistDiagSCMatrix::~DistDiagSCMatrix() { } double DistDiagSCMatrix::get_element(int i) const { double res; double *e = find_element(i); if (e) { res = *e; messagegrp()->bcast(res, messagegrp()->me()); } else { messagegrp()->bcast(res, element_to_node(i)); } return res; } void DistDiagSCMatrix::set_element(int i,double a) { double *e = find_element(i); if (e) { *e = a; } } void DistDiagSCMatrix::accumulate_element(int i,double a) { double *e = find_element(i); if (e) { *e += a; } } void DistDiagSCMatrix::accumulate(const DiagSCMatrix*a) { // make sure that the argument is of the correct type const DistDiagSCMatrix* la = require_dynamic_cast(a,"DistDiagSCMatrix::accumulate"); // make sure that the dimensions match if (!dim()->equiv(la->dim())) { ExEnv::errn() << indent << "DistDiagSCMatrix::accumulate(SCMatrix*a): " << "dimensions don't match\n"; abort(); } SCMatrixBlockListIter i1, i2; for (i1=la->blocklist->begin(),i2=blocklist->begin(); i1!=la->blocklist->end() && i2!=blocklist->end(); i1++,i2++) { int n = i1.block()->ndat(); if (n != i2.block()->ndat()) { ExEnv::errn() << indent << "DistDiagSCMatrix::accumulate " << "mismatch: internal error" << endl; abort(); } double *dat1 = i1.block()->dat(); double *dat2 = i2.block()->dat(); for (int i=0; i I = local_blocks(SCMatrixSubblockIter::Read); double det = 1.0; for (I->begin(); I->ready(); I->next()) { int n = I->block()->ndat(); double *data = I->block()->dat(); for (int i=0; i gred; messagegrp()->reduce(&det, 1, gred); return det; } double DistDiagSCMatrix::determ_this() { Ref I = local_blocks(SCMatrixSubblockIter::Read); double det = 1.0; for (I->begin(); I->ready(); I->next()) { int n = I->block()->ndat(); double *data = I->block()->dat(); for (int i=0; i gred; messagegrp()->reduce(det, gred); return det; } double DistDiagSCMatrix::trace() { double ret=0.0; Ref I = local_blocks(SCMatrixSubblockIter::Read); for (I->begin(); I->ready(); I->next()) { int n = I->block()->ndat(); double *data = I->block()->dat(); for (int i=0; isum(ret); return ret; } void DistDiagSCMatrix::gen_invert_this() { Ref I = local_blocks(SCMatrixSubblockIter::Read); for (I->begin(); I->ready(); I->next()) { int n = I->block()->ndat(); double *data = I->block()->dat(); for (int i=0; i 1.0e-8) data[i] = 1.0/data[i]; else data[i] = 0.0; } } } void DistDiagSCMatrix::element_op(const Ref& op) { SCMatrixBlockListIter i; for (i = blocklist->begin(); i != blocklist->end(); i++) { op->process_base(i.block()); } if (op->has_collect()) op->collect(messagegrp()); } void DistDiagSCMatrix::element_op(const Ref& op, DiagSCMatrix* m) { DistDiagSCMatrix *lm = require_dynamic_cast(m,"DistDiagSCMatrix::element_op"); if (!dim()->equiv(lm->dim())) { ExEnv::errn() << indent << "DistDiagSCMatrix: bad element_op\n"; abort(); } SCMatrixBlockListIter i, j; for (i = blocklist->begin(), j = lm->blocklist->begin(); i != blocklist->end(); i++, j++) { op->process_base(i.block(), j.block()); } if (op->has_collect()) op->collect(messagegrp()); } void DistDiagSCMatrix::element_op(const Ref& op, DiagSCMatrix* m,DiagSCMatrix* n) { DistDiagSCMatrix *lm = require_dynamic_cast(m,"DistDiagSCMatrix::element_op"); DistDiagSCMatrix *ln = require_dynamic_cast(n,"DistDiagSCMatrix::element_op"); if (!dim()->equiv(lm->dim()) || !dim()->equiv(ln->dim())) { ExEnv::errn() << indent << "DistDiagSCMatrix: bad element_op\n"; abort(); } SCMatrixBlockListIter i, j, k; for (i = blocklist->begin(), j = lm->blocklist->begin(), k = ln->blocklist->begin(); i != blocklist->end(); i++, j++, k++) { op->process_base(i.block(), j.block(), k.block()); } if (op->has_collect()) op->collect(messagegrp()); } Ref DistDiagSCMatrix::local_blocks(SCMatrixSubblockIter::Access access) { return new SCMatrixListSubblockIter(access, blocklist); } Ref DistDiagSCMatrix::all_blocks(SCMatrixSubblockIter::Access access) { return new DistSCMatrixListSubblockIter(access, blocklist, messagegrp()); } void DistDiagSCMatrix::error(const char *msg) { ExEnv::errn() << indent << "DistDiagSCMatrix: error: " << msg << endl; } Ref DistDiagSCMatrix::skit() { return dynamic_cast(kit().pointer()); } ///////////////////////////////////////////////////////////////////////////// // Local Variables: // mode: c++ // c-file-style: "CLJ" // End: