/* util.c */
#include "../ETree.h"
#define MYDEBUG 0
/*--------------------------------------------------------------------*/
/*
----------------------------------------------
return the number of bytes taken by the object
created -- 95nov15, cca
----------------------------------------------
*/
int
ETree_sizeOf (
ETree *etree
) {
int nbytes ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_sizeOf(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
nbytes = sizeof(struct _ETree) ;
if ( etree->tree != NULL ) {
nbytes += Tree_sizeOf(etree->tree) ;
}
if ( etree->nodwghtsIV != NULL ) {
nbytes += IV_sizeOf(etree->nodwghtsIV) ;
}
if ( etree->nodwghtsIV != NULL ) {
nbytes += IV_sizeOf(etree->bndwghtsIV) ;
}
if ( etree->vtxToFrontIV != NULL ) {
nbytes += IV_sizeOf(etree->vtxToFrontIV) ;
}
return(nbytes) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
return the number of factor indices
created -- 95nov15, cca
modified -- 96jan11, cca
----------------------------------------
*/
int
ETree_nFactorIndices (
ETree *etree
) {
int nb, nfront, nv, nind, nvtx, v ;
int *bndwghts, *nodwghts ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nFactorIndices(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
nodwghts = IV_entries(etree->nodwghtsIV) ;
bndwghts = IV_entries(etree->bndwghtsIV) ;
nind = 0 ;
for ( v = 0 ; v < nfront ; v++ ) {
nv = nodwghts[v] ;
nb = bndwghts[v] ;
nind += nv + nb ;
}
return(nind) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return the number of factor entries
symflag -- symmetry flag
0 (SPOOLES_SYMMETRIC) -- symmetric
1 (SPOOLES_HERMITIAN) -- hermitian
2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
created -- 98jun05, cca
------------------------------------------
*/
int
ETree_nFactorEntries (
ETree *etree,
int symflag
) {
int J, nfront, nvtx, nzf ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nFactorEntries(%p,%d)"
"\n bad input\n", etree, symflag) ;
exit(-1) ;
}
nzf = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
nzf += ETree_nFactorEntriesInFront(etree, symflag, J) ;
}
return(nzf) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------------
return the number of factor operations
type -- type of matrix entries
1 (SPOOLES_REAL) -- real entries
2 (SPOOLES_COMPLEX) -- complex entries
symflag -- symmetry flag
0 (SPOOLES_SYMMETRIC) -- symmetric
1 (SPOOLES_HERMITIAN) -- hermitian
2 (SPOOLES_NONSYMMETRIC) -- nonsymmetric
created -- 98jun05, cca
------------------------------------------
*/
double
ETree_nFactorOps (
ETree *etree,
int type,
int symflag
) {
double ops ;
int J, nfront, nvtx ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| (nfront = etree->nfront) <= 0
|| (nvtx = etree->nvtx) <= 0 ) {
fprintf(stderr, "\n fatal error in ETree_nFactorOps(%p,%d,%d)"
"\n bad input\n", etree, type, symflag) ;
exit(-1) ;
}
ops = 0 ;
for ( J = 0 ; J < nfront ; J++ ) {
ops += ETree_nInternalOpsInFront(etree, type, symflag, J)
+ ETree_nExternalOpsInFront(etree, type, symflag, J) ;
}
return(ops) ; }
/*--------------------------------------------------------------------*/
/*
----------------------------------------
return the number of entries an LU front
created -- 96dec04, cca
----------------------------------------
*/
double
ETree_nFactorEntriesInFront (
ETree *etree,
int symflag,
int J
) {
int b, m, nent ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| J < 0 || J >= etree->nfront ) {
fprintf(stderr,
"\n fatal error in ETree_nFactorEntriesInFront(%p,%d,%d)"
"\n bad input\n", etree, symflag, J) ;
exit(-1) ;
}
b = IV_entry(etree->nodwghtsIV, J) ;
m = IV_entry(etree->bndwghtsIV, J) ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
nent = (b*(b+1))/2 + b*m ;
break ;
case SPOOLES_NONSYMMETRIC :
nent = b*b + 2*b*m ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nFactorEntriesInFront(%p,%d,%d)"
"\n bad symflag\n", etree, symflag, J) ;
break ;
}
return(nent) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
return the number of internal LU operations for a front
created -- 96dec04, cca
-------------------------------------------------------
*/
double
ETree_nInternalOpsInFront (
ETree *etree,
int type,
int symflag,
int J
) {
double b, m, ops ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| J < 0 || J >= etree->nfront ) {
fprintf(stderr,
"\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
"\n bad input\n", etree, type, symflag, J) ;
exit(-1) ;
}
b = ETree_frontSize(etree, J) ;
m = ETree_frontBoundarySize(etree, J) ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
ops = (b*(b+1)*(2*b+1))/6. + m*b*b ;
break ;
case SPOOLES_NONSYMMETRIC :
ops = b*(2*b*b+1)/3. + 2*m*b*b ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
"\n bad symflag\n", etree, type, symflag, J) ;
break ;
}
switch ( type ) {
case SPOOLES_REAL :
break ;
case SPOOLES_COMPLEX :
ops = 4*ops ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nInternalOpsInFront(%p,%d,%d,%d)"
"\n bad type\n", etree, type, symflag, J) ;
break ;
}
return(ops) ; }
/*--------------------------------------------------------------------*/
/*
-------------------------------------------------------
return the number of external LU operations for a front
created -- 96dec04, cca
-------------------------------------------------------
*/
double
ETree_nExternalOpsInFront (
ETree *etree,
int type,
int symflag,
int J
) {
double b, m, ops ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL
|| etree->nfront <= 0
|| J < 0 || J >= etree->nfront ) {
fprintf(stderr,
"\n fatal error in ETree_nExternalOpsInFront(%p,%d,%d,%d)"
"\n bad input\n", etree, J, type, symflag) ;
exit(-1) ;
}
b = IV_entry(etree->nodwghtsIV, J) ;
m = IV_entry(etree->bndwghtsIV, J) ;
switch ( symflag ) {
case SPOOLES_SYMMETRIC :
case SPOOLES_HERMITIAN :
ops = m*(m+1)*b ;
break ;
case SPOOLES_NONSYMMETRIC :
ops = 2*b*m*m ;
break ;
default :
break ;
}
switch ( type ) {
case SPOOLES_REAL :
break ;
case SPOOLES_COMPLEX :
ops = 4*ops ;
break ;
default :
fprintf(stderr,
"\n fatal error in ETree_nExternalOpsInFront(%p,%d,%d,%d)"
"\n bad input\n", etree, J, type, symflag) ;
break ;
}
return(ops) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
return a DV object that contains the number of operations
for each front using a backward looking algorithm
created -- 96dec04, cca
---------------------------------------------------------
*/
DV *
ETree_backwardOps (
ETree *etree,
int type,
int symflag,
int *vwghts,
IVL *symbfacIVL
) {
double extops, opsKbndK, opsKK ;
double *ops ;
DV *opsDV ;
int bndwghtJ, ii, J, k, K, kwght,
nadj, nfront, size, wghtJ, wghtK ;
int *counts, *indices, *list, *mark, *vtxToFront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || symbfacIVL == NULL ) {
fprintf(stderr, "\n fatal error in ETree_backwardOps(%p,%p,%p)"
"\n bad input\n", etree, vwghts, symbfacIVL) ;
exit(-1) ;
}
nfront = etree->nfront ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
list = IVinit(nfront, -1) ;
mark = IVinit(nfront, -1) ;
counts = IVinit(nfront, 0) ;
/*
----------------------------
initialize the ops DV object
----------------------------
*/
opsDV = DV_new() ;
DV_init(opsDV, nfront, NULL) ;
ops = DV_entries(opsDV) ;
DV_fill(opsDV, 0.0) ;
/*
-------------------
fill the ops vector
-------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
ops[J] += ETree_nInternalOpsInFront(etree, type, symflag, J) ;
wghtJ = ETree_frontSize(etree, J) ;
bndwghtJ = ETree_frontBoundarySize(etree, J) ;
IVL_listAndSize(symbfacIVL, J, &size, &indices) ;
for ( ii = nadj = 0 ; ii < size ; ii++ ) {
k = indices[ii] ;
if ( (K = vtxToFront[k]) != J ) {
kwght = (vwghts == NULL) ? 1 : vwghts[k] ;
if ( mark[K] != J ) {
counts[K] = 0 ;
mark[K] = J ;
list[nadj++] = K ;
}
counts[K] += kwght ;
}
}
IVqsortUp(nadj, list) ;
extops = 0.0 ;
for ( ii = 0 ; ii < nadj ; ii++ ) {
K = list[ii] ;
wghtK = counts[K] ;
bndwghtJ -= wghtK ;
if ( type == SPOOLES_REAL ) {
opsKbndK = 2*wghtJ*wghtK*bndwghtJ ;
if ( symflag == SPOOLES_SYMMETRIC ) {
opsKK = wghtJ*wghtK*(wghtK+1) ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
opsKK = 2*wghtJ*wghtK*wghtK ;
}
} else if ( type == SPOOLES_COMPLEX ) {
opsKbndK = 8*wghtJ*wghtK*bndwghtJ ;
if ( symflag == SPOOLES_SYMMETRIC
|| symflag == SPOOLES_HERMITIAN ) {
opsKK = 4*wghtJ*wghtK*(wghtK+1) ;
} else if ( symflag == SPOOLES_NONSYMMETRIC ) {
opsKK = 8*wghtJ*wghtK*wghtK ;
}
}
extops += opsKK + opsKbndK ;
ops[K] += opsKK + opsKbndK ;
if ( symflag == SPOOLES_NONSYMMETRIC ) {
extops += opsKbndK ;
ops[K] += opsKbndK ;
}
}
/*
fprintf(stdout,
"\n front %d, %.0f internal ops, %.0f external ops, %.0f extops",
J, ETree_nInternalOpsInFront(etree, type, symflag, J),
ETree_nExternalOpsInFront(etree, type, symflag, J), extops) ;
*/
}
IVfree(list) ;
IVfree(mark) ;
IVfree(counts) ;
return(opsDV) ; }
/*--------------------------------------------------------------------*/
/*
------------------------------------
return an IV object that contains
the number of entries for each front
created -- 98jan30, cca
------------------------------------
*/
IV *
ETree_factorEntriesIV (
ETree *etree,
int symflag
) {
int J, nfront ;
int *nzf ;
IV *nzfIV ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_factorEntriesIV(%p,%d)"
"\n bad input\n", etree, symflag) ;
exit(-1) ;
}
nfront = ETree_nfront(etree) ;
/*
------------------------
initialize the IV object
------------------------
*/
nzfIV = IV_new() ;
IV_init(nzfIV, nfront, NULL) ;
nzf = IV_entries(nzfIV) ;
IV_fill(nzfIV, 0) ;
/*
-------------------
fill the nzf vector
-------------------
*/
for ( J = 0 ; J < nfront ; J++ ) {
nzf[J] = ETree_nFactorEntriesInFront(etree, symflag, J) ;
}
return(nzfIV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------
return a DV object that contains the number of operations
for each front using a forward-looking algorithm
created -- 96dec04, cca
---------------------------------------------------------
*/
DV *
ETree_forwardOps (
ETree *etree,
int type,
int symflag
) {
double *ops ;
DV *opsDV ;
int J, nfront ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL ) {
fprintf(stderr, "\n fatal error in ETree_forwardOps(%p)"
"\n bad input\n", etree) ;
exit(-1) ;
}
nfront = etree->nfront ;
opsDV = DV_new() ;
DV_init(opsDV, nfront, NULL) ;
ops = DV_entries(opsDV) ;
DV_fill(opsDV, 0.0) ;
for ( J = 0 ; J < nfront ; J++ ) {
ops[J] += ETree_nInternalOpsInFront(etree, type, symflag, J)
+ ETree_nExternalOpsInFront(etree, type, symflag, J) ;
}
return(opsDV) ; }
/*--------------------------------------------------------------------*/
/*
---------------------------------------------------------------
given an IV object that maps uncompressed vertices to vertices,
create and return an ETree object that is relative to the
uncompressed graph.
created -- 97feb13, cca
---------------------------------------------------------------
*/
ETree *
ETree_expand (
ETree *etree,
IV *eqmapIV
) {
ETree *etree2 ;
int ii, ndof, nfront ;
int *map, *vtxToFront, *vtxToFront2 ;
/*
---------------
check the input
---------------
*/
if ( etree == NULL || eqmapIV == NULL ) {
fprintf(stderr, "\n fatal error in ETree_expand(%p,%p)"
"\n bad input\n", etree, eqmapIV) ;
exit(-1) ;
}
nfront = etree->nfront ;
IV_sizeAndEntries(eqmapIV, &ndof, &map) ;
/*
---------------------------
create the new ETree object
---------------------------
*/
etree2 = ETree_new() ;
ETree_init1(etree2, nfront, ndof) ;
IV_copy(etree2->nodwghtsIV, etree->nodwghtsIV) ;
IV_copy(etree2->bndwghtsIV, etree->bndwghtsIV) ;
etree2->tree->root = etree->tree->root ;
IVcopy(nfront, etree2->tree->par, etree->tree->par) ;
IVcopy(nfront, etree2->tree->fch, etree->tree->fch) ;
IVcopy(nfront, etree2->tree->sib, etree->tree->sib) ;
vtxToFront = IV_entries(etree->vtxToFrontIV) ;
vtxToFront2 = IV_entries(etree2->vtxToFrontIV) ;
for ( ii = 0 ; ii < ndof ; ii++ ) {
vtxToFront2[ii] = vtxToFront[map[ii]] ;
}
return(etree2) ; }
/*--------------------------------------------------------------------*/
/*
--------------------------------------------------------------
this method is used to splice together two front trees
when the domain vertices and schur complement vertices
have been ordered separately.
etree0 -- the lower front tree is for vertices in the domains.
graph0 -- graph for all the vertices
mapIV -- IV object that maps vertices to schur complement
vertices, if IV_entry(mapIV, v) < 0 then v is
a domain vertex.
etree1 -- the upper front tree is for vertices in the schur
complement.
created -- 97feb01, cca
--------------------------------------------------------------
*/
ETree *
ETree_spliceTwoETrees (
ETree *etree0,
Graph *graph0,
IV *mapIV,
ETree *etree1
) {
ETree *etree2 ;
int *bndwghts0, *bndwghts1, *bndwghts2, *fch0, *head0, *link0,
*map, *mark, *nodwghts0, *nodwghts1, *nodwghts2, *par0,
*par1, *par2, *sib0, *vadj, *vtxToFront0, *vtxToFront1,
*vtxToFront2 ;
int ii, J, K, nfront0, nfront1, nfront2, nvtx, phi, v, vsize, w ;
/*
---------------
check the input
---------------
*/
if ( etree0 == NULL || graph0 == NULL
|| mapIV == NULL || etree1 == NULL ) {
fprintf(stderr,
"\n fatal error in ETree_spliceTwoETrees(%p,%p,%p,%p)"
"\n bad input\n",
etree0, graph0, mapIV, etree1) ;
exit(-1) ;
}
nfront0 = etree0->nfront ;
nvtx = etree0->nvtx ;
par0 = etree0->tree->par ;
fch0 = etree0->tree->fch ;
sib0 = etree0->tree->sib ;
nodwghts0 = IV_entries(etree0->nodwghtsIV) ;
bndwghts0 = IV_entries(etree0->bndwghtsIV) ;
vtxToFront0 = IV_entries(etree0->vtxToFrontIV) ;
nfront1 = etree1->nfront ;
par1 = etree1->tree->par ;
bndwghts1 = IV_entries(etree1->bndwghtsIV) ;
nodwghts1 = IV_entries(etree1->nodwghtsIV) ;
vtxToFront1 = IV_entries(etree1->vtxToFrontIV) ;
map = IV_entries(mapIV) ;
/*
-------------------------
create the new front tree
-------------------------
*/
nfront2 = nfront0 + nfront1 ;
etree2 = ETree_new() ;
ETree_init1(etree2, nfront2, etree0->nvtx) ;
par2 = etree2->tree->par ;
nodwghts2 = IV_entries(etree2->nodwghtsIV) ;
bndwghts2 = IV_entries(etree2->bndwghtsIV) ;
vtxToFront2 = IV_entries(etree2->vtxToFrontIV) ;
/*
--------------------------------------------------
fill the parent fields for fronts in the same tree
--------------------------------------------------
*/
for ( J = 0 ; J < nfront0 ; J++ ) {
par2[J] = par0[J] ;
nodwghts2[J] = nodwghts0[J] ;
bndwghts2[J] = bndwghts0[J] ;
}
for ( J = 0 ; J < nfront1 ; J++ ) {
par2[J+nfront0] = nfront0 + par1[J] ;
nodwghts2[J+nfront0] = nodwghts1[J] ;
bndwghts2[J+nfront0] = bndwghts1[J] ;
}
/*
---------------------------
set the vertex to front map
---------------------------
*/
for ( v = 0 ; v < nvtx ; v++ ) {
if ( (J = vtxToFront0[v]) >= 0 ) {
vtxToFront2[v] = J ;
} else {
vtxToFront2[v] = vtxToFront1[map[v]] + nfront0 ;
}
}
/*
---------------------------------------------
link the vertices to fronts in the lower tree
---------------------------------------------
*/
head0 = IVinit(nfront0, -1) ;
link0 = IVinit(nvtx, -1) ;
for ( v = 0 ; v < nvtx ; v++ ) {
if ( (J = vtxToFront0[v]) >= 0 ) {
link0[v] = head0[J] ;
head0[J] = v ;
}
}
/*
-------------------------------------------------------
link roots of the lower tree to nodes in the upper tree
-------------------------------------------------------
*/
mark = IVinit(nvtx, -1) ;
for ( J = etree0->tree->root ; J != -1 ; J = sib0[J] ) {
/*
---------------------------------------
K is the parent front in the upper tree
---------------------------------------
*/
K = nfront1 ;
/*
---------------------------------------
loop over vertices in the lower front J
---------------------------------------
*/
for ( v = head0[J] ; v != -1 ; v = link0[v] ) {
Graph_adjAndSize(graph0, v, &vsize, &vadj) ;
for ( ii = 0 ; ii < vsize ; ii++ ) {
w = vadj[ii] ;
if ( vtxToFront0[w] < 0 ) {
phi = map[w] ;
/*
---------------------------------------------------
w is a vertex that belongs to phi in the upper tree
---------------------------------------------------
*/
if ( mark[phi] != J ) {
mark[phi] = J ;
if ( K > vtxToFront1[phi] ) {
/*
------------------------------------
least numbered adjacent front so far
------------------------------------
*/
K = vtxToFront1[phi] ;
}
}
}
}
}
if ( K < nfront1 ) {
/*
--------------------
set the parent field
--------------------
*/
par2[J] = nfront0 + K ;
}
}
/*
-----------------------------
set the remaining tree fields
-----------------------------
*/
Tree_setFchSibRoot(etree2->tree) ;
/*
------------------------
free the working storage
------------------------
*/
IVfree(head0) ;
IVfree(link0) ;
IVfree(mark) ;
return(etree2) ; }
/*--------------------------------------------------------------------*/
syntax highlighted by Code2HTML, v. 0.9.1