source: ThirdParty/mpqc_open/src/lib/math/scmat/distrect.cc@ b7e5b0

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since b7e5b0 was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 26.0 KB
Line 
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
39using namespace std;
40using namespace sc;
41
42#define DEBUG 0
43
44/////////////////////////////////////////////////////////////////////////////
45
46static void
47fail(const char *m)
48{
49 ExEnv::errn() << indent << "distrect.cc: error: " << m << endl;
50 abort();
51}
52
53/////////////////////////////////////////////////////////////////////////////
54// DistSCMatrix member functions
55
56static ClassDesc DistSCMatrix_cd(
57 typeid(DistSCMatrix),"DistSCMatrix",1,"public SCMatrix",
58 0, 0, 0);
59
60DistSCMatrix::DistSCMatrix(const RefSCDimension&a,const RefSCDimension&b,
61 DistSCMatrixKit*k):
62 SCMatrix(a,b,k)
63{
64 init_blocklist();
65}
66
67int
68DistSCMatrix::block_to_node(int i, int j) const
69{
70 return (i*d2->blocks()->nblock() + j)%messagegrp()->n();
71}
72
73Ref<SCMatrixBlock>
74DistSCMatrix::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
92double *
93DistSCMatrix::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
111int
112DistSCMatrix::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
123void
124DistSCMatrix::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
145DistSCMatrix::~DistSCMatrix()
146{
147}
148
149double
150DistSCMatrix::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
164void
165DistSCMatrix::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
173void
174DistSCMatrix::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
182SCMatrix *
183DistSCMatrix::get_subblock(int br, int er, int bc, int ec)
184{
185 error("get_subblock");
186 return 0;
187}
188
189void
190DistSCMatrix::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
196void
197DistSCMatrix::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
203SCVector *
204DistSCMatrix::get_row(int i)
205{
206 error("get_row");
207 return 0;
208}
209
210void
211DistSCMatrix::assign_row(SCVector *v, int i)
212{
213 error("assign_row");
214}
215
216void
217DistSCMatrix::accumulate_row(SCVector *v, int i)
218{
219 error("accumulate_row");
220}
221
222SCVector *
223DistSCMatrix::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
249void
250DistSCMatrix::assign_column(SCVector *v, int i)
251{
252 error("assign_column");
253}
254
255void
256DistSCMatrix::accumulate_column(SCVector *v, int i)
257{
258 error("accumulate_column");
259}
260
261void
262DistSCMatrix::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
294void
295DistSCMatrix::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
362void
363DistSCMatrix::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
393void
394DistSCMatrix::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
424void
425DistSCMatrix::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
484void
485DistSCMatrix::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
520void
521DistSCMatrix::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
531void
532DistSCMatrix::delete_vecform()
533{
534 delete[] vec[0];
535 delete[] vec;
536 vec = 0;
537 nvec = 0;
538}
539
540void
541DistSCMatrix::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()
643void
644DistSCMatrix::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
685void
686DistSCMatrix::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
720double
721DistSCMatrix::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
738void
739DistSCMatrix::gen_invert_this()
740{
741 invert_this();
742}
743
744double
745DistSCMatrix::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
754double
755DistSCMatrix::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
778double
779DistSCMatrix::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
793void
794DistSCMatrix::schmidt_orthog(SymmSCMatrix *S, int nc)
795{
796 error("no schmidt_orthog");
797}
798
799int
800DistSCMatrix::schmidt_orthog_tol(SymmSCMatrix *S, double tol, double *res)
801{
802 error("no schmidt_orthog_tol");
803 return 0;
804}
805
806void
807DistSCMatrix::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
818void
819DistSCMatrix::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
838void
839DistSCMatrix::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
863void
864DistSCMatrix::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
870void
871DistSCMatrix::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
928Ref<SCMatrixSubblockIter>
929DistSCMatrix::local_blocks(SCMatrixSubblockIter::Access access)
930{
931 return new SCMatrixListSubblockIter(access, blocklist);
932}
933
934Ref<SCMatrixSubblockIter>
935DistSCMatrix::all_blocks(SCMatrixSubblockIter::Access access)
936{
937 return new DistSCMatrixListSubblockIter(access, blocklist, messagegrp());
938}
939
940void
941DistSCMatrix::error(const char *msg)
942{
943 ExEnv::errn() << "DistSCMatrix: error: " << msg << endl;
944}
945
946Ref<DistSCMatrixKit>
947DistSCMatrix::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:
Note: See TracBrowser for help on using the repository browser.