void PreconditionerBlockMS<space_type>::init( void ) { if( Environment::worldComm().isMasterRank() ) std::cout << "Init preconditioner blockms\n"; LOG(INFO) << "Init ...\n"; tic(); BoundaryConditions M_bc = M_model.boundaryConditions(); LOG(INFO) << "Create sub Matrix\n"; map_vector_field<FEELPP_DIM,1,2> m_dirichlet_u { M_bc.getVectorFields<FEELPP_DIM> ( "u", "Dirichlet" ) }; map_scalar_field<2> m_dirichlet_p { M_bc.getScalarFields<2> ( "phi", "Dirichlet" ) }; /* * AA = [[ A - k^2 M, B^t], * [ B , 0 ]] * We need to extract A-k^2 M and add it M to form A+(1-k^2) M = A+g M */ // Is the zero() necessary ? M_11->zero(); this->matrix()->updateSubMatrix(M_11, M_Vh_indices, M_Vh_indices, false); // M_11 = A-k^2 M LOG(INFO) << "Use relax = " << M_relax << std::endl; M_11->addMatrix(M_relax,M_mass); // A-k^2 M + M_relax*M = A+(M_relax-k^2) M auto f2A = form2(_test=M_Vh, _trial=M_Vh,_matrix=M_11); auto f1A = form1(_test=M_Vh); for(auto const & it : m_dirichlet_u ) f2A += on(_range=markedfaces(M_Vh->mesh(),it.first), _expr=it.second,_rhs=f1A, _element=u, _type="elimination_symmetric"); /* * Rebuilding sub-backend */ backend(_name=M_prefix_11, _rebuild=true); backend(_name=M_prefix_22, _rebuild=true); // We have to set the G, Px,Py,Pz or X,Y,Z matrices to AMS if(soption(_name="pc-type", _prefix=M_prefix_11) == "ams") { #if FEELPP_DIM == 3 initAMS(); { if(boption(_name="setAlphaBeta",_prefix=M_prefix_11)) { auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")), _backend=backend(_name=M_prefix_11), _prefix=M_prefix_11, _matrix=M_11 ); prec->setMatrix(M_11); prec->attachAuxiliarySparseMatrix("a_alpha",M_a_alpha); prec->attachAuxiliarySparseMatrix("a_beta",M_a_beta); } } #else std::cerr << "ams preconditioner is not interfaced in two dimensions\n"; #endif } toc("[PreconditionerBlockMS] Init",FLAGS_v>0); LOG(INFO) << "Init done\n"; }
void PreconditionerBlockMS<space_type>::initAMS( void ) { M_grad = Grad( _domainSpace=M_Qh, _imageSpace=M_Vh); // This preconditioner is linked to that backend : the backend will // automatically use the preconditioner. auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")), _backend=backend(_name=M_prefix_11), _prefix=M_prefix_11, _matrix=M_11 ); prec->setMatrix(M_11); prec->attachAuxiliarySparseMatrix("G",M_grad.matPtr()); if(boption(M_prefix_11+".useEdge")) { LOG(INFO) << "[ AMS ] : using SetConstantEdgeVector \n"; ozz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(1),cst(0),cst(0))); zoz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(1),cst(0))); zzo.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(0),cst(1))); *M_ozz = ozz; M_ozz->close(); *M_zoz = zoz; M_zoz->close(); *M_zzo = zzo; M_zzo->close(); prec->attachAuxiliaryVector("Px",M_ozz); prec->attachAuxiliaryVector("Py",M_zoz); prec->attachAuxiliaryVector("Pz",M_zzo); } else { LOG(INFO) << "[ AMS ] : using SetCoordinates \n"; X.on(_range=elements(M_Vh->mesh()),_expr=Px()); Y.on(_range=elements(M_Vh->mesh()),_expr=Py()); Z.on(_range=elements(M_Vh->mesh()),_expr=Pz()); *M_X = X; M_X->close(); *M_Y = Y; M_Y->close(); *M_Z = Z; M_Z->close(); prec->attachAuxiliaryVector("X",M_X); prec->attachAuxiliaryVector("Y",M_Y); prec->attachAuxiliaryVector("Z",M_Z); } }
PreconditionerBlockMS<space_type>::PreconditionerBlockMS(space_ptrtype Xh, // (u)x(p) ModelProperties model, // model std::string const& p, // prefix sparse_matrix_ptrtype AA ) // The matrix : M_backend(backend()), // the backend associated to the PC M_Xh( Xh ), M_Vh( Xh->template functionSpace<0>() ), // Potential M_Qh( Xh->template functionSpace<1>() ), // Lagrange M_Vh_indices( M_Vh->nLocalDofWithGhost() ), M_Qh_indices( M_Qh->nLocalDofWithGhost() ), M_uin( M_backend->newVector( M_Vh ) ), M_uout( M_backend->newVector( M_Vh ) ), M_pin( M_backend->newVector( M_Qh ) ), M_pout( M_backend->newVector( M_Qh ) ), U( M_Xh, "U" ), M_mass(M_backend->newMatrix(M_Vh,M_Vh)), M_L(M_backend->newMatrix(M_Qh,M_Qh)), M_er( 1. ), M_model( model ), M_prefix( p ), M_prefix_11( p+".11" ), M_prefix_22( p+".22" ), u(M_Vh, "u"), ozz(M_Vh, "ozz"), zoz(M_Vh, "zoz"), zzo(M_Vh, "zzo"), M_ozz(M_backend->newVector( M_Vh )), M_zoz(M_backend->newVector( M_Vh )), M_zzo(M_backend->newVector( M_Vh )), X(M_Qh, "X"), Y(M_Qh, "Y"), Z(M_Qh, "Z"), M_X(M_backend->newVector( M_Qh )), M_Y(M_backend->newVector( M_Qh )), M_Z(M_backend->newVector( M_Qh )), phi(M_Qh, "phi") { tic(); LOG(INFO) << "[PreconditionerBlockMS] setup starts"; this->setMatrix( AA ); this->setName(M_prefix); /* Indices are need to extract sub matrix */ std::iota( M_Vh_indices.begin(), M_Vh_indices.end(), 0 ); std::iota( M_Qh_indices.begin(), M_Qh_indices.end(), M_Vh->nLocalDofWithGhost() ); M_11 = AA->createSubMatrix( M_Vh_indices, M_Vh_indices, true, true); /* Boundary conditions */ BoundaryConditions M_bc = M_model.boundaryConditions(); map_vector_field<FEELPP_DIM,1,2> m_dirichlet_u { M_bc.getVectorFields<FEELPP_DIM> ( "u", "Dirichlet" ) }; map_scalar_field<2> m_dirichlet_p { M_bc.getScalarFields<2> ( "phi", "Dirichlet" ) }; /* Compute the mass matrix (needed in first block, constant) */ auto f2A = form2(_test=M_Vh, _trial=M_Vh, _matrix=M_mass); auto f1A = form1(_test=M_Vh); f2A = integrate(_range=elements(M_Vh->mesh()), _expr=inner(idt(u),id(u))); // M for(auto const & it : m_dirichlet_u ) { LOG(INFO) << "Applying " << it.second << " on " << it.first << " for "<<M_prefix_11<<"\n"; f2A += on(_range=markedfaces(M_Vh->mesh(),it.first), _expr=it.second,_rhs=f1A, _element=u, _type="elimination_symmetric"); } /* Compute the L (= er * grad grad) matrix (the second block) */ auto f2L = form2(_test=M_Qh,_trial=M_Qh, _matrix=M_L); for(auto it : M_model.materials() ) { f2L += integrate(_range=markedelements(M_Qh->mesh(),marker(it)), _expr=M_er*inner(gradt(phi), grad(phi))); } auto f1LQ = form1(_test=M_Qh); for(auto const & it : m_dirichlet_p) { LOG(INFO) << "Applying " << it.second << " on " << it.first << " for "<<M_prefix_22<<"\n"; f2L += on(_range=markedfaces(M_Qh->mesh(),it.first),_element=phi, _expr=it.second, _rhs=f1LQ, _type="elimination_symmetric"); } if(soption(_name="pc-type", _prefix=M_prefix_11) == "ams") #if FEELPP_DIM == 3 { M_grad = Grad( _domainSpace=M_Qh, _imageSpace=M_Vh); // This preconditioner is linked to that backend : the backend will // automatically use the preconditioner. auto prec = preconditioner(_pc=pcTypeConvertStrToEnum(soption(M_prefix_11+".pc-type")), _backend=backend(_name=M_prefix_11), _prefix=M_prefix_11, _matrix=M_11 ); prec->setMatrix(M_11); prec->attachAuxiliarySparseMatrix("G",M_grad.matPtr()); if(boption(M_prefix_11+".useEdge")) { LOG(INFO) << "[ AMS ] : using SetConstantEdgeVector \n"; ozz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(1),cst(0),cst(0))); zoz.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(1),cst(0))); zzo.on(_range=elements(M_Vh->mesh()),_expr=vec(cst(0),cst(0),cst(1))); *M_ozz = ozz; M_ozz->close(); *M_zoz = zoz; M_zoz->close(); *M_zzo = zzo; M_zzo->close(); prec->attachAuxiliaryVector("Px",M_ozz); prec->attachAuxiliaryVector("Py",M_zoz); prec->attachAuxiliaryVector("Pz",M_zzo); } else { LOG(INFO) << "[ AMS ] : using SetCoordinates \n"; X.on(_range=elements(M_Vh->mesh()),_expr=Px()); Y.on(_range=elements(M_Vh->mesh()),_expr=Py()); Z.on(_range=elements(M_Vh->mesh()),_expr=Pz()); *M_X = X; M_X->close(); *M_Y = Y; M_Y->close(); *M_Z = Z; M_Z->close(); prec->attachAuxiliaryVector("X",M_X); prec->attachAuxiliaryVector("Y",M_Y); prec->attachAuxiliaryVector("Z",M_Z); } } #else std::cerr << "ams preconditioner is not interfaced in two dimensions\n"; #endif toc( "[PreconditionerBlockMS] setup done ", FLAGS_v > 0 ); }