int bsp_om_save_file(char *filename, void * address, u32 length, u32 mode)
{
    int ret = BSP_OK;
    int fd;
    int bytes;
    mm_segment_t old_fs;
    umode_t flag;

    old_fs = get_fs();
    set_fs(KERNEL_DS);

    if(DUMP_SAVE_FILE_MODE_CREATE == mode)
    {
        flag = O_CREAT|O_WRONLY|O_TRUNC;
    }
    else
    {
        flag = O_CREAT|O_RDWR|O_APPEND;
    }
    fd = sys_open(filename, flag, 0755);
    if(fd < 0)
    {
        om_error("<bsp_om_save_file>, open failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    bytes = sys_write(fd, address, length);
    if(bytes != length)
    {
        om_error("<bsp_om_save_file>, write data failed! ret = %d\n", bytes);
        ret = BSP_ERROR;
        (void)sys_close(fd);
        goto out;
    }

    ret = sys_close(fd);
    if(0 != ret)
    {
        om_error("<bsp_om_save_file>, close file failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    ret = BSP_OK;

out:
    set_fs(old_fs);
    return ret;
}
Esempio n. 2
0
    void Geometry::generate_indices(const bool OLD_ORDERING) {

        // Either unknowns (potentials and currents) are ordered by mesh (i.e. V_1, p_1, V_2, p_2,...) (this is the OLD_ORDERING)
        // or by type (V_1,V_2,V_3 .. p_1, p_2...) (by DEFAULT)
        // or by the user himself encoded into the vtp file.
        // if you use OLD_ORDERING make sure to iterate only once on each vertex: not to overwrite index (meshes have shared vertices).
        if (begin()->begin()->index()==unsigned(-1)) {
            unsigned index = 0;
            if (!OLD_ORDERING)
                for (Vertices::iterator pit=vertex_begin();pit != vertex_end();++pit)
                    (invalid_vertices_.empty()||invalid_vertices_.count(*pit)==0) ? pit->index()=index++ : unsigned(-1);

            for(iterator mit=begin();mit!=end();++mit){
                if(OLD_ORDERING){
                    om_error(is_nested_); // OR non nested but without shared vertices
                    for (Mesh::const_vertex_iterator vit=mit->vertex_begin();vit!=mit->vertex_end();++vit,++index)
                        (*vit)->index() = index;
                }
                if(!mit->isolated()&&!mit->current_barrier())
                    for ( Mesh::iterator tit = mit->begin(); tit != mit->end(); ++tit)
                        tit->index() = index++;
            }
            // even the last surface triangles (yes for EIT... )
            nb_current_barrier_triangles()=0;
            for (iterator mit=begin(); mit!=end();++mit)
                if(mit->current_barrier())
                    if(!mit->isolated()){
                        nb_current_barrier_triangles()+=mit->nb_triangles();
                        for (Mesh::iterator tit=mit->begin(); tit!=mit->end(); ++tit)
                            tit->index() = index++;
                    } else {
                        for(Mesh::iterator tit=mit->begin();tit!=mit->end();++tit)
                            tit->index()=unsigned(-1);
                    }

            size_ = index;
        }else{
            std::cout << "vertex_begin()->index() " << vertex_begin()->index() << std::endl;
            size_ = vertices_.size();
            for (iterator mit=begin();mit!=end();++mit)
                size_ += mit->size();
        }
    }
Esempio n. 3
0
    void assemble_cortical2(const Geometry& geo, Matrix& mat, const Head2EEGMat& M, const std::string& domain_name, const unsigned gauss_order, double gamma, const std::string &filename)
    {
        // Re-writting of the optimization problem in M. Clerc, J. Kybic "Cortical mapping by Laplace–Cauchy transmission using a boundary element method".
        // with a Lagrangian formulation as in see http://www.math.uh.edu/~rohop/fall_06/Chapter3.pdf eq3.3
        // find argmin(norm(gradient(X)) under constraints: 
        // H * X = 0 and M * X = m
        // let G be the gradient norm matrix, l1, l2 the lagrange parameters
        // 
        // [ G  H' M'] [   X    ]   [ 0 ]
        // | H  0    | |   l1   | = | 0 |
        // [ M     0 ] [   l2   ]   [ m ]
        //
        // {----,----}
        //      K
        // we want a submat of the inverse of K (using blockwise inversion, (TODO maybe iterative solution better ?)).
        // Assumptions:
        // - domain_name: the domain containing the sources is an innermost domain (defined as the interior of only one interface (called Cortex)
        // - Cortex interface is composed of one mesh only (no shared vertices)

        const Domain& SourceDomain = geo.domain(domain_name);
        const Interface& Cortex    = SourceDomain.begin()->interface();
        const Mesh& cortex         = Cortex.begin()->mesh();
        
        om_error(SourceDomain.size()==1);
        om_error(Cortex.size()==1);

        // shape of the new matrix:
        unsigned Nl = geo.size()-geo.nb_current_barrier_triangles()-Cortex.nb_vertices()-Cortex.nb_triangles();
        unsigned Nc = geo.size()-geo.nb_current_barrier_triangles();
        std::fstream f(filename.c_str());
        Matrix H;
        if ( !f ) {
            // build the HeadMat:
            // The following is the same as assemble_HM except N_11, D_11 and S_11 are not computed.
            SymMatrix mat_temp(Nc);
            mat_temp.set(0.0);
            double K = 1.0 / (4.0 * M_PI);
            // We iterate over the meshes (or pair of domains) to fill the lower half of the HeadMat (since its symmetry)
            for ( Geometry::const_iterator mit1 = geo.begin(); mit1 != geo.end(); ++mit1) {
                for ( Geometry::const_iterator mit2 = geo.begin(); (mit2 != (mit1+1)); ++mit2) {
                    // if mit1 and mit2 communicate, i.e they are used for the definition of a common domain
                    const int orientation = geo.oriented(*mit1, *mit2); // equals  0, if they don't have any domains in common
                    // equals  1, if they are both oriented toward the same domain
                    // equals -1, if they are not
                    if ( orientation != 0) {
                        double Scoeff =   orientation * geo.sigma_inv(*mit1, *mit2) * K;
                        double Dcoeff = - orientation * geo.indicator(*mit1, *mit2) * K;
                        double Ncoeff;
                        if ( !(mit1->current_barrier() || mit2->current_barrier()) && ( (*mit1 != *mit2)||( *mit1 != cortex) ) ) {
                            // Computing S block first because it's needed for the corresponding N block
                            operatorS(*mit1, *mit2, mat_temp, Scoeff, gauss_order);
                            Ncoeff = geo.sigma(*mit1, *mit2)/geo.sigma_inv(*mit1, *mit2);
                        } else {
                            Ncoeff = orientation * geo.sigma(*mit1, *mit2) * K;
                        }
                        if ( !mit1->current_barrier() && (( (*mit1 != *mit2)||( *mit1 != cortex) )) ) {
                            // Computing D block
                            operatorD(*mit1, *mit2, mat_temp, Dcoeff, gauss_order);
                        }
                        if ( ( *mit1 != *mit2 ) && ( !mit2->current_barrier() ) ) {
                            // Computing D* block
                            operatorD(*mit1, *mit2, mat_temp, Dcoeff, gauss_order, true);
                        }
                        // Computing N block
                        if ( (*mit1 != *mit2)||( *mit1 != cortex) ) {
                            operatorN(*mit1, *mit2, mat_temp, Ncoeff, gauss_order);
                        }
                    }
                }
            }
            // Deflate all current barriers as one
            deflat(mat_temp,geo);

            H = Matrix(Nl + M.nlin(), Nc);
            H.set(0.0);
            // copy mat_temp into H except the lines for cortex vertices [i_vb_c, i_ve_c] and cortex triangles [i_tb_c, i_te_c].
            unsigned iNl = 0;
            for ( Geometry::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
                if ( *mit != cortex ) {
                    for ( Mesh::const_vertex_iterator vit = mit->vertex_begin(); vit != mit->vertex_end(); ++vit) {
                        H.setlin(iNl, mat_temp.getlin((*vit)->index()));
                        ++iNl;
                    }
                    if ( !mit->current_barrier() ) {
                        for ( Mesh::const_iterator tit = mit->begin(); tit != mit->end(); ++tit) {
                            H.setlin(iNl, mat_temp.getlin(tit->index()));
                            ++iNl;
                        }
                    }
                }
            }
            if ( filename.length() != 0 ) {
                std::cout << "Saving matrix H (" << filename << ")." << std::endl;
                H.save(filename);
            }
        } else {
            std::cout << "Loading matrix H (" << filename << ")." << std::endl;
            H.load(filename);
        }

        // concat M to H
        for ( unsigned i = Nl; i < Nl + M.nlin(); ++i) {
            for ( unsigned j = 0; j < Nc; ++j) {
                H(i, j) = M(i-Nl, j);
            }
        }

        // ** Get the gradient of P1&P0 elements on the meshes **
        SymMatrix G(Nc);
        G.set(0.);
        for ( Geometry::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
            mit->gradient_norm2(G);
        }
        // multiply by gamma the submat of current gradient norm2
        for ( Meshes::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
            if ( !mit->current_barrier() ) {
                for ( Mesh::const_iterator tit1 = mit->begin(); tit1 != mit->end(); ++tit1) {
                    for ( Mesh::const_iterator tit2 = mit->begin(); tit2 != mit->end(); ++tit2) {
                        G(tit1->index(), tit2->index()) *= gamma;
                    }
                }
            }
        }
        std::cout << "gamma = " << gamma << std::endl;
        
        G.invert();
        mat = (G * H.transpose() * (H * G * H.transpose()).inverse()).submat(0, Nc, Nl, M.nlin());
    }
Esempio n. 4
0
    void assemble_cortical(const Geometry& geo, Matrix& mat, const Head2EEGMat& M, const std::string& domain_name, const unsigned gauss_order, double alpha, double beta, const std::string &filename)
    {
        // Following the article: M. Clerc, J. Kybic "Cortical mapping by Laplace–Cauchy transmission using a boundary element method".
        // Assumptions:
        // - domain_name: the domain containing the sources is an innermost domain (defined as the interior of only one interface (called Cortex))
        // - Cortex interface is composed of one mesh only (no shared vertices)

        const Domain& SourceDomain  = geo.domain(domain_name);
        const Interface& Cortex     = SourceDomain.begin()->interface();
        const Mesh& cortex          = Cortex.begin()->mesh();
        
        om_error(SourceDomain.size()==1);
        om_error(Cortex.size()==1);

        // shape of the new matrix:
        unsigned Nl = geo.size()-geo.nb_current_barrier_triangles()-Cortex.nb_vertices()-Cortex.nb_triangles();
        unsigned Nc = geo.size()-geo.nb_current_barrier_triangles();
        std::fstream f(filename.c_str());
        Matrix P;
        if ( !f ) {
            // build the HeadMat:
            // The following is the same as assemble_HM except N_11, D_11 and S_11 are not computed.
            SymMatrix mat_temp(Nc);
            mat_temp.set(0.0);
            double K = 1.0 / (4.0 * M_PI);
            // We iterate over the meshes (or pair of domains) to fill the lower half of the HeadMat (since its symmetry)
            for ( Geometry::const_iterator mit1 = geo.begin(); mit1 != geo.end(); ++mit1) {
                for ( Geometry::const_iterator mit2 = geo.begin(); (mit2 != (mit1+1)); ++mit2) {
                    // if mit1 and mit2 communicate, i.e they are used for the definition of a common domain
                    const int orientation = geo.oriented(*mit1, *mit2); // equals  0, if they don't have any domains in common
                    // equals  1, if they are both oriented toward the same domain
                    // equals -1, if they are not
                    if ( orientation != 0) {
                        double Scoeff =   orientation * geo.sigma_inv(*mit1, *mit2) * K;
                        double Dcoeff = - orientation * geo.indicator(*mit1, *mit2) * K;
                        double Ncoeff;
                        if ( !(mit1->current_barrier() || mit2->current_barrier()) && ( (*mit1 != *mit2)||( *mit1 != cortex) ) ) {
                            // Computing S block first because it's needed for the corresponding N block
                            operatorS(*mit1, *mit2, mat_temp, Scoeff, gauss_order);
                            Ncoeff = geo.sigma(*mit1, *mit2)/geo.sigma_inv(*mit1, *mit2);
                        } else {
                            Ncoeff = orientation * geo.sigma(*mit1, *mit2) * K;
                        }
                        if ( !mit1->current_barrier() && (( (*mit1 != *mit2)||( *mit1 != cortex) )) ) {
                            // Computing D block
                            operatorD(*mit1, *mit2, mat_temp, Dcoeff, gauss_order,false);
                        }
                        if ( ( *mit1 != *mit2 ) && ( !mit2->current_barrier() ) ) {
                            // Computing D* block
                            operatorD(*mit1, *mit2, mat_temp, Dcoeff, gauss_order, true);
                        }
                        // Computing N block
                        if ( (*mit1 != *mit2)||( *mit1 != cortex) ) {
                            operatorN(*mit1, *mit2, mat_temp, Ncoeff, gauss_order);
                        }
                    }
                }
            }
            // Deflate all current barriers as one
            deflat(mat_temp,geo);

            mat = Matrix(Nl, Nc);
            mat.set(0.0);
            // copy mat_temp into mat except the lines for cortex vertices [i_vb_c, i_ve_c] and cortex triangles [i_tb_c, i_te_c].
            unsigned iNl = 0;
            for ( Geometry::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
                if ( *mit != cortex ) {
                    for ( Mesh::const_vertex_iterator vit = mit->vertex_begin(); vit != mit->vertex_end(); ++vit) {
                        mat.setlin(iNl, mat_temp.getlin((*vit)->index()));
                        ++iNl;
                    }
                    if ( !mit->current_barrier() ) {
                        for ( Mesh::const_iterator tit = mit->begin(); tit != mit->end(); ++tit) {
                            mat.setlin(iNl, mat_temp.getlin(tit->index()));
                            ++iNl;
                        }
                    }
                }
            }
            // ** Construct P: the null-space projector **
            Matrix W;
            {
                Matrix U, s;
                mat.svd(U, s, W);
            }

            SparseMatrix S(Nc,Nc);
            // we set S to 0 everywhere, except in the last part of the diag:
            for ( unsigned i = Nl; i < Nc; ++i) {
                S(i, i) = 1.0;
            }
            P = (W * S) * W.transpose(); // P is a projector: P^2 = P and mat*P*X = 0
            if ( filename.length() != 0 ) {
                std::cout << "Saving projector P (" << filename << ")." << std::endl;
                P.save(filename);
            }
        } else {
            std::cout << "Loading projector P (" << filename << ")." << std::endl;
            P.load(filename);
        }

        // ** Get the gradient of P1&P0 elements on the meshes **
        Matrix MM(M.transpose() * M);
        SymMatrix RR(Nc, Nc); RR.set(0.);
        for ( Geometry::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
            mit->gradient_norm2(RR);
        }

        // ** Choose Regularization parameter **
        SparseMatrix alphas(Nc,Nc); // diagonal matrix
        Matrix Z;
        if ( alpha < 0 ) { // try an automatic method... TODO find better estimation
            double nRR_v = RR.submat(0, geo.nb_vertices(), 0, geo.nb_vertices()).frobenius_norm();
            alphas.set(0.);
            alpha = MM.frobenius_norm() / (1.e3*nRR_v);
            beta  = alpha * 50000.;
            for ( Vertices::const_iterator vit = geo.vertex_begin(); vit != geo.vertex_end(); ++vit) {
                alphas(vit->index(), vit->index()) = alpha;
            }
            for ( Meshes::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
                if ( !mit->current_barrier() ) {
                    for ( Mesh::const_iterator tit = mit->begin(); tit != mit->end(); ++tit) {
                        alphas(tit->index(), tit->index()) = beta;
                    }
                }
            }
            std::cout << "AUTOMATIC alphas = " << alpha << "\tbeta = " << beta << std::endl;
        } else {
            for ( Vertices::const_iterator vit = geo.vertex_begin(); vit != geo.vertex_end(); ++vit) {
                alphas(vit->index(), vit->index()) = alpha;
            }
            for ( Meshes::const_iterator mit = geo.begin(); mit != geo.end(); ++mit) {
                if ( !mit->current_barrier() ) {
                    for ( Mesh::const_iterator tit = mit->begin(); tit != mit->end(); ++tit) {
                        alphas(tit->index(), tit->index()) = beta;
                    }
                }
            }
            std::cout << "alphas = " << alpha << "\tbeta = " << beta << std::endl;
        }
        Z = P.transpose() * (MM + alphas*RR) * P;

        // ** PseudoInverse and return **
        // X = P * { (M*P)' * (M*P) + (R*P)' * (R*P) }¡(-1) * (M*P)'m
        // X = P * { P'*M'*M*P + P'*R'*R*P }¡(-1) * P'*M'm
        // X = P * { P'*(MM + a*RR)*P }¡(-1) * P'*M'm
        // X = P * Z¡(-1) * P' * M'm
        Matrix rhs = P.transpose() * M.transpose();
        mat = P * Z.pinverse() * rhs;
    }
int om_clear_old_file(int fd, char * header)
{
    int ret = BSP_OK;
    int i;
    int index;
    int head_len;
    int read_bytes;
    char *buf = BSP_NULL;
    struct linux_dirent *dir;
    char filename[OM_DUMP_FILE_MAX_NUM][OM_DUMP_FILE_NAME_LENGTH] = {{0},{0}};
    char temp[OM_DUMP_FILE_NAME_LENGTH];

    buf = kmalloc(1024, GFP_KERNEL);
    if(BSP_NULL == buf)
    {
        bsp_trace(BSP_LOG_LEVEL_ERROR, BSP_MODU_OM, "om_clear_old_file: Alloc mem error!");
        return BSP_ERROR;
    }

    read_bytes = sys_getdents(fd, (struct linux_dirent *)buf, 1024);
    if(-1 == read_bytes)
    {
        /* 读取文件夹错误 */
        om_error("<om_clear_old_file>, dents error!\n");
        ret = BSP_ERROR;
        goto out;
    }

    if(0 == read_bytes)
    {
        /* 文件夹是空的,直接返回OK */
        ret = BSP_OK;
        goto out;
    }

    /*轮询文件夹*/
    head_len = strlen(header);
    for(i=0; i<read_bytes; )
    {
        dir = (struct linux_dirent *)(buf + i);
        i += (int)dir->d_reclen;

        /* 删除旧的和错误的文件 */
        if(0 == strncmp ((char *)dir->d_name, header, head_len))
        {
            strncpy(temp, OM_ROOT_PATH, OM_DUMP_FILE_NAME_LENGTH-1);
            strncat(temp, dir->d_name, OM_DUMP_FILE_NAME_LENGTH-strlen(OM_ROOT_PATH)-1);

            index = simple_strtol(dir->d_name + head_len, NULL, 0);
            // 如果索引号超过最大值,或者有重复,直接删除文件
            if((index >= OM_DUMP_FILE_MAX_NUM - 1) || (0 != filename[index][0]))
            {
                sys_unlink(temp);
            }
            else
            {
                strncpy(filename[index], temp, OM_DUMP_FILE_NAME_LENGTH -1);
            }
        }
    }

    /* 文件重命名 */
    for(i=OM_DUMP_FILE_MAX_NUM-2; i>=0; i--)
    {
        if(filename[i][0])
        {
            snprintf(temp, sizeof(temp), "%s%s%02d.bin", OM_ROOT_PATH, OM_DUMP_HEAD, i+1);
            /* coverity[check_return] */
            (void)sys_rename(filename[i], temp);
        }
    }

out:
    if(buf)
        kfree(buf);

    return ret;
}
int bsp_om_append_file(char *filename, void * address, u32 length, u32 max_size)
{
    int ret = BSP_OK;
    int fd;
    int bytes;
    int len;
    mm_segment_t old_fs;

    old_fs = get_fs();
    set_fs(KERNEL_DS);

    ret = om_create_dir(OM_ROOT_PATH);
    if(BSP_OK != ret)
    {
        om_error("<bsp_om_append_file>, create dir failed! ret = %d\n", ret);
        goto out;
    }

    /* open file */
    ret = sys_access(filename, 0);
    if(BSP_OK != ret)
    {
        /*create file */
        fd = sys_open(filename, O_CREAT|O_RDWR, 0755);
        if(fd < 0)
        {
            om_error("<bsp_om_append_file>, open failed while mode is create, ret = %d\n", fd);
            goto out;
        }
    }
    else
    {
        fd = sys_open(filename, O_APPEND|O_RDWR, 0755);
        if(fd < 0)
        {
            om_error("<bsp_om_append_file>, open failed while mode is append, ret = %d\n", fd);
            goto out;
        }
    }

    len = sys_lseek(fd, 0, SEEK_END);
    if(ERROR == len)
    {
        om_error("<bsp_om_append_file>, seek failed! ret = %d\n", len);
        (void)sys_close(fd);
        goto out;
    }

    if (len >= max_size)
    {
        sys_close(fd);
        ret = sys_unlink(filename);
        if (OK != ret)
        {
            om_error("<bsp_om_append_file>, remove failed! ret = %d\n", ret);
	        goto out;
        }

        /*重新建立reset文件*/
        fd = sys_open(filename, O_CREAT|O_RDWR, 0755);
        if(fd < 0)
        {
            om_error("<bsp_om_append_file>, create failed! ret = %d\n", fd);
            goto out;
        }
    }

    bytes = sys_write(fd, address, length);
    if(bytes != length)
    {
        om_error("<bsp_om_append_file>, write data failed! ret = %d\n", bytes);
        ret = BSP_ERROR;
        (void)sys_close(fd);
        goto out;
    }

    ret = sys_close(fd);
    if(0 != ret)
    {
        om_error("<bsp_om_append_file>, close failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    ret = BSP_OK;

out:
    set_fs(old_fs);
    return ret;
}
int bsp_om_save_loop_file(char * dirName, char *fileHeader, void * address, u32 length)
{
    int ret = BSP_OK;
    int fd;
    int bytes;
    mm_segment_t old_fs;
    char newFileName[OM_DUMP_FILE_NAME_LENGTH] = {0};

    /* 进入目录 */
    if (NULL == dirName || NULL == fileHeader)
    {
        om_error("<bsp_om_save_loop_file>, file name NULL!\n");
        return BSP_ERROR;
    }
    if ((strlen((const char*)dirName) + strlen((const char*)fileHeader)) >= OM_DUMP_FILE_NAME_LENGTH)
    {
        om_error("<bsp_om_save_loop_file>, file name too long!\n");
        return BSP_ERROR;
    }

    old_fs = get_fs();
    set_fs(KERNEL_DS);

    fd = om_open_dir(dirName);
    if(fd < 0)
    {
        om_error("<bsp_om_save_loop_file>, open om dir failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    ret = om_clear_old_file(fd, fileHeader);
    if(BSP_OK != ret)
    {
        om_error("<bsp_om_save_loop_file>, clear old file failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    om_close_dir(fd);

    //新文件名:0
    memset(newFileName, 0, sizeof(newFileName));
    snprintf(newFileName, sizeof(newFileName), "%s%s%02d.bin", dirName, fileHeader, 0);
    fd = sys_creat(newFileName, 0755);
    if(fd < 0)
    {
        om_error("<bsp_om_save_loop_file>, creat file failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    bytes = sys_write(fd, address, length);

    if(bytes != length)
    {
        om_error("<bsp_om_save_loop_file>, write data to file failed! ret = %d\n", bytes);
        ret = BSP_ERROR;
        (void)sys_close(fd);
        goto out;
    }

     ret = sys_close(fd);
    if(0 != ret)
    {
        om_error("<bsp_om_save_loop_file>, close file failed! ret = %d\n", ret);
        ret = BSP_ERROR;
        goto out;
    }

    ret = BSP_OK;

out:
    set_fs(old_fs);
    return ret;
}