ModelAlgebraic::ModelAlgebraic( std::string _theprefix, WorldComm const& _worldComm, std::string const& subPrefix, std::string const& rootRepository ) : super_type( _theprefix,_worldComm,subPrefix,rootRepository), M_verboseSolverTimer( boption(_name="verbose_solvertimer",_prefix=this->prefix()) ), M_verboseSolverTimerAllProc( boption(_name="verbose_solvertimer_allproc",_prefix=this->prefix()) ), M_rebuildCstPartInLinearSystem( boption(_name="linearsystem-cst-update",_prefix=this->prefix()) ), M_useLinearJacobianInResidual( boption(_name="residual-uselinearjac",_prefix=this->prefix()) ), M_rebuildLinearPartInJacobian( boption(_name="jacobian-linear-update",_prefix=this->prefix()) ), M_rebuildCstPartInResidual(true), // not an option (just opitmisation with semi-implicit) M_useCstMatrix( boption(_name="use-cst-matrix",_prefix=this->prefix()) ), M_useCstVector( boption(_name="use-cst-vector",_prefix=this->prefix()) ), M_needToRebuildCstPart( false ), M_errorIfSolverNotConverged( boption(_name="error-if-solver-not-converged",_prefix=this->prefix()) ), M_printGraph( boption(_name="graph-print-python",_prefix=this->prefix()) ) { //-----------------------------------------------------------------------// //-----------------------------------------------------------------------// if (Environment::vm().count(prefixvm(this->prefix(),"graph-print-python-filename"))) M_printGraphFileName = Environment::vm()[prefixvm(this->prefix(),"graph-print-python-filename")].as< std::string >(); else M_printGraphFileName = this->prefix()+".graphPython.py"; }
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 DrivenCavity<Dim>::run() { this->init(); auto U = Vh->element( "(u,p)" ); auto V = Vh->element( "(v,q)" ); auto u = U.template element<0>( "u" ); auto v = V.template element<0>( "u" ); auto p = U.template element<1>( "p" ); auto q = V.template element<1>( "p" ); //#if defined( FEELPP_USE_LM ) auto lambda = U.template element<2>(); auto nu = V.template element<2>(); //#endif u=vf::project(Vh->template functionSpace<0>(), elements(mesh), zero<Dim,1>()); p=vf::project(Vh->template functionSpace<1>(), elements(mesh), constant(0.0)); if ( Environment::worldComm().isMasterRank() ) std::cout << "Initializing residual " << "\n"; backend(_name="newtonns")->nlSolver()->residual = boost::bind( &DrivenCavity::Residual, boost::ref( *this ), _1, _2 ); if ( Environment::worldComm().isMasterRank() ) std::cout << "Initializing the Jacobian matrix" << "\n"; backend(_name="newtonns")->nlSolver()->jacobian = boost::bind( &DrivenCavity::Jacobian, boost::ref( *this ), _1, _2 ); if ( boption(_name="continuation" ) ) { double ReTarget = Re; int N = std::ceil( std::log( Re ) ); for( int i = 0; i <= N; ++i ) { Re = std::exp( std::log(1)+i*(std::log(ReTarget)-std::log(1))/double(N)); if ( Environment::worldComm().isMasterRank() ) std::cout << "Start solving for Reynolds = " << Re << "\n"; backend(_name="newtonns")->nlSolve( _solution=U ); if ( Environment::worldComm().isMasterRank() ) std::cout << "Done!" << "\n"; } } else { if ( Environment::worldComm().isMasterRank() ) std::cout << "Start solving for Reynolds = " << Re << "\n"; backend(_name="newtonns")->nlSolve( _solution=U ); if ( Environment::worldComm().isMasterRank() ) std::cout << "Done!" << "\n"; } this->exportResults( U ); }
void runApplicationSolid() { typedef FeelModels::SolidMechanics< Simplex<FEELPP_DIM,1>, Lagrange<OrderDisp, Vectorial,Continuous,PointSetFekete> > model_type; auto SM = model_type::New("solid"); if ( SM->isStationary() ) { bool algoQuasiStatic = boption(_name="solve-quasi-static"); if ( !algoQuasiStatic ) { SM->init(); SM->printAndSaveInfo(); SM->solve(); SM->exportResults(); } else { SM->init(); SM->printAndSaveInfo(); std::string variableSymbol = soption(_name="solve-quasi-static.variable-symbol"); CHECK( SM->modelProperties().parameters().find(variableSymbol) != SM->modelProperties().parameters().end() ) << "not find symbol " << variableSymbol; double valueFinal = SM->modelProperties().parameters().find(variableSymbol)->second.value(); double valueInitial = doption(_name="solve-quasi-static.variable-initial"); double valueStep = doption(_name="solve-quasi-static.variable-step"); int cptNeed = std::abs(valueFinal-valueInitial)/valueStep; double currentParam = valueInitial; std::string namefileVariableParameters = (fs::path(SM->rootRepository()) / fs::path("paramters-done.data")).string(); std::string saveType = soption(_name="solve-quasi-static.save.file-format"); int cptCurrent=1; if ( SM->doRestart() ) { std::ifstream fileParameter(namefileVariableParameters.c_str()); while ( ! fileParameter.eof() ) { fileParameter >> cptCurrent >> currentParam; } fileParameter.close(); SM->fieldDisplacement().load(_path=SM->rootRepository()+"/"+(boost::format("uSol.field-%1%") %cptCurrent ).str(), _type=saveType ); if ( SM->useDisplacementPressureFormulation() ) SM->fieldPressure().load(_path=SM->rootRepository()+"/"+(boost::format("pSol.field-%1%") %cptCurrent ).str(), _type=saveType ); SM->restartExporters(cptCurrent); ++cptCurrent; } else {
ExporterVTK<MeshType,N>::~ExporterVTK() { #if VTK_MAJOR_VERSION >= 6 && defined(VTK_HAS_PARALLEL) #if defined(FEELPP_VTK_INSITU_ENABLED) /* end up in situ simulation */ if(boption( _name="exporter.vtk.insitu.enable" )) { inSituProcessor->Finalize(); //inSituProcessor->Delete(); } #endif /* clean memory */ delete this->opaqueComm; #endif }
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); } }
void ExporterVTK<MeshType,N>::init() { if ( mesh_type::nDim == 1 ) if ( mesh_type::Shape == SHAPE_LINE ) { M_element_type = ( mesh_type::nOrder == 1 )? VTK_LINE : VTK_POLY_LINE; M_face_type = VTK_VERTEX; } if ( mesh_type::nDim == 2 ) { if ( mesh_type::Shape == SHAPE_TRIANGLE ) M_element_type = ( mesh_type::nOrder == 1 )? VTK_TRIANGLE : VTK_QUADRATIC_TRIANGLE; else if ( mesh_type::Shape == SHAPE_QUAD ) M_element_type = ( mesh_type::nOrder == 1 )? VTK_QUAD : VTK_QUADRATIC_QUAD; M_face_type = ( mesh_type::nOrder == 1 )? VTK_LINE : VTK_POLY_LINE; } if ( mesh_type::nDim == 3 ) { if ( mesh_type::Shape == SHAPE_TETRA ) { M_element_type = ( mesh_type::nOrder == 1 )? VTK_TETRA: VTK_QUADRATIC_TETRA; M_face_type = ( mesh_type::nOrder == 1 )? VTK_TRIANGLE : VTK_QUADRATIC_TRIANGLE; } else if ( mesh_type::Shape == SHAPE_HEXA ) { M_element_type = ( mesh_type::nOrder == 1 )? VTK_HEXAHEDRON : VTK_QUADRATIC_HEXAHEDRON; M_face_type = ( mesh_type::nOrder == 1 )? VTK_QUAD : VTK_QUADRATIC_QUAD; } } #if VTK_MAJOR_VERSION >= 6 && defined(VTK_HAS_PARALLEL) /* before version 5.10, we cannot initialize a MPIController with an external MPI_Comm */ this->lComm = this->worldComm().comm(); /* initialize the VTK communicator from the current MPI communicator */ this->opaqueComm = new vtkMPICommunicatorOpaqueComm(&(this->lComm)); #if defined(FEELPP_VTK_INSITU_ENABLED) /* initialize in-situ visualization if needed */ if(boption( _name="exporter.vtk.insitu.enable" )) { if(inSituProcessor == NULL) { inSituProcessor = vtkSmartPointer<vtkCPProcessor>::New(); inSituProcessor->Initialize(*(this->opaqueComm)); //inSituProcessor->DebugOn(); } else { inSituProcessor->RemoveAllPipelines(); } /* specify a user script */ std::string pyscript = soption( _name="exporter.vtk.insitu.pyscript" ); if(pyscript != "") { vtkSmartPointer<vtkCPPythonScriptPipeline> pipeline = vtkSmartPointer<vtkCPPythonScriptPipeline>::New(); pipeline->Initialize(pyscript.c_str()); inSituProcessor->AddPipeline(pipeline.GetPointer()); } /* else revert to a basic VTK pipeline */ else { vtkSmartPointer<vtkBaseInsituPipeline> pipeline = vtkSmartPointer<vtkBaseInsituPipeline>::New(); pipeline->Initialize(); inSituProcessor->AddPipeline(pipeline.GetPointer()); } } #endif #endif //std::cout << "Faces: " << M_face_type << "; Elements: " << M_element_type << std::endl; }
void ExporterVTK<MeshType,N>::save() const { int stepIndex = TS_INITIAL_INDEX; double time = 0.0; bool hasSteps = true; std::ostringstream fname; std::ostringstream oss; DVLOG(2) << "[ExporterVTK] checking if frequency is ok\n"; if ( this->cptOfSave() % this->freq() ) { this->saveTimeSet(); return; } DVLOG(2) << "[ExporterVTK] frequency is ok\n"; DVLOG(2) << "[ExporterVTK] save()...\n"; timeset_const_iterator __ts_it = this->beginTimeSet(); timeset_const_iterator __ts_en = this->endTimeSet(); int i = 0; while ( __ts_it != __ts_en ) { timeset_ptrtype __ts = *__ts_it; typename timeset_type::step_const_iterator __it = __ts->beginStep(); typename timeset_type::step_const_iterator __end = __ts->endStep(); /* instanciante data object */ vtkSmartPointer<vtkout_type> out = vtkSmartPointer<vtkout_type>::New(); /* check if we have steps for the current dataset */ if(__it == __end) { LOG(INFO) << "Timeset " << __ts->name() << " (" << __ts->index() << ") contains no timesteps (Consider using add() or addRegions())" << std::endl; hasSteps = false; /* save mesh if we have one */ if(__ts->hasMesh()) { this->saveMesh(__ts->mesh(), out); } } else { __it = boost::prior( __end ); typename timeset_type::step_ptrtype __step = *__it; if ( __step->isInMemory() ) { /* write data into vtk object */ this->saveMesh(__step->mesh(), out); this->saveNodeData( __step, __step->beginNodalScalar(), __step->endNodalScalar(), out ); this->saveNodeData( __step, __step->beginNodalVector(), __step->endNodalVector(), out ); this->saveNodeData( __step, __step->beginNodalTensor2(), __step->endNodalTensor2(), out ); this->saveElementData( __step, __step->beginElementScalar(), __step->endElementScalar(), out ); this->saveElementData( __step, __step->beginElementVector(), __step->endElementVector(), out ); this->saveElementData( __step, __step->beginElementTensor2(), __step->endElementTensor2(), out ); #if VTK_MAJOR_VERSION >= 6 && defined(VTK_HAS_PARALLEL) out->GetInformation()->Set(vtkDataObject::DATA_TIME_STEP(), __step->time()); #endif /* record time value */ time = __step->time(); stepIndex = __step->index(); } } /* Build a multi block dataset based on gathered data */ vtkSmartPointer<vtkMultiBlockDataSet> mbds = this->buildMultiBlockDataSet( time, out ); /* InitializeExternal is only supported from 5.10+, */ /* but lets aim for the latest major version 6 to reduce the complexity */ fname.str(""); fname << this->path() << "/" << this->prefix() //<< this->prefix() //this->path() << "-" << (stepIndex - TS_INITIAL_INDEX); #if VTK_MAJOR_VERSION < 6 || !defined(VTK_HAS_PARALLEL) fname << "-" << this->worldComm().size() << "_" << this->worldComm().rank(); #endif fname << ".vtm"; #if defined(FEELPP_VTK_INSITU_ENABLED) /* initialize in-situ visualization if needed and if we specified pipelines to handle */ if(boption( _name="exporter.vtk.insitu.enable" ) && inSituProcessor->GetNumberOfPipelines() > 0) { //std::cout << "Processing timestep In-Situ " << (__step->index() - TS_INITIAL_INDEX) << " " << __step->time() << std::endl; vtkSmartPointer<vtkCPDataDescription> dataDescription = vtkSmartPointer<vtkCPDataDescription>::New(); dataDescription->AddInput("input"); dataDescription->SetTimeData(time, stepIndex - TS_INITIAL_INDEX); vtkStdString sh = soption( _name="exporter.vtk.insitu.hostname"); vtkSmartPointer<vtkStringArray> hname = vtkSmartPointer<vtkStringArray>::New(); hname->SetName( "hostname" ); hname->InsertNextValue(sh); vtkSmartPointer<vtkIntArray> port = vtkSmartPointer<vtkIntArray>::New(); port->SetName( "port" ); port->InsertNextValue( ioption( _name="exporter.vtk.insitu.port") ); vtkSmartPointer<vtkFieldData> fdata = vtkSmartPointer<vtkFieldData>::New(); fdata->AddArray(hname); fdata->AddArray(port); dataDescription->SetUserData(fdata); if(inSituProcessor->RequestDataDescription(dataDescription.GetPointer()) != 0) { dataDescription->GetInputDescriptionByName("input")->SetGrid(mbds); //dataDescription->SetForceOutput(true); //std::cout << "CoProcess " << inSituProcessor->CoProcess(dataDescription.GetPointer())<< std::endl; inSituProcessor->CoProcess(dataDescription.GetPointer()); } } /* if insitu is not enable, or if it is enabled but we want to save data */ /* handle thoses cases with this if */ if(!(boption( _name="exporter.vtk.insitu.enable" )) || inSituProcessor->GetNumberOfPipelines() == 0 || (boption( _name="exporter.vtk.insitu.enable" ) && boption( _name="exporter.vtk.insitu.save" ) ) ) { #endif /* write VTK files */ this->write(stepIndex, fname.str(), mbds); /* write additional file for handling time steps */ /* only write on master rank */ if(this->worldComm().isMasterRank()) { /* rebuild the filename for the pvd file */ /* This removes the path used for exporting */ std::ostringstream lfile; lfile << this->prefix() //<< this->prefix() //this->path() << "-" << (stepIndex - TS_INITIAL_INDEX); #if VTK_MAJOR_VERSION < 6 || !defined(VTK_HAS_PARALLEL) lfile << "-" << this->worldComm().size() << "_" << this->worldComm().rank(); #endif lfile << ".vtm"; /* check if we are on the initial timestep */ /* if so, we delete the previous pvd file */ /* otherwise we would append dataset to already existing data */ std::string pvdFilename = this->path() + "/" + this->prefix() + ".pvd"; if( (stepIndex - TS_INITIAL_INDEX) == 0 && fs::exists(pvdFilename.c_str())) { fs::remove(pvdFilename.c_str()); } #if VTK_MAJOR_VERSION < 6 || !defined(VTK_HAS_PARALLEL) /* when we are not writing data with parallel filters */ /* we provide the info about the different parts from with */ /* a dataset is built: the different file names and the part id */ std::ostringstream oss; for(int i = 0; i < this->worldComm().size(); i++) { oss.str(""); oss << this->prefix() << "-" << (stepIndex - TS_INITIAL_INDEX) << "-" << this->worldComm().size() << "_" << i << ".vtm"; this->writeTimePVD(pvdFilename, time, oss.str(), i); } #else /* When writing in parallel, we only write one entry in the pvd file */ this->writeTimePVD(pvdFilename, time, lfile.str()); #endif } #if defined(FEELPP_VTK_INSITU_ENABLED) } #endif __ts_it++; } DVLOG(2) << "[ExporterVTK] saving done\n"; this->saveTimeSet(); }
createGMSHMesh, // 2. function name tag, // 3. namespace of tag types ( required ( mesh, * ) ( desc, * ) ) // 4. one required parameter, and ( optional ( prefix,(std::string), "" ) ( format, *, ioption(_prefix=prefix,_name="gmsh.format") ) ( h, *( boost::is_arithmetic<mpl::_> ), doption(_prefix=prefix,_name="gmsh.hsize") ) //( geo_parameters, *( boost::icl::is_map<mpl::_> ), Gmsh::gpstr2map("") ) ( parametricnodes, *( boost::is_integral<mpl::_> ), 0 ) ( in_memory, *( boost::is_integral<mpl::_> ), boption(_prefix=prefix,_name="gmsh.in-memory") ) ( straighten, *( boost::is_integral<mpl::_> ), boption(_prefix=prefix,_name="gmsh.straighten") ) ( refine, *( boost::is_integral<mpl::_> ), ioption(_prefix=prefix,_name="gmsh.refine") ) ( structured, *( boost::is_integral<mpl::_> ), ioption(_prefix=prefix,_name="gmsh.structured") ) ( update, *( boost::is_integral<mpl::_> ), MESH_RENUMBER|MESH_UPDATE_EDGES|MESH_UPDATE_FACES|MESH_CHECK ) ( force_rebuild, *( boost::is_integral<mpl::_> ), 0 ) ( physical_are_elementary_regions, *,boption(_prefix=prefix,_name="gmsh.physical_are_elementary_regions")) ( periodic, *, PeriodicEntities() ) ( respect_partition, (bool), boption(_prefix=prefix,_name="gmsh.respect_partition") ) ( rebuild_partitions, (bool), boption(_prefix=prefix,_name="gmsh.partition") ) ( rebuild_partitions_filename, *( boost::is_convertible<mpl::_,std::string> ) , desc->prefix()+".msh" ) ( worldcomm, *, Environment::worldComm() ) ( partitions, *( boost::is_integral<mpl::_> ), worldcomm.localSize() ) ( partition_file, *( boost::is_integral<mpl::_> ), 0 ) ( partitioner, *( boost::is_integral<mpl::_> ), ioption(_prefix=prefix,_name="gmsh.partitioner") ) )
void Partitioning<Dim>::run() { int p = 2; int* pm = new int[p]; for(unsigned short i = 0; i < p; ++i) pm[i] = i * (Environment::numberOfProcessors() / p); bool excluded = std::binary_search(pm, pm + p, Environment::rank()); mpi::group new_group; if(excluded) new_group = Environment::worldComm().group().include(pm,pm+p); else new_group = Environment::worldComm().group().exclude(pm,pm+p); delete [] pm; boost::mpi::communicator bComm(Environment::worldComm(), new_group); std::vector<int> active( bComm.size(), true ); WorldComm wComm(bComm,bComm,bComm,bComm.rank(),active); //wComm.showMe(); boost::shared_ptr<Mesh<Simplex<Dim>>> mesh; if(!excluded) { std::cout << "proc " << Environment::rank() << " is not excluded and is locally rank " << wComm.rank() << " and loads mesh with " << wComm.globalSize() << " partitions\n"; // mesh = loadMesh(_mesh = new Mesh<Simplex<Dim>>(wComm), _worldcomm=wComm ); mesh = createGMSHMesh(_mesh = new Mesh<Simplex<Dim>>(wComm), _worldcomm = wComm, _desc = domain(_worldcomm = wComm, _name = "hypercube", _shape = "hypercube", _xmin = 0.0, _xmax = 1.0, _ymin = 0.0, _ymax = 1.0, _zmin = 0.0, _zmax = 1.0)); std::cout << " - nelement(mesh)=" << nelements(elements(mesh)) << "\n"; std::cout << " - loading space\n"; auto Vh = Pch<2>( mesh ); auto u = Vh->element("u"); auto f = expr( soption(_name="functions.f"), "f", wComm ); auto g = expr( soption(_name="functions.g"), "g", wComm ); auto v = Vh->element( g, "g" ); auto l = form1( _test=Vh ); l = integrate(_range=elements(mesh),_expr=f*id(v)); auto a = form2( _trial=Vh, _test=Vh); a = integrate(_range=elements(mesh), _expr=gradt(u)*trans(grad(v)) ); if(boption("gmsh.domain.usenames")) { if(nelements(markedfaces(mesh, "Dirichlet"), boption("use_global")) > 0) a+=on(_range=markedfaces(mesh, "Dirichlet"), _rhs=l, _element=u, _expr=g); } else a+=on(_range=boundaryfaces(mesh), _rhs=l, _element=u, _expr=g); a.solve(_rhs=l,_solution=u); auto e = exporter( _mesh=mesh ); //e->addRegions(); e->add( "u", u ); e->add( "g", v ); e->save(); } else { std::cout << "proc " << Environment::rank() << " is excluded and does not load mesh"; int np = 0; mpi::all_reduce(wComm, 1, np, std::plus<int>()); std::cout << "proc " << Environment::rank() << " - nb proc = " << np << "\n"; } } // Partitioning::run
typename CRBTrilinear<TruthModelType>::convergence_type CRBTrilinear<TruthModelType>::offline() { int proc_number = this->worldComm().globalRank(); bool rebuild_database = boption(_name="crb.rebuild-database") ; bool orthonormalize_primal = boption(_name="crb.orthonormalize-primal") ; boost::timer ti; if( this->worldComm().isMasterRank() ) std::cout << "Offline CRBTrilinear starts, this may take a while until Database is computed..."<<std::endl; LOG(INFO) << "[CRBTrilinear::offline] Starting offline for output " << this->M_output_index << "\n"; LOG(INFO) << "[CRBTrilinear::offline] initialize underlying finite element model\n"; //M_model->initModel(); LOG( INFO )<< " -- model init done in " << ti.elapsed() << "s"; parameter_type mu( this->M_Dmu ); double delta_pr; double delta_du; size_type index; //if M_N == 0 then there is not an already existing database if ( rebuild_database || this->M_N == 0) { ti.restart(); LOG(INFO) << "[CRBTrilinear::offline] compute random sampling\n"; int total_proc = this->worldComm().globalSize(); std::string sampling_mode = soption("crb.sampling-mode"); bool all_proc_same_sampling=boption("crb.all-procs-have-same-sampling"); int sampling_size = ioption("crb.sampling-size"); std::string file_name = ( boost::format("M_Xi_%1%_"+sampling_mode+"-proc%2%on%3%") % sampling_size %proc_number %total_proc ).str(); if( all_proc_same_sampling ) file_name+="-all-proc-have-same-sampling"; std::ifstream file ( file_name ); if( ! file ) { // random sampling std::string supersamplingname =(boost::format("Dmu-%1%-generated-by-master-proc") %sampling_size ).str(); if( sampling_mode == "log-random" ) this->M_Xi->randomize( sampling_size , all_proc_same_sampling , supersamplingname ); else if( sampling_mode == "log-equidistribute" ) this->M_Xi->logEquidistribute( sampling_size , all_proc_same_sampling , supersamplingname ); else if( sampling_mode == "equidistribute" ) this->M_Xi->equidistribute( sampling_size , all_proc_same_sampling , supersamplingname ); else throw std::logic_error( "[CRBTrilinear::offline] ERROR invalid option crb.sampling-mode, please select between log-random, log-equidistribute or equidistribute" ); //M_Xi->equidistribute( this->vm()["crb.sampling-size"].template as<int>() ); this->M_Xi->writeOnFile(file_name); } else { this->M_Xi->clear(); this->M_Xi->readFromFile(file_name); } this->M_WNmu->setSuperSampling( this->M_Xi ); LOG( INFO )<<"[CRBTrilinear offline] M_error_type = "<<this->M_error_type<<std::endl; LOG(INFO) << " -- sampling init done in " << ti.elapsed() << "s"; ti.restart(); // empty sets this->M_WNmu->clear(); if( this->M_error_type == CRB_NO_RESIDUAL ) mu = this->M_Dmu->element(); else { // start with M_C = { arg min mu, mu \in Xi } boost::tie( mu, index ) = this->M_Xi->min(); } int size = mu.size(); //std::cout << " -- WN size : " << M_WNmu->size() << "\n"; // dimension of reduced basis space this->M_N = 0; this->M_maxerror = 1e10; delta_pr = 0; delta_du = 0; //boost::tie( M_maxerror, mu, index ) = maxErrorBounds( N ); LOG(INFO) << "[CRBTrilinear::offline] allocate reduced basis data structures\n"; this->M_Aqm_pr.resize( this->M_model->Qa() ); for(int q=0; q<this->M_model->Qa(); q++) { this->M_Aqm_pr[q].resize( 1 ); } M_Aqm_tril_pr.resize( this->M_model->QaTri() ); //for(int q=0; q<this->M_model->QaTri(); q++) this->M_Fqm_pr.resize( this->M_model->Ql( 0 ) ); for(int q=0; q<this->M_model->Ql( 0 ); q++) { this->M_Fqm_pr[q].resize( 1 ); } this->M_Lqm_pr.resize( this->M_model->Ql( this->M_output_index ) ); for(int q=0; q<this->M_model->Ql( this->M_output_index ); q++) this->M_Lqm_pr[q].resize( 1 ); }//end of if( rebuild_database ) #if 1 else { mu = this->M_current_mu; if( proc_number == 0 ) { std::cout<<"we are going to enrich the reduced basis"<<std::endl; std::cout<<"there are "<<this->M_N<<" elements in the database"<<std::endl; } LOG(INFO) <<"we are going to enrich the reduced basis"<<std::endl; LOG(INFO) <<"there are "<<this->M_N<<" elements in the database"<<std::endl; }//end of else associated to if ( rebuild_databse ) #endif LOG(INFO) << "[CRBTrilinear::offline] compute affine decomposition\n"; std::vector< std::vector<sparse_matrix_ptrtype> > Aqm; std::vector< std::vector<sparse_matrix_ptrtype> > Aqm_tril; std::vector< std::vector<std::vector<vector_ptrtype> > > Fqm; boost::tie( boost::tuples::ignore, Aqm, Fqm ) = this->M_model->computeAffineDecomposition(); element_ptrtype u( new element_type( this->M_model->functionSpace() ) ); LOG(INFO) << "[CRBTrilinear::offline] starting offline adaptive loop\n"; bool reuse_prec = this->vm()["crb.reuse-prec"].template as<bool>() ; bool use_predefined_WNmu = this->vm()["crb.use-predefined-WNmu"].template as<bool>() ; int N_log_equi = this->vm()["crb.use-logEquidistributed-WNmu"].template as<int>() ; int N_equi = this->vm()["crb.use-equidistributed-WNmu"].template as<int>() ; int N_random = ioption( "crb.use-random-WNmu" ); /* if( N_log_equi > 0 || N_equi > 0 ) use_predefined_WNmu = true;*/ // file where the sampling is savec std::string file_name = ( boost::format("SamplingWNmu") ).str(); std::ifstream file ( file_name ); this->M_WNmu->clear(); if ( use_predefined_WNmu ) // In this case we want to read the sampling { if( ! file ) // The user forgot to give the sampling file throw std::logic_error( "[CRB::offline] ERROR the file SamplingWNmu doesn't exist so it's impossible to known which parameters you want to use to build the database" ); else { int sampling_size = this->M_WNmu->readFromFile(file_name); if( Environment::isMasterRank() ) std::cout<<"[CRB::offline] Read WNmu ( sampling size : " << sampling_size <<" )"<<std::endl; LOG( INFO )<<"[CRB::offline] Read WNmu ( sampling size : " << sampling_size <<" )"; } } else // We generate the sampling with choosen strategy { if ( N_log_equi>0 ) { this->M_WNmu->logEquidistribute( N_log_equi , true ); if( Environment::isMasterRank() ) std::cout<<"[CRB::offline] Log-Equidistribute WNmu ( sampling size : " <<N_log_equi<<" )"<<std::endl; LOG( INFO )<<"[CRB::offline] Log-Equidistribute WNmu ( sampling size : " <<N_log_equi<<" )"; } else if ( N_equi>0 ) { this->M_WNmu->equidistribute( N_equi , true ); if( Environment::isMasterRank() ) std::cout<<"[CRB::offline] Equidistribute WNmu ( sampling size : " <<N_equi<<" )"<<std::endl; LOG( INFO )<<"[CRB::offline] Equidistribute WNmu ( sampling size : " <<N_equi<<" )"; } else if ( N_random>0 ) { this->M_WNmu->randomize( N_random , true ); if( Environment::isMasterRank() ) std::cout<<"[CRB::offline] Randomize WNmu ( sampling size : " <<N_random<<" )"<<std::endl; LOG( INFO )<<"[CRB::offline] Randomize WNmu ( sampling size : " <<N_random<<" )"; } else // In this case we don't know what sampling to use throw std::logic_error( "[CRB::offline] ERROR : You have to choose an appropriate strategy for the offline sampling : random, equi, logequi or predefined" ); this->M_WNmu->writeOnFile(file_name); /* if( ! file ) { this->M_WNmu->clear(); std::vector< parameter_type > V; parameter_type __mu; __mu = this->M_Dmu->element(); __mu(0)= 1 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 111112 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 222223 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 333334 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 444445 , __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 555556 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 666667 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 777778 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 888889 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 1e+06 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 8123 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)= 9123 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=1.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=2.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=4.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=912 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=1.123e3 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=4.123e3 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=7.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=2123 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=6.123e3 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=3.123e3 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=3.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=5.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=9.123e4 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=812 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=5.111e3 ; __mu(1)= 1 ; V.push_back( __mu ); __mu(0)=5.124e2 ; __mu(1)= 1 ; V.push_back( __mu ); this->M_WNmu->setElements( V ); this->M_iter_max = this->M_WNmu->size(); this->M_WNmu->writeOnFile(file_name); }*/ use_predefined_WNmu=true; } //build sampling this->M_iter_max = this->M_WNmu->size(); mu = this->M_WNmu->at( this->M_N ); // first element if( this->M_error_type == CRB_NO_RESIDUAL || use_predefined_WNmu ) { //in this case it makes no sens to check the estimated error this->M_maxerror = 1e10; } LOG(INFO) << "[CRBTrilinear::offline] strategy "<< this->M_error_type <<"\n"; while ( this->M_maxerror > this->M_tolerance && this->M_N < this->M_iter_max ) { boost::timer timer, timer2; LOG(INFO) <<"========================================"<<"\n"; if( proc_number == this->worldComm().masterRank() ) std::cout<<"construction of "<<this->M_N<<"/"<<this->M_iter_max<<" basis "<<std::endl; LOG(INFO) << "N=" << this->M_N << "/" << this->M_iter_max << "( nb proc : "<<worldComm().globalSize()<<")"; // for a given parameter \p mu assemble the left and right hand side u->setName( ( boost::format( "fem-primal-N%1%-proc%2%" ) % (this->M_N) % proc_number ).str() ); mu.check(); u->zero(); timer2.restart(); LOG(INFO) << "[CRB::offline] solving primal" << "\n"; *u = this->M_model->solve( mu ); //if( proc_number == this->worldComm().masterRank() ) std::cout << " -- primal problem solved in " << timer2.elapsed() << "s\n"; timer2.restart(); if( ! use_predefined_WNmu ) this->M_WNmu->push_back( mu, index ); this->M_WNmu_complement = this->M_WNmu->complement(); this->M_model->rBFunctionSpace()->addPrimalBasisElement( *u ); //WARNING : the dual element is not the real dual solution ! //no dual problem was solved this->M_model->rBFunctionSpace()->addDualBasisElement( *u ); int number_of_added_elements=1; this->M_N+=number_of_added_elements; if ( orthonormalize_primal ) { this->orthonormalize( this->M_N, this->M_model->rBFunctionSpace()->primalRB() , number_of_added_elements ); this->orthonormalize( this->M_N, this->M_model->rBFunctionSpace()->primalRB() , number_of_added_elements ); this->orthonormalize( this->M_N, this->M_model->rBFunctionSpace()->primalRB() , number_of_added_elements ); } LOG(INFO) << "[CRB::offline] compute Aq_pr, Aq_du, Aq_pr_du" << "\n"; for (size_type q = 0; q < this->M_model->Qa(); ++q ) { this->M_Aqm_pr[q][0].conservativeResize( this->M_N, this->M_N ); // only compute the last line and last column of reduced matrices for ( size_type i = this->M_N-number_of_added_elements; i < this->M_N; i++ ) { for ( size_type j = 0; j < this->M_N; ++j ) { this->M_Aqm_pr[q][0]( i, j ) = Aqm[q][0]->energy( this->M_model->rBFunctionSpace()->primalBasisElement(i) , this->M_model->rBFunctionSpace()->primalBasisElement(j) ); } } for ( size_type j=this->M_N-number_of_added_elements; j < this->M_N; j++ ) { for ( size_type i = 0; i < this->M_N; ++i ) { this->M_Aqm_pr[q][0]( i, j ) = Aqm[q][0]->energy( this->M_model->rBFunctionSpace()->primalBasisElement(i), this->M_model->rBFunctionSpace()->primalBasisElement(j) ); } } }//loop over q LOG(INFO) << "[CRBTrilinear::offline] compute Fq_pr" << "\n"; for ( size_type q = 0; q < this->M_model->Ql( 0 ); ++q ) { this->M_Fqm_pr[q][0].conservativeResize( this->M_N ); for ( size_type l = 1; l <= number_of_added_elements; ++l ) { int index = this->M_N-l; this->M_Fqm_pr[q][0]( index ) = this->M_model->Fqm( 0, q, 0, this->M_model->rBFunctionSpace()->primalBasisElement(index) ); } }//loop over q LOG(INFO) << "[CRB::offline] compute Lq_pr" << "\n"; for ( size_type q = 0; q < this->M_model->Ql( this->M_output_index ); ++q ) { this->M_Lqm_pr[q][0].conservativeResize( this->M_N ); for ( size_type l = 1; l <= number_of_added_elements; ++l ) { int index = this->M_N-l; this->M_Lqm_pr[q][0]( index ) = this->M_model->Fqm( this->M_output_index, q, 0, this->M_model->rBFunctionSpace()->primalBasisElement(index) ); } }//loop over q sparse_matrix_ptrtype trilinear_form; for (size_type q = 0; q < this->M_model->QaTri(); ++q ) { M_Aqm_tril_pr[q].resize( this->M_N ); for (int k=0 ; k<this->M_N; k++) { //bring back the matrix associated to the trilinear form for a given basis function //we do this here to use only one matrix trilinear_form = this->M_model->computeTrilinearForm( this->M_model->rBFunctionSpace()->primalBasisElement(k) ); M_Aqm_tril_pr[q][k].conservativeResize( this->M_N, this->M_N ); for ( int i = 0; i < this->M_N; ++i ) { for ( int j = 0; j < this->M_N; ++j ) { M_Aqm_tril_pr[q][k]( i, j ) = trilinear_form->energy( this->M_model->rBFunctionSpace()->primalBasisElement(j), this->M_model->rBFunctionSpace()->primalBasisElement(i) ); }//j }//i }//k }// q timer2.restart(); if ( ! use_predefined_WNmu ) { bool already_exist; do { //initialization already_exist=false; //pick randomly an element mu = this->M_Dmu->element(); //make sure that the new mu is not already is M_WNmu BOOST_FOREACH( auto _mu, *this->M_WNmu ) { if( mu == _mu ) already_exist=true; } } while( already_exist ); this->M_current_mu = mu; } else { //remmber that in this case M_iter_max = sampling size if( this->M_N < this->M_iter_max )
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 ); }