6 #ifdef FLOW123D_HAVE_BDDCML
12 const unsigned numDofsSub,
13 const MatrixType matrixType,
16 : numDofs_( static_cast<int>( numDofs ) ),
17 numDofsSub_( static_cast<int>( numDofsSub ) ),
18 matrixType_( matrixType ),
20 numSubLoc_ ( numSubLoc )
28 rhsVec_.resize( numDofsSub_, 0. );
31 ifix_.resize( numDofsSub_, 0 );
32 fixv_.resize( numDofsSub_, 0. );
35 sol_.resize( numDofsSub_, 0. );
43 isMatAssembled_ =
false;
101 meshDim_ =
static_cast<int>( meshDim );
105 numElemSub_ = isegn.size( );
106 numNodesSub_ = isngn.size( );
109 numNodes_ = numNodes;
112 int numElemSubInt =
static_cast<int>( numElemSub_ );
114 &(procElemStarts[0]), 1,
MPI_INT, comm_ );
117 for (
unsigned i = 1; i < static_cast<unsigned>( nProc_ ); i++ )
118 procElemStarts[i] = procElemStarts[i-1] + procElemStarts[i];
120 for (
unsigned i = nProc_; i > 0; i-- )
121 procElemStarts[i] = procElemStarts[i-1];
123 procElemStarts[0] = 0;
126 numElem_ = procElemStarts[ nProc_ ];
129 OLD_ASSERT( std::accumulate( nnet.begin(), nnet.end(), 0 ) == (
int)(inet.size()),
130 "array inet size mismatch \n " );
131 OLD_ASSERT( std::accumulate( nndf.begin(), nndf.end(), 0 ) == numDofsSub_,
132 "array nndf content mismatch: %d %d \n ", std::accumulate( nndf.begin(), nndf.end(), 0 ), numDofsSub_ );
133 OLD_ASSERT(
static_cast<int>(isvgvn.size()) == numDofsSub_,
134 "array isvgvn size mismatch \n " );
135 OLD_ASSERT(
static_cast<int>(nnet.size()) == numElemSub_,
136 "array nnet size mismatch \n " );
137 OLD_ASSERT(
static_cast<int>(nndf.size()) == numNodesSub_,
138 "array nndf size mismatch \n " );
139 OLD_ASSERT(
static_cast<int>(xyz.size()) == numNodesSub_ * nDim_,
140 "array xyz size mismatch: %d %d \n ",
static_cast<int>(xyz.size()), numNodesSub_ * nDim_ );
143 inet_.resize( inet.size() );
144 std::copy( inet.begin(), inet.end(), inet_.begin() );
145 nnet_.resize( nnet.size() );
146 std::copy( nnet.begin(), nnet.end(), nnet_.begin() );
147 nndf_.resize( nndf.size() );
148 std::copy( nndf.begin(), nndf.end(), nndf_.begin() );
149 isegn_.resize( isegn.size() );
150 std::copy( isegn.begin(), isegn.end(), isegn_.begin() );
151 isngn_.resize( isngn.size() );
152 std::copy( isngn.begin(), isngn.end(), isngn_.begin() );
153 isvgvn_.resize( isvgvn.size() );
154 std::copy( isvgvn.begin(), isvgvn.end(), isvgvn_.begin() );
155 xyz_.resize( xyz.size() );
156 std::copy( xyz.begin(), xyz.end(), xyz_.begin() );
157 element_data_.resize( element_data.size() );
158 std::copy( element_data.begin(), element_data.end(), element_data_.begin() );
161 for (
unsigned ind = 0; ind < isvgvn_.size(); ++ind ) {
162 global2LocalDofMap_.insert( std::make_pair(
static_cast<unsigned>( isvgvn_[ind] ), ind ) );
176 unsigned length = numElements * elMatSize;
177 coo_.prepareAssembly( length );
185 const VecUint_ & rowIndices,
186 const VecUint_ & colIndices )
189 for (
unsigned i = 0; i < rowIndices.size(); i++) {
190 for (
unsigned j = 0; j < colIndices.size(); j++) {
193 if (subMat(i,j) != 0.0)
194 coo_.insert( rowIndices[i], colIndices[j], subMat(i,j) );
199 isMatAssembled_ =
false;
210 if ( isMatAssembled_ )
return;
213 coo_.finishAssembly( );
216 isMatAssembled_ =
true;
224 const VecUint_ & dofIndices )
226 for (
unsigned i = 0; i < dofIndices.size( ); i ++ ) {
229 Global2LocalMap_::iterator pos = global2LocalDofMap_.find( dofIndices[i] );
235 if (pos == global2LocalDofMap_.end()) {
236 DebugOut().every_proc() <<
"RHS, Missing map to local for idx: " << dofIndices[i];
238 const unsigned indLoc = pos -> second;
240 rhsVec_[ indLoc ] += subVec[i];
251 const double factor,
FMT_UNUSED const double scalar )
254 ConstraintVec_::const_iterator cIter = constraints.begin( );
255 ConstraintVec_::const_iterator cEnd = constraints.end( );
257 for ( ; cIter != cEnd; ++cIter ) {
258 unsigned globalDof = cIter -> first;
259 double value = (cIter -> second );
262 Global2LocalMap_::iterator pos = global2LocalDofMap_.find( globalDof );
263 if ( pos != global2LocalDofMap_.end() ) {
265 unsigned indLoc = pos -> second;
268 fixv_[ indLoc ] = factor *
value;
280 thisConstraint.push_back( std::make_pair( index, 0. ) );
281 this -> applyConstraints( thisConstraint, 1., scalar );
282 thisConstraint.clear();
290 const double &
value )
293 diagWeightsCoo_.insert( index, index,
value );
296 isDiagAssembled_ =
false;
307 if ( isDiagAssembled_ )
return;
310 diagWeightsCoo_.finishAssembly( );
313 isDiagAssembled_ =
true;
322 int verboseLevel,
int maxIt,
int ndecrMax,
bool use_adaptive )
327 "Subdomain mesh was not loaded, perhaps missing call to loadMesh() member function. \n " );
336 if ( numSubAtLevels != NULL ) {
339 OLD_ASSERT( numLevels ==
static_cast<int>((*numSubAtLevels).size()),
340 "Inconsistent size of numbers of subdomains at levels: %d %d \n",
341 numLevels,
static_cast<int>((*numSubAtLevels).size()) );
343 "Inconsistent number of subdomains at first level: %d %d \n",
344 (*numSubAtLevels)[0], numSub );
346 std::copy( (*numSubAtLevels).begin(), (*numSubAtLevels).end(),
352 if ( numLevels == 2 ) {
353 numSubLev[0] = numSub;
356 else if ( numLevels > 2 ) {
357 double coarsening = pow( numSub, 1. /
double(numLevels - 1) );
359 numSubLev[0] = numSub;
360 for (
int i = 1; i <= numLevels-2; i++) {
361 int ir = numLevels - i - 1;
362 numSubLev[i] = (int) pow( coarsening, ir );
363 if ( numSubLev[i]%2 != 0 ) {
364 numSubLev[i] = numSubLev[i] + 1;
367 numSubLev[numLevels-1] = 1;
370 OLD_ASSERT(
false,
"Missing numbers of subdomains at levels. \n" );
377 int lnumSubLev = numSubLev.size();
380 int justDirectSolve = 0;
382 bddcml_init_c( &numLevels, &(numSubLev[0]), &lnumSubLev, &numSubLoc_, &commInt, &verboseLevel, &numBase, &justDirectSolve );
389 int linet = inet_.size();
390 int lnnet = nnet_.size();
391 int lnndf = nndf_.size();
392 int lisngn = isngn_.size();
393 int lisvgvn = isvgvn_.size();
394 int lisegn = isegn_.size();
396 int lxyz1 = numNodesSub_;
399 int lifix = ifix_.size();
400 int lfixv = fixv_.size();
402 int lrhsVec = rhsVec_.size();
403 int isRhsCompleteInt = 0;
411 bool onlyUpperTriangle;
412 if ( matrixType_ == GENERAL ) {
413 onlyUpperTriangle =
false;
416 onlyUpperTriangle =
true;
420 this -> finishMatAssembly();
421 coo_.extractArrays( i_sparse, j_sparse, a_sparse, onlyUpperTriangle );
429 for (
unsigned inz = 0; inz < a_sparse.size(); inz++ ) {
430 if ( i_sparse[inz] != indRow ) {
431 indRow = i_sparse[inz];
432 Global2LocalMap_::iterator pos = global2LocalDofMap_.find(
static_cast<unsigned> ( indRow ) );
434 "Cannot remap index %d to local indices. \n ", indRow );
435 indRowLoc =
static_cast<int> ( pos -> second );
437 if ( j_sparse[inz] != indCol ) {
438 indCol = j_sparse[inz];
439 Global2LocalMap_::iterator pos = global2LocalDofMap_.find(
static_cast<unsigned> ( indCol ) );
441 "Cannot remap index %d to local indices. \n ", indCol );
442 indColLoc =
static_cast<int> ( pos -> second );
445 i_sparse[ inz ] = indRowLoc;
446 j_sparse[ inz ] = indColLoc;
451 int isMatAssembledInt = 0;
453 int la = a_sparse.size();
457 "It appears that diagonal weights for BDDC are not loaded. This is currently mandatory. \n " );
464 this -> finishDiagAssembly();
465 diagWeightsCoo_.extractArrays( i_diag_sparse, j_diag_sparse, diag_sparse );
466 diagWeightsCoo_.clear();
471 for (
unsigned inz = 0; inz < diag_sparse.size(); inz++ ) {
472 indRow = i_diag_sparse[inz];
473 Global2LocalMap_::iterator pos = global2LocalDofMap_.find(
static_cast<unsigned> ( indRow ) );
475 "Cannot remap index %d to local indices. \n ", indRow );
476 indRowLoc =
static_cast<int> ( pos -> second );
478 i_diag_sparse[ inz ] = indRowLoc;
481 int lsub_diagonal = numDofsSub_;
482 OLD_ASSERT( lsub_diagonal ==
static_cast<int>(diag_sparse.size()),
483 "Array length mismatch: %d %d . \n ", lsub_diagonal,
static_cast<int>(diag_sparse.size()) );
487 for (
int i = 0; i < lsub_diagonal; i++ ){
488 indRowLoc = i_diag_sparse[i];
489 double value = diag_sparse[i];
490 sub_diagonal[indRowLoc] =
value;
492 OLD_ASSERT( std::find(sub_diagonal.begin(), sub_diagonal.end(), -1. ) == sub_diagonal.end(),
493 "There are missing entries in the diagonal of weights. \n " );
496 int numDofsInt =
static_cast<int> ( numDofs_ );
497 int numDofsSubInt =
static_cast<int> ( numDofsSub_ );
500 if ( matrixType_ == GENERAL ) matrixTypeInt = 0 ;
501 else if ( matrixType_ == SPD ) matrixTypeInt = 1 ;
502 else if ( matrixType_ == SYMMETRICGENERAL ) matrixTypeInt = 2 ;
503 else if ( matrixType_ == SPD_VIA_SYMMETRICGENERAL ) matrixTypeInt = 2 ;
504 else {
OLD_ASSERT(
false,
"Illegal matrixType \n " );}
507 int lsol = sol_.size();
511 int lUserConstraints1 = 0;
512 int lUserConstraints2 = 0;
514 int lelement_data1 = 1;
515 int lelement_data2 = element_data_.size();
520 int find_components_int = 1;
521 int use_dual_mesh_graph_int = 0;
522 int neighbouring = 0;
525 bddcml_upload_subdomain_data_c( &numElem_, &numNodes_, &numDofsInt, &nDim_, &meshDim_,
526 &iSub, &numElemSub_, &numNodesSub_, &numDofsSubInt,
527 &(inet_[0]),&linet, &(nnet_[0]),&lnnet, &(nndf_[0]),&lnndf,
528 &(isngn_[0]),&lisngn, &(isvgvn_[0]),&lisvgvn, &(isegn_[0]),&lisegn,
529 &(xyz_[0]),&lxyz1,&lxyz2,
530 &(ifix_[0]),&lifix, &(fixv_[0]),&lfixv,
531 &(rhsVec_[0]),&lrhsVec, &isRhsCompleteInt,
533 &matrixTypeInt, &(i_sparse[0]), &(j_sparse[0]), &(a_sparse[0]), &
la, &isMatAssembledInt,
534 &(userConstraints[0]),&lUserConstraints1,&lUserConstraints2,
535 &(element_data_[0]),&lelement_data1,&lelement_data2,
536 &(sub_diagonal[0]), &lsub_diagonal,
537 &find_components_int, &use_dual_mesh_graph_int, &neighbouring );
545 int use_defaults_int = 0;
546 int parallel_division_int = 0;
547 int use_arithmetic_int = 1;
548 int use_adaptive_int;
549 if ( use_adaptive ) {
550 use_adaptive_int = 1;
553 use_adaptive_int = 0;
555 int use_user_constraints_int = 0;
556 int weights_type = 3;
559 int use_corner_constraints_int = 1;
563 bddcml_setup_preconditioner_c( & matrixTypeInt, & use_defaults_int,
564 & parallel_division_int, & use_arithmetic_int,
565 & use_corner_constraints_int,
566 & use_adaptive_int, & use_user_constraints_int,
571 double normSquaredLoc = 0.;
573 bddcml_dotprod_subdomain_c( &iSub, &(rhsVec_[0]), &lrhsVec, &(rhsVec_[0]), &lrhsVec, &normSquaredLoc );
575 for (
double elem: rhsVec_ ) normSquaredLoc += elem*elem;
579 double normSquared = 0.;
581 normRhs_ = std::sqrt( normSquared );
585 if ( matrixType_ == SPD )
587 else if ( matrixType_ == SPD_VIA_SYMMETRICGENERAL)
592 int recycling_int = 0;
593 int max_number_of_stored_vectors = 100;
597 bddcml_solve_c( & commInt, & method, & tol, & maxIt, & ndecrMax,
598 & recycling_int, & max_number_of_stored_vectors,
599 & numIter_, & convergedReason_, & condNumber_);
608 bddcml_download_local_solution_c( &iSub, &(sol_[0]), &lsol );
613 bddcml_dotprod_subdomain_c( &iSub, &(sol_[0]), &lsol, &(sol_[0]), &lsol, &normSquaredLoc );
615 for (
double elem: sol_ ) normSquaredLoc += elem*elem;
621 normSol_ = std::sqrt( normSquared );