📄 symbfwblk.c
字号:
snode, xsuper - supernodal partition.
xsuper(nsuper+1): xsuper(j):xsuper(j+1)-1 is jth supernode
snode(m): j=snode(i) means xsuper(j) <= i < xsuper(j+1).
xlindx,lindx - compressed subscript array.
xlindx(nsuper+1): lindx(xlindx(j):xlindx(j+1)-1) are the subscripts
for supernode j.
nsuper - number of supernodes
m,n - size(b), m rows, n columns.
OUTPUT
xjc - n+1-array: Start of each column in *pxir.
*pxir - length *pmaxnnz array of row-indices.
UPDATED
*pmaxnnz - The allocated number of entries in *pxir. Will be changed
by this function to the exact number needed (but s.t. maxnnz >= 1).
WORK
snodefrom - int(nsuper)
processed - char(nsuper)
************************************************************ */
void symbfwmat(int *xjc, int **pxir,int *pmaxnnz,
const int *bjc, const int *bir,
const int *invperm, const int *snode, const int *xsuper,
const int *xlindx, const int *lindx,
const int nsuper, const int m, const int n,
int *snodefrom, char *processed)
{
int i,j,k,inz, maxnnz;
int *xir;
/* ------------------------------------------------------------
INIT: processed = 0, xir = *pxir, maxnnz = *pmaxnnz.
------------------------------------------------------------ */
memset(processed, 0, nsuper * sizeof(char));
xir = *pxir;
maxnnz = *pmaxnnz;
/* ------------------------------------------------------------
For each column j, compute nz-structure of L\b(:,j) into xir.
First make sure that xir has enough (at least m) available entries.
------------------------------------------------------------ */
inz = 0;
for(j = 0; j < n; j++){
xjc[j] = inz;
if(inz + m > maxnnz){
maxnnz += inz + m; /* required + old amount */
xir = (int *) mxRealloc(xir, maxnnz*sizeof(int));
}
/* ------------------------------------------------------------
Find all nz-supernodes in L\b(:,j).
------------------------------------------------------------ */
getnzsuper(snodefrom, processed, bir + bjc[j], bjc[j+1]-bjc[j],
invperm, snode, xsuper, xlindx, lindx);
/* ------------------------------------------------------------
For each nz-supernode, write the row-indices from "snodefrom" into xir.
------------------------------------------------------------ */
for(k = 0; k < nsuper; k++)
if(processed[k]){
processed[k] = 0;
for(i = snodefrom[k]; i < xsuper[k+1]; i++)
xir[inz++] = i;
}
}
/* ------------------------------------------------------------
FINALLY: close last column in xir, Realloc xir to the actual
maxnnz:= xjc[n], and return.
------------------------------------------------------------ */
xjc[n] = inz;
if(inz < maxnnz){
maxnnz = MAX(inz,1); /* avoid realloc to NULL */
xir = (int *) mxRealloc(xir, maxnnz * sizeof(int));
}
*pxir = xir;
*pmaxnnz = maxnnz;
}
/* ============================================================
MAIN: MEXFUNCTION
============================================================ */
/* ************************************************************
PROCEDURE mexFunction - Entry for Matlab
************************************************************ */
void mexFunction(const int nlhs, mxArray *plhs[],
const int nrhs, const mxArray *prhs[])
{
const mxArray *L_FIELD;
int maxnnz, i,j, nsuper,m,n;
const int *ljc,*lir,*bjc,*bir;
int *xjc,*xir, *snode,*xlindx,*lindx, *iwork,*xsuper, *invperm;
char *cwork;
double *xpr;
const double *permPr, *xsuperPr;
/* ------------------------------------------------------------
Check for proper number of arguments
------------------------------------------------------------ */
mxAssert(nrhs >= NPARIN, "symbfwblk requires more input arguments");
mxAssert(nlhs <= NPAROUT, "symbfwblk produces 1 output argument");
/* ------------------------------------------------------------
Get rhs-input B
------------------------------------------------------------ */
mxAssert(mxIsSparse(B_IN), "B must be sparse");
m = mxGetM(B_IN);
n = mxGetN(B_IN);
bjc = mxGetJc(B_IN);
bir = mxGetIr(B_IN);
/* ------------------------------------------------------------
Disassemble block Cholesky structure L
------------------------------------------------------------ */
mxAssert(mxIsStruct(L_IN), "Parameter `L' should be a structure.");
L_FIELD = mxGetField(L_IN,0,"perm");
mxAssert( L_FIELD != NULL, "Missing field L.perm."); /* L.perm */
mxAssert(m == mxGetM(L_FIELD) * mxGetN(L_FIELD), "L.perm size mismatches B");
permPr = mxGetPr(L_FIELD);
L_FIELD = mxGetField(L_IN,0,"L");
mxAssert( L_FIELD!= NULL, "Missing field L.L."); /* L.L */
mxAssert( m == mxGetM(L_FIELD) && m == mxGetN(L_FIELD), "Size L.L mismatch.");
mxAssert(mxIsSparse(L_FIELD), "L.L should be sparse.");
ljc = mxGetJc(L_FIELD);
lir = mxGetIr(L_FIELD);
L_FIELD = mxGetField(L_IN,0,"xsuper");
mxAssert( L_FIELD!= NULL, "Missing field L.xsuper."); /* L.xsuper */
nsuper = mxGetM(L_FIELD) * mxGetN(L_FIELD) - 1;
mxAssert( nsuper <= m , "Size L.xsuper mismatch.");
xsuperPr = mxGetPr(L_FIELD);
/* ------------------------------------------------------------
Allocate int-part of sparse output matrix X(m x n)
Heuristically set nnz to nnz(B) + 4*m.
------------------------------------------------------------ */
maxnnz = bjc[n] + 4 * m;
xjc = (int *) mxCalloc(n + 1, sizeof(int));
xir = (int *) mxCalloc(maxnnz, sizeof(int));
/* ------------------------------------------------------------
Allocate working arrays:
int invperm(m), snode(m), xsuper(nsuper+1), xlindx(nsuper+1), lindx(nnz(L)),
iwork(nsuper).
char cwork(nsuper).
------------------------------------------------------------ */
invperm = (int *) mxCalloc(m,sizeof(int));
snode = (int *) mxCalloc(m,sizeof(int));
xsuper = (int *) mxCalloc(nsuper+1,sizeof(int));
xlindx = (int *) mxCalloc(nsuper+1,sizeof(int));
lindx = (int *) mxCalloc(ljc[m], sizeof(int));
iwork = (int *) mxCalloc(nsuper, sizeof(int));
cwork = (char *) mxCalloc(nsuper, sizeof(char));
/* ------------------------------------------------------------
Convert PERM, XSUPER to integer and C-Style
------------------------------------------------------------ */
for(i = 0; i < m; i++){
j = permPr[i];
invperm[--j] = i; /* so that invperm[perm[i]] = i */
}
for(i = 0; i <= nsuper; i++){
j = xsuperPr[i];
xsuper[i] = --j;
}
/* ------------------------------------------------------------
Create "snode" from xsuper, and get compact subscript (xlindx,lindx)
from (ljc,lir,xsuper), i.e. nz-pattern per supernode.
------------------------------------------------------------ */
snodeCompress(xlindx,lindx,snode, ljc,lir,xsuper,nsuper);
/* ------------------------------------------------------------
Compute nz structure after forward solve
------------------------------------------------------------ */
symbfwmat(xjc, &xir, &maxnnz, bjc, bir, invperm, snode, xsuper,
xlindx, lindx,
nsuper, m, n, iwork, cwork);
/* ------------------------------------------------------------
Create output matrix x
------------------------------------------------------------ */
X_OUT = mxCreateSparse(m,n, 1,mxREAL);
mxFree(mxGetJc(X_OUT)); /* jc */
mxFree(mxGetIr(X_OUT)); /* ir */
mxFree(mxGetPr(X_OUT)); /* pr */
xpr = (double *) mxCalloc(maxnnz,sizeof(double));
mxSetJc(X_OUT, xjc);
mxSetIr(X_OUT, xir);
mxSetPr(X_OUT, xpr);
mxSetNzmax(X_OUT, maxnnz);
for(i = 0; i < maxnnz; i++)
xpr[i] = 1.0;
/* ------------------------------------------------------------
Release working arrays.
------------------------------------------------------------ */
mxFree(cwork);
mxFree(iwork);
mxFree(lindx);
mxFree(xlindx);
mxFree(xsuper);
mxFree(snode);
mxFree(invperm);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -