示例#1
0
//=============================================================================
int Amesos_Umfpack::PerformNumericFactorization( ) 
{
  // MS // no overhead time in this method
  ResetTimer(0);

  RcondValidOnAllProcs_ = false ; 
  if (MyPID_ == 0) {
    std::vector<double> Control(UMFPACK_CONTROL);
    std::vector<double> Info(UMFPACK_INFO);
    umfpack_di_defaults( &Control[0] ) ; 
    if (Numeric) umfpack_di_free_numeric (&Numeric) ;
    int status = umfpack_di_numeric (&Ap[0], 
				     &Ai[0], 
				     &Aval[0], 
				     Symbolic, 
				     &Numeric, 
				     &Control[0], 
				     &Info[0]) ;
    Rcond_ = Info[UMFPACK_RCOND]; 

#if NOT_DEF
    std::cout << " Rcond_ = " << Rcond_ << std::endl ; 

    int lnz1 = 1000 ;
    int unz1 = 1000 ;
    int n = 4;
    int * Lp = (int *) malloc ((n+1) * sizeof (int)) ;
    int * Lj = (int *) malloc (lnz1 * sizeof (int)) ;
    double * Lx = (double *) malloc (lnz1 * sizeof (double)) ;
    int * Up = (int *) malloc ((n+1) * sizeof (int)) ;
    int * Ui = (int *) malloc (unz1 * sizeof (int)) ;
    double * Ux = (double *) malloc (unz1 * sizeof (double)) ;
    int * P = (int *) malloc (n * sizeof (int)) ;
    int * Q = (int *) malloc (n * sizeof (int)) ;
    double * Dx = (double *) NULL ;	/* D vector not requested */
    double * Rs  = (double *) malloc (n * sizeof (double)) ;
    if (!Lp || !Lj || !Lx || !Up || !Ui || !Ux || !P || !Q || !Rs)
    {
      assert( false ) ; 
    }
    int do_recip;
    status = umfpack_di_get_numeric (Lp, Lj, Lx, Up, Ui, Ux,
	P, Q, Dx, &do_recip, Rs, Numeric) ;
    if (status < 0)
    {
      assert( false ) ; 
    }

    printf ("\nL (lower triangular factor of C): ") ;
    (void) umfpack_di_report_matrix (n, n, Lp, Lj, Lx, 0, &Control[0]) ;
    printf ("\nU (upper triangular factor of C): ") ;
    (void) umfpack_di_report_matrix (n, n, Up, Ui, Ux, 1, &Control[0]) ;
    printf ("\nP: ") ;
    (void) umfpack_di_report_perm (n, P, &Control[0]) ;
    printf ("\nQ: ") ;
    (void) umfpack_di_report_perm (n, Q, &Control[0]) ;
    printf ("\nScale factors: row i of A is to be ") ;

#endif

    assert( status == 0 ) ; 
  }
  
  NumFactTime_ = AddTime("Total numeric factorization time", NumFactTime_, 0);

  return 0;
}
示例#2
0
/*! \fn solve a singular linear system with UmfPack methods
 *
 *  \param  [in/out]  [systemData]
 *
 *
 *  solve even singular system
 *  (note that due to initialization A is given in its transposed form A^T)
 *
 *  A * x = b
 *  <=> P * R * A * Q * Q * x = P * R * b       |   P * R * A * Q = L * U
 *  <=> L * U * Q * x = P * R * b
 *
 *  note that P and Q are orthogonal permutation matrices, so P^(-1) = P^T and Q^(-1) = Q^T
 *
 *   (1) L * y = P * R * b  <=>  P^T * L * y = R * b     (L is always regular so this can be solved by umfpack)
 *
 *   (2) U * z = y      (U is singular, this cannot be solved by umfpack)
 *
 *   (3) Q * x = z  <=>  x = Q^T * z
 *
 *
 * author: kbalzereit, wbraun
 */
