OOFEM 3.0
Loading...
Searching...
No Matches
fetisolver.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
36#include "mathfem.h"
37#include "fetisolver.h"
38#include "skyline.h"
39#include "verbose.h"
40#include "dofmanager.h"
41#include "engngm.h"
42#include "domain.h"
44#include "classfactory.h"
45
46namespace oofem {
48
49FETISolver :: FETISolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m),
50 ni(20),
51 err(1.e-6),
55{
56}
57
58
59FETISolver :: ~FETISolver()
60{
61 if ( engngModel->giveRank() == 0 ) {
62 delete commBuff;
63 delete masterCommunicator;
64 }
65}
66
67
68int
69FETISolver :: estimateMaxPackSize(IntArray &map, DataStream &buff, int &packUnpackType)
70{
71 int rank = domain->giveEngngModel()->giveRank();
72 int count = 0;
74
75 if ( rank == 0 ) {
76 // master comm maps contain boundary dof managers
77 for ( int m: map ) {
78 count += masterCommunicator->giveDofManager( m )->giveNumberOfDofs();
79 }
80 } else {
81 for ( int m: map ) {
82 for ( Dof *dof: *domain->giveDofManager( m ) ) {
83 if ( dof->giveEquationNumber(dn) != 0 ) {
84 count++;
85 }
86 }
87 }
88 }
89
90 return ( buff.givePackSizeOfDouble(1) * count * FETISOLVER_MAX_RBM );
91}
92
93
94void
95FETISolver :: initializeFrom(InputRecord &ir)
96{
102
103 if ( fabs(limit) < 1.e-20 ) {
104 limit = 1.e-20;
105 }
106
107 if ( err < 1.e-20 ) {
108 err = 1.e-20;
109 }
110
111 if ( err > 0.1 ) {
112 err = 0.1;
113 }
114}
115
116void FETISolver :: setUpCommunicationMaps()
117{
118 int nnodes = domain->giveNumberOfDofManagers();
119 int boundaryDofManNum = 0;
120 int indx = 1, neq;
121 StaticCommunicationBuffer commBuff(MPI_COMM_WORLD);
122 IntArray commMap;
124
125 // determine the total number of boundary dof managers
126 for ( int i = 1; i <= nnodes; i++ ) {
127 if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) {
128 boundaryDofManNum++;
129 }
130 }
131
132 if ( domain->giveEngngModel()->giveRank() != 0 ) {
133 commBuff.resize( commBuff.givePackSizeOfInt(1) );
134 commBuff.write(boundaryDofManNum);
135
136#ifdef __VERBOSE_PARALLEL
137 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Sending data to partition 0 (send %d)\n",
138 this->giveEngngModel()->giveRank(),
139 "FETISolver :: setUpCommunicationMaps : send number of boundary dofMans", boundaryDofManNum);
140#endif
141 commBuff.iSend(0, FETICommunicator :: NumberOfBoundaryDofManagersMsg);
142
143 MPI_Barrier(MPI_COMM_WORLD);
144 }
145
146#ifdef __VERBOSE_PARALLEL
147 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Barrier reached\n",
148 this->giveEngngModel()->giveRank(), "FETISolver :: setUpCommunicationMaps");
149#endif
150
151
152
153
154 commMap.resize(boundaryDofManNum);
155
156 commBuff.resize(commBuff.givePackSizeOfInt(1) * 2 * boundaryDofManNum);
157 commBuff.init();
158 // determine total number of DOFs per each boundary node
159 // and build communication map simultaneously
160 indx = 1;
161 IntArray locNum;
162 if ( domain->giveEngngModel()->giveRank() != 0 ) {
163 for ( int i = 1; i <= nnodes; i++ ) {
164 if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) {
165 // remember comm map entry
166 commMap.at(indx++) = i;
167 // determine number of DOFs
168 domain->giveDofManager(i)->giveCompleteLocationArray(locNum, dn);
169 neq = 0;
170 for ( int j = 1; j <= locNum.giveSize(); j++ ) {
171 if ( locNum.at(j) ) {
172 neq++;
173 }
174 }
175
176 commBuff.write( domain->giveDofManager(i)->giveGlobalNumber() );
177 commBuff.write(neq);
178 }
179 }
180 } else {
181 for ( int i = 1; i <= nnodes; i++ ) {
182 if ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) {
183 // remember comm map entry
184 commMap.at(indx++) = i;
185 }
186 }
187 }
188
189 if ( domain->giveEngngModel()->giveRank() != 0 ) {
190 processCommunicator.setToSendArry(this, commMap, 0);
191 processCommunicator.setToRecvArry(this, commMap, 0);
192 commBuff.iSend(0, FETICommunicator :: BoundaryDofManagersRecMsg);
193#ifdef __VERBOSE_PARALLEL
194 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Barrier reached\n",
195 this->giveEngngModel()->giveRank(), "FETISolver :: setUpCommunicationMaps");
196#endif
197 MPI_Barrier(MPI_COMM_WORLD);
198#ifdef __VERBOSE_PARALLEL
199 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Barrier reached\n",
200 this->giveEngngModel()->giveRank(), "FETISolver :: setUpCommunicationMaps");
201#endif
202 MPI_Barrier(MPI_COMM_WORLD);
203 } else {
204 // remember comm map for direct mapping at master
205 this->masterCommMap = commMap;
206 }
207}
208
209
210
211
212
213/*******************************************************************/
214/*******************************************************************/
215/*******************************************************************/
216/*******************************************************************/
217
218void
219FETISolver :: projection(FloatArray &v, FloatMatrix &l, FloatMatrix &l1)
220/*
221 * funkce provadi projekci v modifikovane metode sdruzenych gradientu
222 *
223 * vstupy
224 * v - vektor pred projekci
225 * l - matice L(m,n)
226 * l1 - inverzni matice k matici L^T L, rozmery (n,n)
227 *
228 * vystup
229 * v - vektor po projekci
230 *
231 * 7.12.1998
232 */
233{
234 FloatArray help1, help2;
235
236 help1.beTProductOf(l, v);
237 help2.beProductOf(l1, help1);
238 help1.beProductOf(l, help2);
239
240 v.subtract(help1);
241}
242
243
244
245
246int
247FETISolver :: packRBM(ProcessCommunicator &processComm)
248{
249 int result = 1;
250 const IntArray &toSendMap = processComm.giveToSendMap();
252 IntArray locationArray;
254
255 for ( int inode : toSendMap ) {
256 domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn);
257 int ndofs = locationArray.giveSize();
258 for ( int j = 1; j <= ndofs; j++ ) {
259 int eqNum;
260 if ( ( eqNum = locationArray.at(j) ) ) {
261 for ( int ir = 1; ir <= nse; ir++ ) {
262 result &= send_buff.write( rbm.at(eqNum, ir) );
263 }
264
265 if ( nse == 0 ) {
266 result &= send_buff.write(0.0);
267 }
268 }
269 }
270 }
271
272 return result;
273}
274
275
276int
277FETISolver :: masterUnpackRBM(ProcessCommunicator &processComm)
278{
279 int result = 1;
280 const IntArray &toRecvMap = processComm.giveToRecvMap();
282 IntArray locationArray;
283
284 int receivedRank = processComm.giveRank();
285 if ( receivedRank != 0 ) {
286 // for (irbm = 1; irbm <= nsem.at(receivedRank+1); irbm++) {
287 for ( int to : toRecvMap ) {
288 //
289 // loop over all dofs
290 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++ ) {
291 for ( int irbm = 1; irbm <= nsem.at(receivedRank + 1); irbm++ ) {
292 // unpack contribution
293 double value;
294 result &= recv_buff.read(value);
295 if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
296 // corresponding DOFs in boundary node
297
298 // localize to corresponding places
299 int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions();
300 for ( int j = 1; j <= nshared; j++ ) {
301 int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j);
302 if ( part == processComm.giveRank() ) {
303 continue;
304 }
305
306 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof);
307 l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = value;
308 }
309 } else { // no reference partition
310 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof);
311 l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = ( -1.0 ) * value;
312 }
313 }
314 }
315 }
316 }
317
318 return result;
319}
320
321int
322FETISolver :: masterMapRBM()
323{
324 int receivedRank = 0, result;
325 IntArray locationArray;
326 int size = masterCommMap.giveSize();
327 // master will map its own values directly
328 int locpos;
330
331 for ( int irbm = 1; irbm <= nsem.at(1); irbm++ ) {
332 for ( int i = 1; i <= size; i++ ) {
333 int to = masterCommunicator->giveMasterCommMapPtr()->at(i);
334 // use receive map, send map is empty to prevent master to send
335 // itself any data. Note, however, that send and receive maps are same.
336 int from = masterCommMap.at(i);
337
338 domain->giveDofManager(from)->giveCompleteLocationArray(locationArray, dn);
339 locpos = 1;
340 //
341 // ndofs = locationArray.giveSize(); // including supported
342 // for (j=1; j<=ndofs; j++) {
343 // if (eqNum = locationArray.at(j)) {
344
345 //
346 // loop over all dofs
347 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++, locpos++ ) {
348 // extract source value
349 while ( locationArray.at(locpos) == 0 ) {
350 locpos++;
351 // test if position of nonzero dof is allowed
352 if ( locpos > locationArray.giveSize() ) {
353 OOFEM_ERROR("Consistency dof error");
354 }
355 }
356
357 double value = rbm.at(locationArray.at(locpos), irbm);
358 if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
359 // corresponding DOFs in boundary node
360
361 // localize to corresponding places
362 int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions();
363 for ( int j = 1; j <= nshared; j++ ) {
364 int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j);
365 if ( part == 0 ) {
366 continue;
367 }
368
369 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof);
370 l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = value;
371 }
372 } else { // no reference partition
373 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof);
374 l.at(eqNum, rbmAddr.at(receivedRank + 1) + irbm - 1) = ( -1.0 ) * value;
375 }
376 }
377 }
378 }
379
380 result = 1;
381 return result;
382}
383
384
385int
386FETISolver :: packQQProducts(ProcessCommunicator &processComm)
387{
388 int result = 1;
390 IntArray locationArray;
391
392 for ( int i = 1; i <= nse; i++ ) {
393 result &= send_buff.write( qq.at(i) );
394 }
395
396 return result;
397}
398
399
400int
401FETISolver :: masterUnpackQQProduct(ProcessCommunicator &processComm)
402{
403 int result = 1;
404 //const IntArray const &toRecvMap = processComm.giveToRecvMap();
406 IntArray locationArray;
407 //double value;
408
409 int receivedRank = processComm.giveRank();
410
411 if ( receivedRank != 0 ) {
412 for ( int i = 1; i <= nsem.at(receivedRank + 1); i++ ) {
413 result &= recv_buff.read( q.at(rbmAddr.at(receivedRank + 1) + i - 1) );
414 }
415 }
416
417 return result;
418}
419
420
421int
422FETISolver :: masterMapQQProduct()
423{
424 int result = 0;
425
426 for ( int i = 1; i <= nsem.at(1); i++ ) {
427 q.at(rbmAddr.at(1) + i - 1) = qq.at(i);
428 result = 1;
429 }
430
431 return result;
432}
433
434
435int
436FETISolver :: packSolution(ProcessCommunicator &processComm)
437{
438 // master
439 int result = 1;
440 const IntArray &toSendMap = processComm.giveToSendMap();
442 IntArray locationArray;
443
444 int rank = processComm.giveRank();
445 for ( int from : toSendMap ) {
446 int ndofs = masterCommunicator->giveDofManager(from)->giveNumberOfDofs();
447 if ( rank == masterCommunicator->giveDofManager(from)->giveReferencePratition() ) {
448 // summ corresponding values (multipliers)
449 int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions();
450 for ( int k = 1; k <= ndofs; k++ ) {
451 double val = 0.0;
452 for ( int j = 1; j <= nshared; j++ ) {
453 int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j);
454 if ( part == processComm.giveRank() ) {
455 continue;
456 }
457
458 int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, k);
459 val += w.at(eqNum);
460 }
461
462 result &= send_buff.write(val);
463 }
464 } else {
465 masterCommunicator->giveDofManager(from)->giveCompleteLocationArray(rank, locationArray);
466 for ( int j = 1; j <= ndofs; j++ ) {
467 int eqNum;
468 if ( ( eqNum = locationArray.at(j) ) ) {
469 result &= send_buff.write( ( -1.0 ) * w.at(eqNum) );
470 }
471 }
472 }
473 }
474
475 return result;
476}
477
478
479int
480FETISolver :: unpackSolution(ProcessCommunicator &processComm)
481{
482 // slaves unpack their slotion contributions
483 int result = 1;
484 const IntArray &toRecvMap = processComm.giveToRecvMap();
486 IntArray locationArray;
488
489 for ( int to : toRecvMap ) {
490 domain->giveDofManager(to)->giveCompleteLocationArray(locationArray, dn);
491 int ndofs = locationArray.giveSize();
492 for ( int j = 1; j <= ndofs; j++ ) {
493 int eqNum;
494 if ( ( eqNum = locationArray.at(j) ) ) {
495 double value;
496 result &= recv_buff.read(value);
497 dd.at(eqNum) = value;
498
499#ifdef __VERBOSE_PARALLEL
500 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Unpacking solution value %f at %d\n",
501 this->giveEngngModel()->giveRank(), "FETISolver :: solveYourselfAt", value, eqNum);
502#endif
503 }
504 }
505 }
506
507 return result;
508}
509
510int
511FETISolver :: masterMapSolution()
512{
513 int receivedRank = 0, result;
514 IntArray locationArray;
515 int size = masterCommMap.giveSize();
517
518 for ( int i = 1; i <= size; i++ ) {
519 int from = masterCommunicator->giveMasterCommMapPtr()->at(i);
520 // use receive map, send map is empty to prevent master to send
521 // itself any data. Note, however, that send and receive maps are same.
522 int to = masterCommMap.at(i);
523
524 domain->giveDofManager(to)->giveCompleteLocationArray(locationArray, dn);
525 int locpos = 1;
526 //
527 // loop over all dofs
528 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); idof++, locpos++ ) {
529 // extract source value
530 while ( locationArray.at(locpos) == 0 ) {
531 locpos++;
532 // test if position of nonzero dof is allowed
533 if ( locpos > locationArray.giveSize() ) {
534 OOFEM_ERROR("Consistency dof error");
535 }
536 }
537
538 double value = 0.0;
539 if ( masterCommunicator->giveDofManager(from)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
540 // corresponding DOFs in boundary node
541
542 // localize to corresponding places
543 int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions();
544 for ( int j = 1; j <= nshared; j++ ) {
545 int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j);
546 if ( part == 0 ) {
547 continue;
548 }
549
550 int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, idof);
551 value += w.at(eqNum);
552 }
553 } else { // no reference partition
554 int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(receivedRank, idof);
555 value = ( -1.0 ) * w.at(eqNum);
556 }
557
558 // unpack to locaL CORRESPONDING EQUATION
559 dd.at( locationArray.at(locpos) ) = value;
560 }
561 }
562
563 result = 1;
564 return result;
565}
566
567
568
569int
570FETISolver :: packResiduals(ProcessCommunicator &processComm)
571{
572 // slaves
573
574 int result = 1;
575 const IntArray &toSendMap = processComm.giveToSendMap();
577 IntArray locationArray;
579
580 for ( int inode : toSendMap ) {
581 domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn);
582 int ndofs = locationArray.giveSize();
583 for ( int j = 1; j <= ndofs; j++ ) {
584 int eqNum;
585 if ( ( eqNum = locationArray.at(j) ) ) {
586 result &= send_buff.write( pp.at(eqNum) );
587 }
588 }
589 }
590
591 return result;
592}
593
594
595int
596FETISolver :: unpackResiduals(ProcessCommunicator &processComm)
597{
598 // master
599
600 int result = 1;
601 const IntArray &toRecvMap = processComm.giveToRecvMap();
603 IntArray locationArray;
604
605 int receivedRank = processComm.giveRank();
606
607 if ( receivedRank != 0 ) {
608 for ( int to : toRecvMap ) {
609 //
610 // loop over all dofs
611 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++ ) {
612 // unpack contribution
613 double value;
614 result &= recv_buff.read(value);
615 if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
616 // corresponding DOFs in boundary node
617
618 // localize to corresponding places
619 int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions();
620 for ( int j = 1; j <= nshared; j++ ) {
621 int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j);
622 if ( part == processComm.giveRank() ) {
623 continue;
624 }
625
626 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof);
627 g.at(eqNum) += value;
628 }
629 } else { // no reference partition
630 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof);
631 g.at(eqNum) += ( -1.0 ) * value;
632 }
633 }
634 }
635 }
636
637 return result;
638}
639
640int
641FETISolver :: masterMapResiduals()
642{ // master will map its own values directly
643 int receivedRank = 0, result;
644 IntArray locationArray;
645 int size = masterCommMap.giveSize();
647
648 for ( int i = 1; i <= size; i++ ) {
649 int to = masterCommunicator->giveMasterCommMapPtr()->at(i);
650 // use receive map, send map is empty to prevent master to send
651 // itself any data. Note, however, that send and receive maps are same.
652 int from = masterCommMap.at(i);
653
654 domain->giveDofManager(from)->giveCompleteLocationArray(locationArray, dn);
655 int locpos = 1;
656 //
657 // ndofs = locationArray.giveSize(); // including supported
658 // for (j=1; j<=ndofs; j++) {
659 // if (eqNum = locationArray.at(j)) {
660
661 //
662 // loop over all dofs
663 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++, locpos++ ) {
664 // extract source value
665 while ( locationArray.at(locpos) == 0 ) {
666 locpos++;
667 // test if position of nonzero dof is allowed
668 if ( locpos > locationArray.giveSize() ) {
669 OOFEM_ERROR("Consistency dof error");
670 }
671 }
672
673 double value = pp.at( locationArray.at(locpos) );
674 if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
675 // corresponding DOFs in boundary node
676
677 // localize to corresponding places
678 int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions();
679 for ( int j = 1; j <= nshared; j++ ) {
680 int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j);
681 if ( part == 0 ) {
682 continue;
683 }
684
685 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof);
686 g.at(eqNum) += value;
687 }
688 } else { // no reference partition
689 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof);
690 g.at(eqNum) += ( -1.0 ) * value;
691 }
692 }
693 }
694
695 result = 1;
696 return result;
697}
698
699
700
701
702int
703FETISolver :: packDirectionVector(ProcessCommunicator &processComm)
704{
705 // master
706 int result = 1;
707 const IntArray &toSendMap = processComm.giveToSendMap();
709 IntArray locationArray;
710
711 int rank = processComm.giveRank();
712 for ( int from : toSendMap ) {
713 int ndofs = masterCommunicator->giveDofManager(from)->giveNumberOfDofs();
714 if ( rank == masterCommunicator->giveDofManager(from)->giveReferencePratition() ) {
715 // summ corresponding values (multipliers)
716 int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions();
717 for ( int k = 1; k <= ndofs; k++ ) {
718 double val = 0.0;
719 for ( int j = 1; j <= nshared; j++ ) {
720 int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j);
721 if ( part == processComm.giveRank() ) {
722 continue;
723 }
724
725 int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, k);
726 val += d.at(eqNum);
727 }
728
729 result &= send_buff.write(val);
730 }
731 } else {
732 masterCommunicator->giveDofManager(from)->giveCompleteLocationArray(rank, locationArray);
733 for ( int j = 1; j <= ndofs; j++ ) {
734 int eqNum;
735 if ( ( eqNum = locationArray.at(j) ) ) {
736 result &= send_buff.write( ( -1.0 ) * d.at(eqNum) );
737 }
738 }
739 }
740 }
741
742 return result;
743}
744
745
746int
747FETISolver :: unpackDirectionVector(ProcessCommunicator &processComm)
748{
749 // slaves unpack their slotion contributions
750 int result = 1;
751 const IntArray &toRecvMap = processComm.giveToRecvMap();
753 IntArray locationArray;
754 // int receivedRank = domainComm.giveRank();
756
757 // if (receivedRank != 0) {
758 for ( int inode : toRecvMap ) {
759 domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn);
760 int ndofs = locationArray.giveSize();
761 for ( int j = 1; j <= ndofs; j++ ) {
762 int eqNum;
763 if ( ( eqNum = locationArray.at(j) ) ) {
764 result &= recv_buff.read( dd.at(eqNum) );
765 }
766 }
767 }
768
769 // }
770 return result;
771}
772
773int
774FETISolver :: masterMapDirectionVector()
775{
776 int receivedRank = 0, result;
777 IntArray locationArray;
778 int size = masterCommMap.giveSize();
780
781 for ( int i = 1; i <= size; i++ ) {
782 int from = masterCommunicator->giveMasterCommMapPtr()->at(i);
783 // use receive map, send map is empty to prevent master to send
784 // itself any data. Note, however, that send and receive maps are same.
785 int to = masterCommMap.at(i);
786
787 domain->giveDofManager(to)->giveCompleteLocationArray(locationArray, dn);
788 int locpos = 1;
789 //
790 // loop over all dofs
791 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(from)->giveNumberOfDofs(); idof++, locpos++ ) {
792 // extract source value
793 while ( locationArray.at(locpos) == 0 ) {
794 locpos++;
795 // test if position of nonzero dof is allowed
796 if ( locpos > locationArray.giveSize() ) {
797 OOFEM_ERROR("Consistency dof error");
798 }
799 }
800
801 double value = 0.0;
802 if ( masterCommunicator->giveDofManager(from)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
803 // corresponding DOFs in boundary node
804
805 // localize to corresponding places
806 int nshared = masterCommunicator->giveDofManager(from)->giveNumberOfSharedPartitions();
807 for ( int j = 1; j <= nshared; j++ ) {
808 int part = masterCommunicator->giveDofManager(from)->giveSharedPartition(j);
809 if ( part == 0 ) {
810 continue;
811 }
812
813 int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(part, idof);
814 value += d.at(eqNum);
815 }
816 } else { // no reference partition
817 int eqNum = masterCommunicator->giveDofManager(from)->giveCodeNumber(receivedRank, idof);
818 value = ( -1.0 ) * d.at(eqNum);
819 }
820
821 // unpack to locaL CORRESPONDING EQUATION
822 dd.at( locationArray.at(locpos) ) = value;
823 }
824 }
825
826 result = 1;
827 return result;
828}
829
830
831int
832FETISolver :: packPPVector(ProcessCommunicator &processComm)
833{
834 // slaves
835
836 int result = 1;
837 const IntArray &toSendMap = processComm.giveToSendMap();
839 IntArray locationArray;
841
842 for ( int inode : toSendMap ) {
843 domain->giveDofManager( inode )->giveCompleteLocationArray(locationArray, dn);
844 int ndofs = locationArray.giveSize();
845 for ( int j = 1; j <= ndofs; j++ ) {
846 int eqNum;
847 if ( ( eqNum = locationArray.at(j) ) ) {
848 result &= send_buff.write( pp.at(eqNum) );
849 }
850 }
851 }
852
853 return result;
854}
855
856
857int
858FETISolver :: unpackPPVector(ProcessCommunicator &processComm)
859{
860 // master
861
862 int result = 1;
863 const IntArray &toRecvMap = processComm.giveToRecvMap();
865 IntArray locationArray;
866
867 int receivedRank = processComm.giveRank();
868
869 if ( receivedRank != 0 ) {
870 for ( int to : toRecvMap ) {
871 //
872 // loop over all dofs
873 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++ ) {
874 // unpack contribution
875 double value;
876 result &= recv_buff.read(value);
877 if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
878 // corresponding DOFs in boundary node
879
880 // localize to corresponding places
881 int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions();
882 for ( int j = 1; j <= nshared; j++ ) {
883 int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j);
884 if ( part == processComm.giveRank() ) {
885 continue;
886 }
887
888 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof);
889 p.at(eqNum) += value;
890 }
891 } else { // no reference partition
892 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof);
893 p.at(eqNum) += ( -1.0 ) * value;
894 }
895 }
896 }
897 }
898
899 return result;
900}
901
902int
903FETISolver :: masterMapPPVector()
904{ // master will map its own values directly
905 int receivedRank = 0, result;
906 IntArray locationArray;
907 int size = masterCommMap.giveSize();
909
910 for ( int i = 1; i <= size; i++ ) {
911 int to = masterCommunicator->giveMasterCommMapPtr()->at(i);
912 // use receive map, send map is empty to prevent master to send
913 // itself any data. Note, however, that send and receive maps are same.
914 int from = masterCommMap.at(i);
915
916 domain->giveDofManager(from)->giveCompleteLocationArray(locationArray, dn);
917 int locpos = 1;
918 //
919 // ndofs = locationArray.giveSize(); // including supported
920 // for (j=1; j<=ndofs; j++) {
921 // if (eqNum = locationArray.at(j)) {
922
923 //
924 // loop over all dofs
925 for ( int idof = 1; idof <= masterCommunicator->giveDofManager(to)->giveNumberOfDofs(); idof++, locpos++ ) {
926 // extract source value
927 while ( locationArray.at(locpos) == 0 ) {
928 locpos++;
929 // test if position of nonzero dof is allowed
930 if ( locpos > locationArray.giveSize() ) {
931 OOFEM_ERROR("Consistency dof error");
932 }
933 }
934
935 double value = pp.at( locationArray.at(locpos) );
936 if ( masterCommunicator->giveDofManager(to)->giveReferencePratition() == receivedRank ) { // contribution from reference partition localizes to all
937 // corresponding DOFs in boundary node
938
939 // localize to corresponding places
940 int nshared = masterCommunicator->giveDofManager(to)->giveNumberOfSharedPartitions();
941 for ( int j = 1; j <= nshared; j++ ) {
942 int part = masterCommunicator->giveDofManager(to)->giveSharedPartition(j);
943 if ( part == 0 ) {
944 continue;
945 }
946
947 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(part, idof);
948 p.at(eqNum) += value;
949 }
950 } else { // no reference partition
951 int eqNum = masterCommunicator->giveDofManager(to)->giveCodeNumber(receivedRank, idof);
952 p.at(eqNum) += ( -1.0 ) * value;
953 }
954 }
955 }
956
957 result = 1;
958 return result;
959}
960
961
962int
963FETISolver :: packGammas(ProcessCommunicator &processComm)
964{
965 // master
966
967 int result = 1;
968 int rank = processComm.giveRank();
970
971 for ( int irbm = 1; irbm <= nsem.at(rank + 1); irbm++ ) {
972 result &= send_buff.write( gamma.at(rbmAddr.at(rank + 1) + irbm - 1) );
973 }
974
975 return result;
976}
977
978
979int
980FETISolver :: unpackGammas(ProcessCommunicator &processComm)
981{
982 // slaves
983 int result = 1;
985
986 localGammas.resize(nse);
987 for ( int irbm = 1; irbm <= nse; irbm++ ) {
988 result &= recv_buff.read( localGammas.at(irbm) );
989 }
990
991 return result;
992}
993
994int
995FETISolver :: masterMapGammas()
996{
997 // slaves
998 int result = 1;
999
1000 localGammas.resize(nse);
1001 for ( int irbm = 1; irbm <= nse; irbm++ ) {
1002 localGammas.at(irbm) = gamma.at(rbmAddr.at(1) + irbm - 1);
1003 }
1004
1005 return result;
1006}
1007
1008
1010FETISolver :: solve(SparseMtrx &A, FloatArray &partitionLoad, FloatArray &partitionSolution)
1011{
1012 int tnse = 0, rank = domain->giveEngngModel()->giveRank();
1013 int source, tag;
1014 int masterLoopStatus;
1015 double nom = 0.0, denom, alpha, beta, energyNorm = 0.0;
1016 FloatMatrix l1;
1017 StaticCommunicationBuffer commBuff(MPI_COMM_WORLD);
1018 Skyline *partitionStiffness = dynamic_cast< Skyline * >(&A);
1019 if ( !partitionStiffness ) {
1020 OOFEM_ERROR("unsuported sparse matrix type");
1021 }
1022
1023
1024 if ( ( partitionSolution.giveSize() ) != partitionLoad.giveSize() ) {
1025 OOFEM_ERROR("size mismatch");
1026 }
1027
1028 int neq = partitionStiffness->giveNumberOfRows();
1029 int size = domain->giveEngngModel()->giveNumberOfProcesses();
1030 nsem.resize(size);
1031
1032 // initialize communication maps
1033 this->setUpCommunicationMaps();
1034 if ( rank == 0 ) {
1035 this->commBuff = new CommunicatorBuff(size);
1036 masterCommunicator = new FETICommunicator(engngModel, this->commBuff, engngModel->giveRank(), size);
1037 masterCommunicator->setUpCommunicationMaps(engngModel);
1038 }
1039
1040 MPI_Barrier(MPI_COMM_WORLD);
1041
1042#ifdef __VERBOSE_PARALLEL
1043 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Barrier reached\n",
1044 this->giveEngngModel()->giveRank(), "FETISolver :: solveYourselfAt");
1045#endif
1046
1047 /*********************************/
1048 /* rozklad matice */
1049 /* vypocet rigid body modes */
1050 /*********************************/
1051 /* pole indexu zavislych rovnic */
1052 se.resize(6);
1053 se.zero();
1054 /* pole posunu jako tuheho telesa */
1055 // rbm.resize (neq, 6); rbm.zero();
1056
1057#ifdef __VERBOSE_PARALLEL
1058 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: rbmodes computation startup, lneq is %d\n",
1059 rank, "FETISolver :: solveYourselfAt", neq);
1060#endif
1061
1062 partitionStiffness->rbmodes(rbm, nse, se, limit, 3);
1063
1064#ifdef __VERBOSE_PARALLEL
1065 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Number of Rigid body modes %3d\n",
1066 rank, "FETISolver :: solveYourselfAt", nse);
1067
1068 //fprintf(stdout, "\n[process rank %3d]: %-30s: RBM dump",
1069 // rank,"FETISolver :: solveYourselfAt");
1070 //rbm.printYourself();
1071
1072#endif
1073
1074 /*****************************/
1075 /* vypocet soucinu R^T . f */
1076 /*****************************/
1077
1078 if ( nse != 0 ) {
1079 qq.resize(nse);
1080 qq.zero();
1081
1082 qq.beTProductOf(rbm, partitionLoad);
1083 qq.negated();
1084 }
1085
1086 /***************************************************************************/
1087 /* zjisteni rozmeru matice L, vektoru q, poctu neznamych na podoblastech */
1088 /***************************************************************************/
1089
1090 // commBuff.init();
1091 if ( rank == 0 ) {
1092 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1093 //
1094 // receive data
1095 //
1096 for ( int i = 1; i < size; i++ ) {
1097 commBuff.iRecv(MPI_ANY_SOURCE, FETISolver :: NumberOfRBMMsg);
1098 while ( !commBuff.testCompletion(source, tag) ) {
1099 ;
1100 }
1101
1102 // unpack data
1103#ifdef __VERBOSE_PARALLEL
1104 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received data from partition %3d\n",
1105 rank, "FETICommunicator :: setUpCommunicationMaps : received number of partition rbm", source);
1106#endif
1107 commBuff.init();
1108 commBuff.read( nsem.at(source + 1) );
1109 tnse += nsem.at(source + 1);
1110 }
1111
1112 nsem.at(1) = nse;
1113 tnse += nse;
1114
1115 OOFEM_LOG_INFO("Number of RBM per partion\npart. rbm\n-------------------------------\n");
1116 for ( int i = 1; i <= size; i++ ) {
1117 OOFEM_LOG_INFO( "%-4d %8d\n", i - 1, nsem.at(i) );
1118 }
1119
1120
1121 // initialize partition start indexes into rbm array
1122 rbmAddr.resize(size);
1123 rbmAddr.zero();
1124 rbmAddr.at(1) = 1;
1125 for ( int i = 2; i <= size; i++ ) {
1126 rbmAddr.at(i) = rbmAddr.at(i - 1) + nsem.at(i - 1);
1127 }
1128 } else { // slave code
1129#ifdef __VERBOSE_PARALLEL
1130 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Sending number of Rigid body modes %3d\n",
1131 rank, "FETISolver :: solveYourselfAt", nse);
1132#endif
1133
1134 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1135 commBuff.write(nse);
1136 commBuff.iSend(0, FETISolver :: NumberOfRBMMsg);
1137 }
1138
1139 MPI_Barrier(MPI_COMM_WORLD);
1140
1141 /*****************************/
1142 /* sestaveni cele matice L */
1143 /*****************************/
1144
1145 if ( rank == 0 ) {
1146 // assemble l matrix containing rbm localized from partition contibutions
1147 if ( tnse ) {
1148 l.resize(masterCommunicator->giveNumberOfDomainEquations(), tnse);
1149 l.zero();
1150 }
1151
1152 masterCommunicator->initReceive(FETISolver :: RBMMessage);
1153 masterCommunicator->unpackAllData(this, & FETISolver :: masterUnpackRBM);
1154 this->masterMapRBM();
1155
1156 if ( tnse ) {
1157 l.negated();
1158 }
1159 } else {
1160 // pack RBMs
1161 processCommunicator.packData(this, & FETISolver :: packRBM);
1162 processCommunicator.initSend(FETISolver :: RBMMessage);
1163 MPI_Barrier(MPI_COMM_WORLD);
1164#ifdef __VERBOSE_PARALLEL
1165 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: RBMMessage Barrier finished",
1166 rank, "FETISolver :: solveYourselfAt");
1167#endif
1168 }
1169
1170 if ( rank == 0 ) {
1171 // receive products of rbm * LoadVector
1172 if ( tnse ) {
1173 q.resize(tnse);
1174 q.zero();
1175 }
1176
1177 masterCommunicator->initReceive(FETISolver :: QQMessage);
1178 masterCommunicator->unpackAllData(this, & FETISolver :: masterUnpackQQProduct);
1179 this->masterMapQQProduct();
1180 } else {
1181 // pack QQ products
1182 processCommunicator.packData(this, & FETISolver :: packQQProducts);
1183 processCommunicator.initSend(FETISolver :: QQMessage);
1184 MPI_Barrier(MPI_COMM_WORLD);
1185 }
1186
1187 /*******************************************/
1188 /*******************************************/
1189 /* sestaveni matice L^T.L a jeji inverze */
1190 /*******************************************/
1191 /*******************************************/
1192
1193 if ( ( rank == 0 ) && ( tnse != 0 ) ) {
1194 FloatMatrix l2;
1195 // compute l1, the inverse of (l^Tl)
1196 l2.beTProductOf(l, l);
1197 l1.beInverseOf(l2);
1198 }
1199
1200 /****************************************************************************/
1201 /****************************************************************************/
1202 /* vypocet pocatecni aproximace neznamych do modifikovane met. sdr. grad. */
1203 /****************************************************************************/
1204 /****************************************************************************/
1205
1206 /****************************/
1207 /* alokace nekterych poli */
1208 /****************************/
1209 /* vektor smeru na jedne podoblasti */
1210 dd.resize(neq);
1211 /* pomocny vektor na jedne podoblasti */
1212 pp.resize(neq);
1213
1214
1215 if ( rank == 0 ) {
1216 /* vektor smeru */
1217 d.resize(masterCommunicator->giveNumberOfDomainEquations() + 1);
1218 /* pomocny vektor */
1219 p.resize( masterCommunicator->giveNumberOfDomainEquations() );
1220 /* vektor gradientu */
1221 g.resize( masterCommunicator->giveNumberOfDomainEquations() );
1222 /* vektor neznamych */
1223 w.resize( masterCommunicator->giveNumberOfDomainEquations() );
1224
1225 /* soucin (L^T.L)^{-1}.q */
1226 if ( tnse ) {
1227 FloatArray help(tnse);
1228 help.beProductOf(l1, q);
1229 w.beProductOf(l, help);
1230 } else {
1231 w.zero();
1232 }
1233
1234 // send aproximation of solution to slaves
1235 masterCommunicator->packAllData(this, & FETISolver :: packSolution);
1236 masterCommunicator->initSend(FETISolver :: SolutionMessage);
1237 this->masterMapSolution();
1238 } else {
1239 // receive send aproximation of solution
1240 processCommunicator.initReceive(FETISolver :: SolutionMessage);
1241 while ( !processCommunicator.receiveCompleted() ) {
1242 ;
1243 }
1244
1245 processCommunicator.unpackData(this, & FETISolver :: unpackSolution);
1246 }
1247
1248 MPI_Barrier(MPI_COMM_WORLD);
1249
1250#ifdef __VERBOSE_PARALLEL
1251 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Solution Approx Barrier finished\n",
1252 rank, "FETISolver :: solveYourselfAt");
1253#endif
1254
1255 dd.subtract(partitionLoad);
1256 partitionStiffness->ldl_feti_sky(pp, dd, nse, limit, se);
1257
1258 if ( rank == 0 ) {
1259 // receive contributions (to resudals) from slaves
1260
1261 masterCommunicator->initReceive(FETISolver :: ResidualMessage);
1262 masterCommunicator->unpackAllData(this, & FETISolver :: unpackResiduals);
1263 this->masterMapResiduals();
1264 } else {
1265 // send contributions (to resudals) to master
1266#ifdef __VERBOSE_PARALLEL
1267 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Residual contribution packing initiated\n",
1268 rank, "FETISolver :: solveYourselfAt");
1269#endif
1270 processCommunicator.packData(this, & FETISolver :: packResiduals);
1271#ifdef __VERBOSE_PARALLEL
1272 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Residual contribution send initiated\n",
1273 rank, "FETISolver :: solveYourselfAt");
1274#endif
1275 processCommunicator.initSend(FETISolver :: ResidualMessage);
1276
1277 MPI_Barrier(MPI_COMM_WORLD);
1278#ifdef __VERBOSE_PARALLEL
1279 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Residual contribution Barrier finished\n",
1280 rank, "FETISolver :: solveYourselfAt");
1281#endif
1282 }
1283
1284
1285 /* v tuto chvili je vypocten nulty vektor gradientu */
1286
1287 /***********************************/
1288 /* vypocet nulteho vektoru smeru */
1289 /***********************************/
1290 if ( rank == 0 ) {
1291 if ( tnse ) {
1292 this->projection(g, l, l1);
1293 }
1294
1295 d = g;
1296 d.negated();
1297
1298 /* vypocet nulteho citatele */
1299 nom = g.computeSquaredNorm();
1300
1301 //#ifdef __VERBOSE_PARALLEL
1302 OOFEM_LOG_DEBUG("\nIteration process\n");
1303 if ( energyNorm_comput_flag ) {
1304 OOFEM_LOG_DEBUG("iteration gradient vector norm energy norm\n=====================================================================\n");
1305 } else {
1306 OOFEM_LOG_DEBUG("iteration gradient vector norm\n================================================\n");
1307 }
1308
1309 //#endif
1310 }
1311
1312 /* cyklus vyjadrujici pocet iteraci */
1313 for ( int i = 0; i < ni; i++ ) {
1314 dd.zero();
1315 if ( rank == 0 ) {
1316 /***************************************/
1317 /* vypocet pomocneho vektoru K.d = p */
1318 /***************************************/
1319
1320 // send direction vector to slaves
1321 masterCommunicator->packAllData(this, & FETISolver :: packDirectionVector);
1322 masterCommunicator->initSend(FETISolver :: DirectionVectorMessage);
1324 } else {
1325 // receive direction vector on slaves
1326 processCommunicator.initReceive(FETISolver :: DirectionVectorMessage);
1327 while ( !processCommunicator.receiveCompleted() ) {
1328 ;
1329 }
1330
1331 processCommunicator.unpackData(this, & FETISolver :: unpackDirectionVector);
1332 }
1333
1334 MPI_Barrier(MPI_COMM_WORLD);
1335
1336
1337 pp.zero();
1338 partitionStiffness->ldl_feti_sky(pp, dd, nse, limit, se);
1339
1340 if ( rank == 0 ) {
1341 p.zero();
1342
1343 // receive contributions (to resudals) from slaves
1344
1345 masterCommunicator->initReceive(FETISolver :: PPVectorMessage);
1346 masterCommunicator->unpackAllData(this, & FETISolver :: unpackPPVector);
1347 this->masterMapPPVector();
1348 } else {
1349 // pack pp on all partitions
1350 processCommunicator.packData(this, & FETISolver :: packPPVector);
1351 processCommunicator.initSend(FETISolver :: PPVectorMessage);
1352 MPI_Barrier(MPI_COMM_WORLD);
1353 }
1354
1355 if ( rank == 0 ) {
1356 /* calculation of the denominator of the fraction defining Alpha */
1357 denom = d.dotProduct(p);
1358
1359 if ( fabs(denom) < FETISOLVER_ZERONUM ) {
1360 OOFEM_LOG_RELEVANT("FETISolver::solve : v modifikovane metode sdruzenych gradientu je nulovy jmenovatel u soucinitele alpha\n");
1361 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1362 commBuff.init();
1364 commBuff.bcast(0);
1365 break;
1366 }
1367
1368 /*******************/
1369 /* vypocet alpha */
1370 /*******************/
1371 alpha = nom / denom;
1372
1373 /**************************************************************/
1374 /* vypocet noveho gradientu g a nove aproximace neznamych x */
1375 /**************************************************************/
1376 for ( int j = 1; j <= masterCommunicator->giveNumberOfDomainEquations(); j++ ) {
1377 w.at(j) += alpha * d.at(j);
1378 g.at(j) += alpha * p.at(j);
1379 }
1380
1381
1382
1383 if ( tnse ) {
1384 this->projection(g, l, l1);
1385 }
1386
1387 denom = nom;
1388 if ( fabs(denom) < FETISOLVER_ZERONUM ) {
1389 OOFEM_LOG_RELEVANT("FETISolver::solve : v modifikovane metode sdruzenych gradientu je nulovy jmenovatel u soucinitele beta\n");
1390 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1391 commBuff.init();
1393 commBuff.bcast(0);
1394 break;
1395 }
1396
1397 nom = g.computeSquaredNorm();
1398
1399 if ( nom < err ) {
1400 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1401 commBuff.init();
1403 commBuff.bcast(0);
1404 break;
1405 }
1406
1407
1408 /******************/
1409 /* vypocet beta */
1410 /******************/
1411 beta = nom / denom;
1412
1413 /****************************/
1414 /* vypocet noveho smeru d */
1415 /****************************/
1416 for ( int j = 1; j <= masterCommunicator->giveNumberOfDomainEquations(); j++ ) {
1417 d.at(j) = beta * d.at(j) - g.at(j);
1418 }
1419 }
1420
1421
1422 if ( rank == 0 ) {
1423 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1424 commBuff.init();
1426 commBuff.bcast(0);
1427 } else {
1428 commBuff.resize( commBuff.givePackSizeOfInt(1) );
1429 commBuff.init();
1430 commBuff.bcast(0);
1431 commBuff.read(masterLoopStatus);
1432 if ( masterLoopStatus == FETISolverIterationBreak ) {
1433#ifdef __VERBOSE_PARALLEL
1434 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received Loop break signal from master\n",
1435 rank, "FETISolver :: solveYourselfAt");
1436#endif
1437
1438 break;
1439 }
1440 }
1441
1442
1443 // computation of energy norm
1444 if ( energyNorm_comput_flag ) {
1445 dd.zero();
1446 if ( rank == 0 ) {
1447 // send aproximation of solution to slaves
1448 masterCommunicator->packAllData(this, & FETISolver :: packSolution);
1449 masterCommunicator->initSend(FETISolver :: SolutionMessage);
1450 this->masterMapSolution();
1451 } else {
1452 // receive send aproximation of solution
1453 processCommunicator.initReceive(FETISolver :: SolutionMessage);
1454 while ( !processCommunicator.receiveCompleted() ) {
1455 ;
1456 }
1457
1458 processCommunicator.unpackData(this, & FETISolver :: unpackSolution);
1459 }
1460
1461 MPI_Barrier(MPI_COMM_WORLD);
1462
1463 pp.zero();
1464 partitionStiffness->ldl_feti_sky(pp, dd, nse, limit, se);
1465
1466 if ( rank == 0 ) {
1467 p.zero();
1468
1469 // receive contributions (to resudals) from slaves
1470
1471 masterCommunicator->initReceive(FETISolver :: PPVectorMessage);
1472 masterCommunicator->unpackAllData(this, & FETISolver :: unpackPPVector);
1473 this->masterMapPPVector();
1474 } else {
1475 // pack pp on all partitions
1476 processCommunicator.packData(this, & FETISolver :: packPPVector);
1477 processCommunicator.initSend(FETISolver :: PPVectorMessage);
1478 MPI_Barrier(MPI_COMM_WORLD);
1479 }
1480
1481 if ( rank == 0 ) {
1482 energyNorm = p.dotProduct(w);
1483 }
1484 }
1485
1486 // end of energy norm computation
1487
1488 //#ifdef __VERBOSE_PARALLEL
1489 if ( rank == 0 ) {
1490 if ( energyNorm_comput_flag ) {
1491 OOFEM_LOG_DEBUG("%-9d%15e %15e\n", i, nom, energyNorm);
1492 } else {
1493 OOFEM_LOG_DEBUG("%-9d%15e\n", i, nom);
1494 }
1495 }
1496#ifdef __VERBOSE_PARALLEL
1497 if ( rank == 0 ) {
1498 OOFEM_LOG_DEBUG("Konec metody sdruzenych gradientu, nite %d, err %e\n", i, nom);
1499 }
1500#endif
1501
1502 } // end iterative loop
1503
1504
1505 /* prelom (break) */
1506
1507 /****************************************************/
1508 /* konec modifikovane metody sdruzenych gradientu */
1509 /****************************************************/
1510
1511 if ( rank == 0 ) {
1512 OOFEM_LOG_INFO("End of iteration, reached norm %15e\n", nom);
1513#ifdef __VERBOSE_PARALLEL
1514 OOFEM_LOG_DEBUG("\nVysledne Lagrangeovy multiplikatory\n");
1515 for ( int i = 1; i <= masterCommunicator->giveNumberOfDomainEquations(); i++ ) {
1516 OOFEM_LOG_DEBUG( "lambda %4d %f\n", i, w.at(i) );
1517 }
1518
1519#endif
1520 }
1521
1522 dd.zero();
1523 if ( rank == 0 ) {
1524 // send solution to slaves
1525 masterCommunicator->packAllData(this, & FETISolver :: packSolution);
1526 masterCommunicator->initSend(FETISolver :: SolutionMessage);
1527 this->masterMapSolution();
1528 } else {
1529 // receive solution
1530 processCommunicator.initReceive(FETISolver :: SolutionMessage);
1531 while ( !processCommunicator.receiveCompleted() ) {
1532 ;
1533 }
1534
1535 processCommunicator.unpackData(this, & FETISolver :: unpackSolution);
1536 }
1537
1538 MPI_Barrier(MPI_COMM_WORLD);
1539
1540
1541#ifdef __VERBOSE_PARALLEL
1542 //fprintf(stdout, "\n[process rank %3d]: %-30s: Partition lagrange multipliers dump:\n",
1543 // rank,"FETISolver :: solveYourselfAt");
1544 //dd.printYourself();
1545#endif
1546
1547 partitionLoad.subtract(dd);
1548#ifdef __VERBOSE_PARALLEL
1549 // fprintf(stdout, "\n[process rank %3d]: %-30s: Partition load dump:\n",
1550 // rank,"FETISolver :: solveYourselfAt");
1551 //partitionLoad.printYourself();
1552#endif
1553 partitionStiffness->ldl_feti_sky(partitionSolution, partitionLoad, nse, limit, se);
1554 pp = partitionSolution;
1555
1556#ifdef __VERBOSE_PARALLEL
1557 //fprintf(stdout, "\n[process rank %3d]: %-30s: Partition solution dump:\n",
1558 // rank,"FETISolver :: solveYourselfAt");
1559 //pp.printYourself();
1560#endif
1561
1562 if ( rank == 0 ) {
1563 g.zero();
1564 // receive contributions (to resudals) from slaves
1565
1566 masterCommunicator->initReceive(FETISolver :: ResidualMessage);
1567 masterCommunicator->unpackAllData(this, & FETISolver :: unpackResiduals);
1568
1569#ifdef __VERBOSE_PARALLEL
1570 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Received residuals from slaves\n",
1571 rank, "FETISolver :: solveYourselfAt");
1572#endif
1573
1574 this->masterMapResiduals();
1575 } else {
1576 // send contributions (to resudals) to master
1577
1578#ifdef __VERBOSE_PARALLEL
1579 OOFEM_LOG_DEBUG("[process rank %3d]: %-30s: Sending residuals to master\n",
1580 rank, "FETISolver :: solveYourselfAt");
1581#endif
1582
1583 processCommunicator.packData(this, & FETISolver :: packResiduals);
1584 processCommunicator.initSend(FETISolver :: ResidualMessage);
1585 MPI_Barrier(MPI_COMM_WORLD);
1586 }
1587
1588#ifdef __VERBOSE_PARALLEL
1589 if ( rank == 0 ) {
1590 //fprintf(stdout, "\n[process rank %3d]: %-30s: Partition residuals dump:\n",
1591 // rank,"FETISolver :: solveYourselfAt");
1592 //g.printYourself();
1593 }
1594
1595#endif
1596
1597 if ( rank == 0 ) {
1598 if ( tnse ) {
1599 FloatArray help1;
1600 help1.beTProductOf(l, g);
1601 // coefficient of linear combinations
1602 gamma.beProductOf(l1, help1);
1603 } else {
1604 gamma.zero();
1605 }
1606
1607 // send corresponding gammas to slaves
1608 masterCommunicator->packAllData(this, & FETISolver :: packGammas);
1609 masterCommunicator->initSend(FETISolver :: GammasMessage);
1610 this->masterMapGammas();
1611 } else {
1612 // receive gammas
1613 processCommunicator.initReceive(FETISolver :: GammasMessage);
1614 while ( !processCommunicator.receiveCompleted() ) {
1615 ;
1616 }
1617
1618 processCommunicator.unpackData(this, & FETISolver :: unpackGammas);
1619 }
1620
1621 MPI_Barrier(MPI_COMM_WORLD);
1622
1623 if ( nse != 0 ) {
1624 FloatArray help;
1626
1627 partitionSolution.add(help);
1628 }
1629
1630 return CR_CONVERGED;
1631}
1632} // end namespace oofem
#define REGISTER_SparseLinSolver(class, type)
int write(bool data) override
Writes a bool value.
Definition combuff.C:273
int read(bool &data) override
Reads a bool value from data.
Definition combuff.C:265
virtual int givePackSizeOfDouble(std::size_t count)=0
int energyNorm_comput_flag
Flag indicating computation of energy norm.
Definition fetisolver.h:101
FloatArray w
Primary unknowns.
Definition fetisolver.h:87
FETICommunicator * masterCommunicator
Definition fetisolver.h:97
double limit
Linear dep./indep. trigger.
Definition fetisolver.h:77
FloatArray localGammas
Definition fetisolver.h:89
int masterMapDirectionVector()
Definition fetisolver.C:774
IntArray se
Indices of singular equations.
Definition fetisolver.h:83
FloatMatrix rbm
Rigid body motions.
Definition fetisolver.h:79
FloatArray gamma
Definition fetisolver.h:89
ProcessCommunicatorBuff pcbuff
Definition fetisolver.h:93
FloatMatrix l
Rigid body motions of all partitions. On master only.
Definition fetisolver.h:81
double err
Max allowed error.
Definition fetisolver.h:75
ProcessCommunicator processCommunicator
Definition fetisolver.h:94
void projection(FloatArray &v, FloatMatrix &l, FloatMatrix &l1)
Definition fetisolver.C:219
IntArray masterCommMap
List of local nodes (at master) participating in communication (list of boundary dof managers).
Definition fetisolver.h:99
CommunicatorBuff * commBuff
Common Communicator buffer.
Definition fetisolver.h:96
FloatArray dd
Definition fetisolver.h:89
int ni
Max number of iterations.
Definition fetisolver.h:73
FloatArray pp
Definition fetisolver.h:89
FloatArray qq
Definition fetisolver.h:89
void setUpCommunicationMaps()
Sets up the communication maps.
Definition fetisolver.C:116
IntArray rbmAddr
Addresses of initial partition contribution to rbm matrix.
Definition fetisolver.h:85
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:721
void add(const FloatArray &src)
Definition floatarray.C:218
void subtract(const FloatArray &src)
Definition floatarray.C:320
bool beInverseOf(const FloatMatrix &src)
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
void resize(int n)
Definition intarray.C:73
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
EngngModel * giveEngngModel()
Definition nummet.h:99
Domain * domain
Pointer to domain.
Definition nummet.h:84
EngngModel * engngModel
Pointer to engineering model.
Definition nummet.h:86
CommunicationBuffer & giveRecvBuff()
CommunicationBuffer & giveSendBuff()
const IntArray & giveToRecvMap()
ProcessCommunicatorBuff * giveProcessCommunicatorBuff()
Returns communication buffer.
const IntArray & giveToSendMap()
void ldl_feti_sky(FloatArray &x, FloatArray &y, int nse, double limit, IntArray &se)
Definition skyline.C:775
void rbmodes(FloatMatrix &r, int &nse, IntArray &se, double limit, int tc)
Definition skyline.C:634
SparseLinearSystemNM(Domain *d, EngngModel *m)
Constructor.
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition sparsemtrx.h:114
#define OOFEM_ERROR(...)
Definition error.h:79
#define FETISOLVER_MAX_RBM
Definition fetisolver.h:60
#define _IFT_FETISolver_energynormflag
Definition fetisolver.h:52
#define _IFT_FETISolver_limit
Definition fetisolver.h:51
#define _IFT_FETISolver_maxerr
Definition fetisolver.h:50
#define FETISOLVER_ZERONUM
computer zero
Definition fetisolver.h:62
#define _IFT_FETISolver_maxiter
Definition fetisolver.h:49
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define IR_GIVE_FIELD(__ir, __value, __id)
Definition inputrecord.h:67
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define OOFEM_LOG_RELEVANT(...)
Definition logger.h:142
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
@ DofManager_shared
Definition dofmanager.h:68
@ CBT_static

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011