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";
}
示例#2
0
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
            {
示例#3
0
 FsFunctionalLinear( space_ptrtype space ) :
     super_type( space ),
     M_backend( backend_type::build( soption( _name="backend" ) ) ), // BACKEND_PETSC is the default backend
     M_vector( M_backend->newVector( space ) ),
     M_name( "functionallinear" )
 {
 }
 /**
  * Constructor
  */
 TestInterpolationHCurl3D()
     :
     super(),
     M_backend( backend_type::build( soption( _name="backend" ) ) )
 {
     this->changeRepository( boost::format( "%1%/" )
                             % this->about().appName()
                           );
 }
示例#5
0
文件: ns.hpp 项目: LANTZT/feelpp
NavierStokes::NavierStokes()
    :
    super(),
    M_backend( backend_type::build( soption("backend") ) ),
    meshSize( this->vm()["hsize"].as<double>() ),
    mu( this->vm()["mu"].as<value_type>() ),
    penalbc( this->vm()["bccoeff"].as<value_type>() ),
    exporter( Exporter<mesh_type>::New( this->vm(), this->about().appName() ) )
{

}
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);
        }
    }
示例#7
0
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;
}
示例#8
0
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();
}
示例#9
0
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
示例#10
0
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 )
示例#11
0
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 );
}