int solveSingularSystem(LINEAR_SYSTEM_DATA* systemData)
{

    DATA_UMFPACK* solverData = (DATA_UMFPACK*) systemData->solverData;
    double *Ux, *Rs, r_ii, *b, sum, *y, *z;
    int *Up, *Ui, *Q, do_recip, rank = 0, current_rank, current_unz, i, j, k, l,
                                success = 0, status, stop = 0;

    int unz = solverData->info[UMFPACK_UNZ];

    Up = (int*) malloc((solverData->n_row + 1) * sizeof(int));
    Ui = (int*) malloc(unz * sizeof(int));
    Ux = (double*) malloc(unz * sizeof(double));

    Q = (int*) malloc(solverData->n_col * sizeof(int));
    Rs = (double*) malloc(solverData->n_row * sizeof(double));

    b = (double*) malloc(solverData->n_col * sizeof(double));
    y = (double*) malloc(solverData->n_col * sizeof(double));
    z = (double*) malloc(solverData->n_col * sizeof(double));

    infoStreamPrint(LOG_LS_V, 0, "Solve singular system");

    status = umfpack_di_get_numeric((int*) NULL, (int*) NULL, (double*) NULL, Up,
                                    Ui, Ux, (int*) NULL, Q, (double*) NULL, &do_recip, Rs,
                                    solverData->numeric);

    switch (status)
    {
    case UMFPACK_WARNING_singular_matrix:
    case UMFPACK_ERROR_out_of_memory:
    case UMFPACK_ERROR_argument_missing:
    case UMFPACK_ERROR_invalid_system:
    case UMFPACK_ERROR_invalid_Numeric_object:
        infoStreamPrint(LOG_LS_V, 0, "error: %d", status);
    }

    /* calculate R*b */
    if (do_recip == 0)
    {
        for (i = 0; i < solverData->n_row; i++)
        {
            b[i] = systemData->b[i] / Rs[i];
        }
    }
    else
    {
        for (i = 0; i < solverData->n_row; i++)
        {
            b[i] = systemData->b[i] * Rs[i];
        }
    }

    /* solve L * y = P * R * b  <=>  P^T * L * y = R * b */
    status = umfpack_di_solve(UMFPACK_Pt_L, solverData->Ap, solverData->Ai,
                              solverData->Ax, y, b, solverData->numeric, solverData->control,
                              solverData->info);

    switch (status)
    {
    case UMFPACK_WARNING_singular_matrix:
    case UMFPACK_ERROR_out_of_memory:
    case UMFPACK_ERROR_argument_missing:
    case UMFPACK_ERROR_invalid_system:
    case UMFPACK_ERROR_invalid_Numeric_object:
        infoStreamPrint(LOG_LS_V, 0, "error: %d", status);
    }

    /* rank is at most as high as the maximum in Ui */
    for (i = 0; i < unz; i++)
    {
        if (rank < Ui[i])
            rank = Ui[i];
    }

    /* if rank is already smaller than n set last component of result zero */
    for (i = rank + 1; i < solverData->n_col; i++)
    {
        if (y[i] < 1e-12)
        {
            z[i] = 0.0;
        }
        else
        {
            infoStreamPrint(LOG_LS_V, 0, "error: system is not solvable*");
            /* free all used memory */
            free(Up);
            free(Ui);
            free(Ux);

            free(Q);
            free(Rs);

            free(b);
            free(y);
            free(z);
            return -1;
        }
    }

    current_rank = rank;
    current_unz = unz;

    while ((stop == 0) && (current_rank > 1))
    {
        /* check if last two rows of U are the same */
        if ((Ux[current_unz] == Ux[current_unz - 1])
                && (Ui[current_unz] == Ui[current_unz - 1])
                && (Up[current_rank] - Up[current_rank - 1] > 1))
        {
            /* if diagonal entry on second to last row is nonzero, remaining matrix is regular */
            if (Ui[Up[current_rank] - 1] == current_rank - 1)
            {
                stop = 1;
            }
            /* last two rows are the same -> under-determined system, calculate one value and set the other one zero */
            else
            {
                z[current_rank] = y[current_rank] / Ux[current_unz];

                /* reduce system */
                for (i = Up[current_rank]; i < current_unz; i++)
                {
                    y[Ui[i]] -= z[current_rank] * Ux[i];
                }

                current_unz = Up[current_rank] - 1;
                current_rank--;

                /* now last row has only zero entries */
                if (y[current_rank] < 1e-12)
                {
                    z[current_rank] = 0.0;
                }
                else
                {
                    infoStreamPrint(LOG_LS_V, 0, "error: system is not solvable");
                    /* free all used memory */
                    free(Up);
                    free(Ui);
                    free(Ux);

                    free(Q);
                    free(Rs);

                    free(b);
                    free(y);
                    free(z);
                    return -1;
                }

                current_rank--;
            }
        }
        else
        {
            stop = 1;
        }
    }

    /* remaining system is regular so solve system by back substitution */
    z[current_rank] = Ux[current_unz] * y[current_rank];

    for (i = current_rank - 1; i >= 0; i--)
    {
        /* get diagonal element r_ii, j shows where the element is in vector Ux, Ui */
        j = Up[i];
        while (Ui[j] != i)
        {
            j++;
        }
        r_ii = Ux[j];
        sum = 0.0;
        for (k = i + 1; k < current_rank; k++)
        {
            for (l = Up[k]; l < Up[k + 1]; l++)
            {
                if (Ui[l] == Ui[i])
                {
                    sum += Ux[i] * z[k];
                }
            }
        }
        z[i] = (y[i] - sum) / r_ii;
    }

    /* x = Q^T * z */
    for (i = 0; i < solverData->n_col; i++)
    {
        systemData->x[Q[i]] = z[i];
    }

    /* free all used memory */
    free(Up);
    free(Ui);
    free(Ux);

    free(Q);
    free(Rs);

    free(b);
    free(y);
    free(z);

    return success;
}
示例#3
0
int sci_umf_luget(char* fname, void* pvApiCtx)
{
    /*
    *  LU_ptr is (a pointer to) a factorization of A, we have:
    *             -1
    *          P R  A Q = L U
    *
    *      A is n_row x n_col
    *      L is n_row x n
    *      U is n     x n_col     n = min(n_row, n_col)
    */

    SciErr sciErr;
    void* Numeric = NULL;
    int lnz = 0, unz = 0, n_row = 0, n_col = 0, n = 0, nz_udiag = 0, i = 0, stat = 0, do_recip = 0, it_flag = 0;
    int *L_mnel = NULL, *L_icol = NULL, *L_ptrow = NULL, *U_mnel = NULL, *U_icol = NULL, *U_ptrow = NULL, *V_irow = NULL, *V_ptcol = NULL;
    double *L_R = NULL, *L_I = NULL, *U_R = NULL, *U_I = NULL, *V_R = NULL, *V_I = NULL, *Rs = NULL;
    int *p = NULL, *q = NULL, pl_miss = 0, error_flag = 0 ;

    int* piAddr1 = NULL;
    int iType1   = 0;

    /* Check numbers of input/output arguments */
    CheckInputArgument(pvApiCtx, 1, 1);
    CheckOutputArgument(pvApiCtx, 1, 5);

    /* get the pointer to the LU factors */
    sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddr1);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    /* Check if the first argument is a pointer */
    sciErr = getVarType(pvApiCtx, piAddr1, &iType1);
    if (sciErr.iErr || iType1 != sci_pointer)
    {
        printError(&sciErr, 0);
        Scierror(999, _("%s: Wrong type for input argument #%d: A pointer expected.\n"), fname, 1);
        return 1;
    }

    sciErr = getPointer(pvApiCtx, piAddr1, &Numeric);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        return 1;
    }

    /* Check if the pointer is a valid ref to ... */
    if ( IsAdrInList(Numeric, ListNumeric, &it_flag) )
    {
        if (it_flag == 0 )
        {
            umfpack_di_get_lunz(&lnz, &unz, &n_row, &n_col, &nz_udiag, Numeric);
        }
        else
        {
            umfpack_zi_get_lunz(&lnz, &unz, &n_row, &n_col, &nz_udiag, Numeric);
        }
    }
    else
    {
        Scierror(999, _("%s: Wrong value for input argument #%d: Must be a valid reference to (umf) LU factors.\n"), fname, 1);
        return 1;
    }

    if (n_row <= n_col)
    {
        n = n_row;
    }
    else
    {
        n = n_col;
    }
    L_mnel  = (int*)MALLOC(n_row * sizeof(int));
    L_icol  = (int*)MALLOC(lnz * sizeof(int));
    L_ptrow = (int*)MALLOC((n_row + 1) * sizeof(int));
    L_R     = (double*)MALLOC( lnz * sizeof(double));
    U_mnel  = (int*)MALLOC(n * sizeof(int));
    U_icol  = (int*)MALLOC(unz * sizeof(int));
    U_ptrow = (int*)MALLOC((n + 1) * sizeof(int));
    U_R     = (double*)MALLOC( unz * sizeof(double));
    V_irow  = (int*)MALLOC(unz * sizeof(int));
    V_ptcol = (int*)MALLOC((n_col + 1) * sizeof(int));
    V_R     = (double*)MALLOC( unz * sizeof(double));
    p       = (int*)MALLOC(n_row * sizeof(int));
    q       = (int*)MALLOC(n_col * sizeof(int));
    Rs      = (double*)MALLOC(n_row * sizeof(double));

    if ( it_flag == 1 )
    {
        L_I = (double*)MALLOC(lnz * sizeof(double));
        U_I = (double*)MALLOC(unz * sizeof(double));
        V_I = (double*)MALLOC(unz * sizeof(double));
    }
    else
    {
        L_I = U_I = V_I = NULL;
    }

    if (    !(L_mnel && L_icol && L_R && L_ptrow  && p &&
              U_mnel && U_icol && U_R && U_ptrow  && q &&
              V_irow && V_R && V_ptcol  && Rs)
            || (it_flag && !(L_I && U_I && V_I))   )
    {
        error_flag = 1;
        goto the_end;
    }

    if ( it_flag == 0 )
    {
        stat = umfpack_di_get_numeric(L_ptrow, L_icol, L_R, V_ptcol, V_irow, V_R,
                                      p, q, (double *)NULL, &do_recip, Rs, Numeric);
    }
    else
    {
        stat = umfpack_zi_get_numeric(L_ptrow, L_icol, L_R, L_I, V_ptcol, V_irow, V_R, V_I,
                                      p, q, (double *)NULL, (double *)NULL, &do_recip, Rs, Numeric);
    }

    if ( stat != UMFPACK_OK )
    {
        error_flag = 2;
        goto the_end;
    };

    if ( do_recip )
    {
        for ( i = 0 ; i < n_row ; i++ )
        {
            Rs[i] = 1.0 / Rs[i];
        }
    }

    if ( it_flag == 0 )
    {
        stat = umfpack_di_transpose(n, n_col, V_ptcol, V_irow, V_R, (int *) NULL,
                                    (int*) NULL, U_ptrow, U_icol, U_R);
    }
    else
    {
        stat = umfpack_zi_transpose(n, n_col, V_ptcol, V_irow, V_R, V_I, (int *) NULL,
                                    (int*) NULL, U_ptrow, U_icol, U_R, U_I, 0);
    }

    if ( stat != UMFPACK_OK )
    {
        error_flag = 2;
        goto the_end;
    };

    for ( i = 0 ; i < n_row ; i++ )
    {
        L_mnel[i] = L_ptrow[i + 1] - L_ptrow[i];
    }
    for ( i = 0 ; i < n ; i++ )
    {
        U_mnel[i] = U_ptrow[i + 1] - U_ptrow[i];
    }

    for ( i = 0 ; i < lnz ; i++ )
    {
        L_icol[i]++;
    }
    for ( i = 0 ; i < unz ; i++ )
    {
        U_icol[i]++;
    }

    for ( i = 0 ; i < n_row ; i++ )
    {
        p[i]++;
    }
    for ( i = 0 ; i < n_col ; i++ )
    {
        q[i]++;
    }

    /* output L */
    if (it_flag) // complex
    {
        sciErr = createComplexSparseMatrix(pvApiCtx, 2, n_row, n, lnz, L_mnel, L_icol, L_R, L_I);
    }
    else
    {
        sciErr = createSparseMatrix(pvApiCtx, 2, n_row, n, lnz, L_mnel, L_icol, L_R);
    }

    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        FREE(L_mnel);
        FREE(U_mnel);
        return 1;
    }

    /* output U */
    if (it_flag) // complex
    {
        sciErr = createComplexSparseMatrix(pvApiCtx, 3, n, n_col, unz, U_mnel, U_icol, U_R, U_I);
    }
    else
    {
        sciErr = createSparseMatrix(pvApiCtx, 3, n, n_col, unz, U_mnel, U_icol, U_R);
    }

    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        FREE(L_mnel);
        FREE(U_mnel);
        return 1;
    }

    /* output p */
    sciErr = createMatrixOfDoubleAsInteger(pvApiCtx, 4, n_row, 1, p);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        FREE(L_mnel);
        FREE(U_mnel);
        return 1;
    }

    /* output q */
    sciErr = createMatrixOfDoubleAsInteger(pvApiCtx, 5, n_col, 1, q);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        FREE(L_mnel);
        FREE(U_mnel);
        return 1;
    }

    /* output res */
    sciErr = createMatrixOfDouble(pvApiCtx, 6, n_row, 1, Rs);
    if (sciErr.iErr)
    {
        printError(&sciErr, 0);
        FREE(L_mnel);
        FREE(U_mnel);
        return 1;
    }

the_end:
    FREE(L_mnel);
    FREE(L_icol);
    FREE(L_R);
    FREE(L_ptrow);
    FREE(p);
    FREE(U_mnel);
    FREE(U_icol);
    FREE(U_R);
    FREE(U_ptrow);
    FREE(q);
    FREE(V_irow);
    FREE(V_R);
    FREE(V_ptcol);
    FREE(Rs);

    if ( it_flag == 1 )
    {
        FREE(L_I);
        FREE(V_I);
        FREE(U_I);
    }

    switch (error_flag)
    {
        case 0:   /* no error */
            AssignOutputVariable(pvApiCtx, 1) = 2;
            AssignOutputVariable(pvApiCtx, 2) = 3;
            AssignOutputVariable(pvApiCtx, 3) = 4;
            AssignOutputVariable(pvApiCtx, 4) = 5;
            AssignOutputVariable(pvApiCtx, 5) = 6;
            ReturnArguments(pvApiCtx);
            return 0;

        case 1:   /* enough memory (with malloc) */
            Scierror(999, _("%s: No more memory.\n"), fname);
            break;

        case 2:   /* a problem with one umfpack routine */
            Scierror(999, "%s: %s\n", fname, UmfErrorMes(stat));
            break;
    }

    return 1;
}