Commit 06e06689 authored by Pierre Kraemer's avatar Pierre Kraemer

SuperLU update in OpenNL + debug in renderTopoSurface plugin

parent fc33bdaf
...@@ -33,7 +33,7 @@ find_package(Boost COMPONENTS regex thread system REQUIRED) ...@@ -33,7 +33,7 @@ find_package(Boost COMPONENTS regex thread system REQUIRED)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
find_package(LibXml2 REQUIRED) find_package(LibXml2 REQUIRED)
find_package(GLEW REQUIRED) find_package(GLEW REQUIRED)
find_package(SuiteSparse REQUIRED) #find_package(SuiteSparse REQUIRED)
IF (DEFINED ASSERTON) IF (DEFINED ASSERTON)
add_definitions(-DCGOGN_ASSERT_BOOL=${ASSERTON}) add_definitions(-DCGOGN_ASSERT_BOOL=${ASSERTON})
...@@ -73,7 +73,7 @@ SET (CGoGN_EXT_INCLUDES ...@@ -73,7 +73,7 @@ SET (CGoGN_EXT_INCLUDES
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}
${LIBXML2_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}
${Boost_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}
# ${SUITESPARSE_INCLUDE_DIRS}
) )
# define libs for external libs # define libs for external libs
...@@ -86,7 +86,7 @@ SET (CGoGN_EXT_LIBS ...@@ -86,7 +86,7 @@ SET (CGoGN_EXT_LIBS
${Boost_SYSTEM_LIBRARY} ${Boost_SYSTEM_LIBRARY}
${Boost_REGEX_LIBRARY} ${Boost_REGEX_LIBRARY}
${Boost_THREAD_LIBRARY} ${Boost_THREAD_LIBRARY}
${SUITESPARSE_LIBRARIES} # ${SUITESPARSE_LIBRARIES}
) )
#optionnal libs #optionnal libs
......
...@@ -18,6 +18,8 @@ find_package(Qt4 REQUIRED) ...@@ -18,6 +18,8 @@ find_package(Qt4 REQUIRED)
find_package(QGLViewer REQUIRED) find_package(QGLViewer REQUIRED)
find_package(PythonLibs 2.7 REQUIRED) find_package(PythonLibs 2.7 REQUIRED)
find_package(SuiteSparse REQUIRED) find_package(SuiteSparse REQUIRED)
find_package(SuperLU REQUIRED)
SET( QT_USE_QTOPENGL TRUE ) SET( QT_USE_QTOPENGL TRUE )
SET( QT_USE_QTXML TRUE ) SET( QT_USE_QTXML TRUE )
...@@ -68,6 +70,7 @@ SET (EXT_INCLUDES ...@@ -68,6 +70,7 @@ SET (EXT_INCLUDES
${QGLVIEWER_INCLUDE_DIR} ${QGLVIEWER_INCLUDE_DIR}
${PYTHON_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}
${SUITESPARSE_INCLUDE_DIRS} ${SUITESPARSE_INCLUDE_DIRS}
${SUPERLU_INCLUDE_DIRS}
) )
# define libs for external libs # define libs for external libs
...@@ -85,6 +88,7 @@ SET (EXT_LIBS ...@@ -85,6 +88,7 @@ SET (EXT_LIBS
${QGLVIEWER_LIBRARIES} ${QGLVIEWER_LIBRARIES}
${PYTHON_LIBRARIES} ${PYTHON_LIBRARIES}
${SUITESPARSE_LIBRARIES} ${SUITESPARSE_LIBRARIES}
${SUPERLU_LIBRARIES}
) )
......
...@@ -28,7 +28,6 @@ ComputeNormalDialog::ComputeNormalDialog(Window* w) : ...@@ -28,7 +28,6 @@ ComputeNormalDialog::ComputeNormalDialog(Window* w) :
{ {
QListWidgetItem* item = new QListWidgetItem(map->getName(), mapList); QListWidgetItem* item = new QListWidgetItem(map->getName(), mapList);
item->setCheckState(Qt::Unchecked); item->setCheckState(Qt::Unchecked);
connect(map, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
} }
} }
......
...@@ -95,6 +95,8 @@ void RenderTopoSurfacePlugin::viewLinked(View* view, Plugin* plugin) ...@@ -95,6 +95,8 @@ void RenderTopoSurfacePlugin::viewLinked(View* view, Plugin* plugin)
const QList<MapHandlerGen*>& maps = view->getLinkedMaps(); const QList<MapHandlerGen*>& maps = view->getLinkedMaps();
foreach(MapHandlerGen* mh, maps) foreach(MapHandlerGen* mh, maps)
{ {
connect(mh, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
connect(mh, SIGNAL(connectivityModified()), this, SLOT(connectivityModified()));
PerMapParameterSet* p = new PerMapParameterSet(mh); PerMapParameterSet* p = new PerMapParameterSet(mh);
registerShader(p->m_renderTopo->shader1()); registerShader(p->m_renderTopo->shader1());
registerShader(p->m_renderTopo->shader2()); registerShader(p->m_renderTopo->shader2());
...@@ -119,6 +121,8 @@ void RenderTopoSurfacePlugin::viewUnlinked(View* view, Plugin* plugin) ...@@ -119,6 +121,8 @@ void RenderTopoSurfacePlugin::viewUnlinked(View* view, Plugin* plugin)
QHash<QString, PerMapParameterSet*>::const_iterator i = params->perMap.constBegin(); QHash<QString, PerMapParameterSet*>::const_iterator i = params->perMap.constBegin();
while (i != params->perMap.constEnd()) while (i != params->perMap.constEnd())
{ {
disconnect(i.value()->mh, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
disconnect(i.value()->mh, SIGNAL(connectivityModified()), this, SLOT(connectivityModified()));
unregisterShader(i.value()->m_renderTopo->shader1()); unregisterShader(i.value()->m_renderTopo->shader1());
unregisterShader(i.value()->m_renderTopo->shader2()); unregisterShader(i.value()->m_renderTopo->shader2());
delete i.value(); delete i.value();
...@@ -146,10 +150,10 @@ void RenderTopoSurfacePlugin::mapLinked(MapHandlerGen* m) ...@@ -146,10 +150,10 @@ void RenderTopoSurfacePlugin::mapLinked(MapHandlerGen* m)
connect(m, SIGNAL(connectivityModified()), this, SLOT(connectivityModified())); connect(m, SIGNAL(connectivityModified()), this, SLOT(connectivityModified()));
ParameterSet* params = h_viewParams[view]; ParameterSet* params = h_viewParams[view];
PerMapParameterSet* p = new PerMapParameterSet(m); PerMapParameterSet* perMap = new PerMapParameterSet(m);
registerShader(p->m_renderTopo->shader1()); registerShader(perMap->m_renderTopo->shader1());
registerShader(p->m_renderTopo->shader2()); registerShader(perMap->m_renderTopo->shader2());
params->perMap.insert(m->getName(), p); params->perMap.insert(m->getName(), perMap);
if(params->selectedMap == NULL || params->perMap.count() == 1) if(params->selectedMap == NULL || params->perMap.count() == 1)
changeSelectedMap(view, m); changeSelectedMap(view, m);
else else
...@@ -165,7 +169,10 @@ void RenderTopoSurfacePlugin::mapUnlinked(MapHandlerGen* m) ...@@ -165,7 +169,10 @@ void RenderTopoSurfacePlugin::mapUnlinked(MapHandlerGen* m)
disconnect(m, SIGNAL(connectivityModified()), this, SLOT(connectivityModified())); disconnect(m, SIGNAL(connectivityModified()), this, SLOT(connectivityModified()));
ParameterSet* params = h_viewParams[view]; ParameterSet* params = h_viewParams[view];
delete params->perMap[m->getName()]; PerMapParameterSet* perMap = params->perMap[m->getName()];
unregisterShader(perMap->m_renderTopo->shader1());
unregisterShader(perMap->m_renderTopo->shader2());
delete perMap;
params->perMap.remove(m->getName()); params->perMap.remove(m->getName());
if(params->selectedMap == m) if(params->selectedMap == m)
......
importPlugin = schnapps.loadPlugin("ImportSurface"); importPlugin = schnapps.loadPlugin("ImportSurface");
renderPlugin = schnapps.loadPlugin("Render"); renderPlugin = schnapps.loadPlugin("Render");
renderVectorPlugin = schnapps.loadPlugin("RenderVector"); #renderVectorPlugin = schnapps.loadPlugin("RenderVector");
renderTopoSurfacePlugin = schnapps.loadPlugin("RenderTopoSurface"); #renderTopoSurfacePlugin = schnapps.loadPlugin("RenderTopoSurface");
differentialPropertiesPlugin = schnapps.loadPlugin("DifferentialProperties"); #differentialPropertiesPlugin = schnapps.loadPlugin("DifferentialProperties");
subdivisionPlugin = schnapps.loadPlugin("SubdivideSurface"); #subdivisionPlugin = schnapps.loadPlugin("SubdivideSurface");
surfaceDeformationPlugin = schnapps.loadPlugin("SurfaceDeformation"); surfaceDeformationPlugin = schnapps.loadPlugin("SurfaceDeformation");
obj = importPlugin.importFromFile("/home/kraemer/Media/Data/surface/lowRes/iphi_good_9k.off"); obj = importPlugin.importFromFile("/home/kraemer/Media/Data/surface/lowRes/iphi_good_9k.off");
...@@ -11,11 +11,11 @@ obj = importPlugin.importFromFile("/home/kraemer/Media/Data/surface/lowRes/iphi_ ...@@ -11,11 +11,11 @@ obj = importPlugin.importFromFile("/home/kraemer/Media/Data/surface/lowRes/iphi_
v = schnapps.getView("view_0"); v = schnapps.getView("view_0");
schnapps.linkViewAndPlugin(v.getName(), renderPlugin.getName()); schnapps.linkViewAndPlugin(v.getName(), renderPlugin.getName());
schnapps.linkViewAndPlugin(v.getName(), renderVectorPlugin.getName()); #schnapps.linkViewAndPlugin(v.getName(), renderVectorPlugin.getName());
schnapps.linkViewAndPlugin(v.getName(), renderTopoSurfacePlugin.getName()); #schnapps.linkViewAndPlugin(v.getName(), renderTopoSurfacePlugin.getName());
schnapps.linkViewAndPlugin(v.getName(), surfaceDeformationPlugin.getName()); schnapps.linkViewAndPlugin(v.getName(), surfaceDeformationPlugin.getName());
schnapps.linkViewAndMap(v.getName(), obj.getName()); schnapps.linkViewAndMap(v.getName(), obj.getName());
differentialPropertiesPlugin.computeNormal(obj.getName()); #differentialPropertiesPlugin.computeNormal(obj.getName());
differentialPropertiesPlugin.computeCurvature(obj.getName()); #differentialPropertiesPlugin.computeCurvature(obj.getName());
...@@ -23,18 +23,15 @@ void ColorComboBox::populateList() ...@@ -23,18 +23,15 @@ void ColorComboBox::populateList()
//QStringList colorNames = QColor::colorNames(); //QStringList colorNames = QColor::colorNames();
QStringList colorNames; QStringList colorNames;
colorNames << colorNames <<
"darkGreen" <<
"green" <<
"gray" <<
"red" << "red" <<
"white" << "green" <<
"blue" << "blue" <<
"cyan "<< "cyan "<<
"darkMagenta" << "magenta" <<
"yellow" << "yellow" <<
"darkRed" << "gray" <<
"black" << "white" <<
"magenta"; "black";
for (int i = 0; i < colorNames.size(); ++i) { for (int i = 0; i < colorNames.size(); ++i) {
QColor color(colorNames[i]); QColor color(colorNames[i]);
......
...@@ -55,7 +55,8 @@ SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/OpenNL/CMakeModules) ...@@ -55,7 +55,8 @@ SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/OpenNL/CMakeModules)
# (with a single underscore) rather than -DAdd__ (with two # (with a single underscore) rather than -DAdd__ (with two
# underscores). If you got two underscores, remove the # underscores). If you got two underscores, remove the
# second one, make clean and re-make SuperLU. # second one, make clean and re-make SuperLU.
#SET(USE_SUPERLU TRUE) SET(USE_SUPERLU TRUE)
find_package(SuperLU REQUIRED)
# Edit these lines to match your installation # Edit these lines to match your installation
#SET(SUPERLU_HOME /home/yourself/SuperLU_4.0 ) #SET(SUPERLU_HOME /home/yourself/SuperLU_4.0 )
......
...@@ -20,8 +20,8 @@ ENDIF(USE_ATLAS) ...@@ -20,8 +20,8 @@ ENDIF(USE_ATLAS)
IF(USE_SUPERLU) IF(USE_SUPERLU)
ADD_DEFINITIONS(-DNL_USE_SUPERLU) ADD_DEFINITIONS(-DNL_USE_SUPERLU)
SET(SUPERLU_INCS ${SUPERLU_HOME}/SRC) # SET(SUPERLU_INCS ${SUPERLU_HOME}/SRC)
INCLUDE_DIRECTORIES(${SUPERLU_INCS}) INCLUDE_DIRECTORIES(${SUPERLU_INCLUDE_DIRS})
ENDIF(USE_SUPERLU) ENDIF(USE_SUPERLU)
IF(USE_CHOLMOD) IF(USE_CHOLMOD)
......
...@@ -121,9 +121,6 @@ typedef void* NLContext ; ...@@ -121,9 +121,6 @@ typedef void* NLContext ;
#define NL_ELAPSED_TIME 0x10a #define NL_ELAPSED_TIME 0x10a
#define NL_PRECONDITIONER 0x10b #define NL_PRECONDITIONER 0x10b
//#define NL_DIRECT 0x10c
//#define NL_FACTORIZED 0x10d
/* Solvers */ /* Solvers */
#define NL_CG 0x200 #define NL_CG 0x200
...@@ -133,7 +130,6 @@ typedef void* NLContext ; ...@@ -133,7 +130,6 @@ typedef void* NLContext ;
#define NL_PERM_SUPERLU_EXT 0x211 #define NL_PERM_SUPERLU_EXT 0x211
#define NL_SYMMETRIC_SUPERLU_EXT 0x212 #define NL_SYMMETRIC_SUPERLU_EXT 0x212
#define NL_SOLVER_USER 0x213 #define NL_SOLVER_USER 0x213
#define NL_CHOLMOD_EXT 0x214 #define NL_CHOLMOD_EXT 0x214
#define NL_CNC_FLOAT_CRS 0x220 #define NL_CNC_FLOAT_CRS 0x220
......
...@@ -517,7 +517,10 @@ void nlEndMatrix() { ...@@ -517,7 +517,10 @@ void nlEndMatrix() {
) ; ) ;
} }
if(nlCurrentContext->solver == NL_CHOLMOD_EXT && // or any other direct solver if((nlCurrentContext->solver == NL_CHOLMOD_EXT || // or any other direct solver
nlCurrentContext->solver == NL_SUPERLU_EXT ||
nlCurrentContext->solver == NL_PERM_SUPERLU_EXT ||
nlCurrentContext->solver == NL_SYMMETRIC_SUPERLU_EXT) &&
nlCurrentContext->direct_solver_context == NULL) { nlCurrentContext->direct_solver_context == NULL) {
nlCurrentContext->factorize_func() ; nlCurrentContext->factorize_func() ;
} }
...@@ -717,7 +720,10 @@ void nlReset(NLboolean keep_matrix) { ...@@ -717,7 +720,10 @@ void nlReset(NLboolean keep_matrix) {
nlUnlockVariable(i); nlUnlockVariable(i);
} }
nlCurrentContext->matrix_already_set = NL_FALSE ; nlCurrentContext->matrix_already_set = NL_FALSE ;
if(nlCurrentContext->solver == NL_CHOLMOD_EXT) { // or any other direct solver if( nlCurrentContext->solver == NL_CHOLMOD_EXT || // or any other direct solver
nlCurrentContext->solver == NL_SUPERLU_EXT ||
nlCurrentContext->solver == NL_PERM_SUPERLU_EXT ||
nlCurrentContext->solver == NL_SYMMETRIC_SUPERLU_EXT) {
nlCurrentContext->clear_factor_func() ; nlCurrentContext->clear_factor_func() ;
} }
} }
......
...@@ -57,8 +57,8 @@ ...@@ -57,8 +57,8 @@
typedef struct { typedef struct {
cholmod_common c ; cholmod_common c ;
cholmod_factor* cL ; cholmod_factor* cL ; // factor
cholmod_dense* cb ; cholmod_dense* cb ; // right-hand side
} cholmod_context ; } cholmod_context ;
...@@ -87,13 +87,13 @@ NLboolean nlFactorize_CHOLMOD() { ...@@ -87,13 +87,13 @@ NLboolean nlFactorize_CHOLMOD() {
nl_assert(M->storage & NL_MATRIX_STORE_COLUMNS) ; nl_assert(M->storage & NL_MATRIX_STORE_COLUMNS) ;
nl_assert(M->m == M->n) ; nl_assert(M->m == M->n) ;
cholmod_start(&(context->c)) ;
/* /*
* Step 1: convert matrix M into CHOLMOD compressed column representation * Step 1: convert matrix M into CHOLMOD compressed column representation
* ---------------------------------------------------------------------- * ----------------------------------------------------------------------
*/ */
cholmod_start(&(context->c)) ;
cA = cholmod_allocate_sparse(n, n, nnz, NL_FALSE, NL_TRUE, -1, CHOLMOD_REAL, &(context->c)) ; cA = cholmod_allocate_sparse(n, n, nnz, NL_FALSE, NL_TRUE, -1, CHOLMOD_REAL, &(context->c)) ;
int* colptr = (int*)(cA->p) ; int* colptr = (int*)(cA->p) ;
int* rowind = (int*)(cA->i) ; int* rowind = (int*)(cA->i) ;
...@@ -154,9 +154,8 @@ NLboolean nlSolve_CHOLMOD() { ...@@ -154,9 +154,8 @@ NLboolean nlSolve_CHOLMOD() {
*/ */
double* cbx = (double*)(context->cb->x) ; double* cbx = (double*)(context->cb->x) ;
for(i = 0; i < n; i++) { for(i = 0; i < n; i++)
cbx[i] = b[i] ; cbx[i] = b[i] ;
}
/* /*
* Step 2: solve * Step 2: solve
...@@ -207,4 +206,9 @@ NLboolean nlSolve_CHOLMOD() { ...@@ -207,4 +206,9 @@ NLboolean nlSolve_CHOLMOD() {
return NL_FALSE ; return NL_FALSE ;
} }
NLboolean nlClear_CHOLMOD() {
nl_assert_not_reached ;
return NL_FALSE ;
}
#endif #endif
...@@ -108,7 +108,10 @@ void nlDeleteContext(NLContext context_in) { ...@@ -108,7 +108,10 @@ void nlDeleteContext(NLContext context_in) {
if(context->alloc_b) { if(context->alloc_b) {
NL_DELETE_ARRAY(context->b) ; NL_DELETE_ARRAY(context->b) ;
} }
if(context->solver == NL_CHOLMOD_EXT) { // or any other direct solver if( context->solver == NL_CHOLMOD_EXT || // or any other direct solver
context->solver == NL_SUPERLU_EXT ||
context->solver == NL_PERM_SUPERLU_EXT ||
context->solver == NL_SYMMETRIC_SUPERLU_EXT) {
context->clear_factor_func() ; context->clear_factor_func() ;
} }
...@@ -268,10 +271,12 @@ NLboolean nlDefaultFactorize() { ...@@ -268,10 +271,12 @@ NLboolean nlDefaultFactorize() {
case NL_CNC_FLOAT_ELL: case NL_CNC_FLOAT_ELL:
case NL_CNC_DOUBLE_ELL: case NL_CNC_DOUBLE_ELL:
case NL_CNC_FLOAT_HYB: case NL_CNC_FLOAT_HYB:
case NL_CNC_DOUBLE_HYB: case NL_CNC_DOUBLE_HYB: break ;
case NL_SUPERLU_EXT: case NL_SUPERLU_EXT:
case NL_PERM_SUPERLU_EXT: case NL_PERM_SUPERLU_EXT:
case NL_SYMMETRIC_SUPERLU_EXT: break ; case NL_SYMMETRIC_SUPERLU_EXT: {
result = nlFactorize_SUPERLU() ;
} break ;
case NL_CHOLMOD_EXT: { case NL_CHOLMOD_EXT: {
result = nlFactorize_CHOLMOD() ; result = nlFactorize_CHOLMOD() ;
} break ; } break ;
...@@ -293,10 +298,12 @@ void nlDefaultClearFactor() { ...@@ -293,10 +298,12 @@ void nlDefaultClearFactor() {
case NL_CNC_FLOAT_ELL: case NL_CNC_FLOAT_ELL:
case NL_CNC_DOUBLE_ELL: case NL_CNC_DOUBLE_ELL:
case NL_CNC_FLOAT_HYB: case NL_CNC_FLOAT_HYB:
case NL_CNC_DOUBLE_HYB: case NL_CNC_DOUBLE_HYB: break ;
case NL_SUPERLU_EXT: case NL_SUPERLU_EXT:
case NL_PERM_SUPERLU_EXT: case NL_PERM_SUPERLU_EXT:
case NL_SYMMETRIC_SUPERLU_EXT: break ; case NL_SYMMETRIC_SUPERLU_EXT: {
nlClear_SUPERLU() ;
} break ;
case NL_CHOLMOD_EXT: { case NL_CHOLMOD_EXT: {
nlClear_CHOLMOD() ; nlClear_CHOLMOD() ;
} break ; } break ;
......
...@@ -54,175 +54,232 @@ ...@@ -54,175 +54,232 @@
#include <slu_cdefs.h> #include <slu_cdefs.h>
#include <supermatrix.h> #include <supermatrix.h>
/* Note: SuperLU is difficult to call, but it is worth it. */
/* Here is a driver inspired by A. Sheffer's "cow flattener". */ typedef struct {
NLboolean nlSolve_SUPERLU() { superlu_options_t options ;
SuperLUStat_t stat ;
SuperMatrix L ;
SuperMatrix U ;
NLint* perm_c ;
NLint* perm_r;
} superlu_context ;
NLboolean nlFactorize_SUPERLU() {
/* OpenNL Context */ /* OpenNL Context */
NLSparseMatrix* M = &(nlCurrentContext->M) ; NLSparseMatrix* M = &(nlCurrentContext->M) ;
NLdouble* b = nlCurrentContext->b ;
NLdouble* x = nlCurrentContext->x ;
/* Compressed Row Storage matrix representation */
NLuint n = nlCurrentContext->n ; NLuint n = nlCurrentContext->n ;
NLuint nnz = nlSparseMatrixNNZ(M) ; /* Number of Non-Zero coeffs */ NLuint nnz = nlSparseMatrixNNZ(M) ; /* Number of Non-Zero coeffs */
NLint* xa = NL_NEW_ARRAY(NLint, n+1) ;
NLdouble* rhs = NL_NEW_ARRAY(NLdouble, n) ;
NLdouble* a = NL_NEW_ARRAY(NLdouble, nnz) ;
NLint* asub = NL_NEW_ARRAY(NLint, nnz) ;
/* Permutation vector */
NLint* perm_r = NL_NEW_ARRAY(NLint, n) ;
NLint* perm = NL_NEW_ARRAY(NLint, n) ;
/* SuperLU variables */ superlu_context* context = (superlu_context*)(nlCurrentContext->direct_solver_context) ;
SuperMatrix A, B ; /* System */ if(context == NULL) {
SuperMatrix L, U ; /* Inverse of A */ nlCurrentContext->direct_solver_context = malloc(sizeof(superlu_context)) ;
NLint info ; /* status code */ context = (superlu_context*)(nlCurrentContext->direct_solver_context) ;
DNformat *vals = NULL ; /* access to result */ }
double *rvals = NULL ; /* access to result */
/* SuperLU options and stats */ /* SUPERLU variables */
superlu_options_t options ; NLint info ;
SuperLUStat_t stat ; SuperMatrix A, AC ;
/* Temporary variables */ /* Temporary variables */
NLRowColumn* Ri = NULL ; NLRowColumn* Ci = NULL ;
NLuint i,jj,count ; NLuint i,j,count ;
/* Sanity checks */ /* Sanity checks */
nl_assert(!(M->storage & NL_MATRIX_STORE_SYMMETRIC)) ; nl_assert(!(M->storage & NL_MATRIX_STORE_SYMMETRIC)) ;
nl_assert(M->storage & NL_MATRIX_STORE_ROWS) ; nl_assert(M->storage & NL_MATRIX_STORE_ROWS) ;
nl_assert(M->m == M->n) ; nl_assert(M->m == M->n) ;
set_default_options(&(context->options)) ;
switch(nlCurrentContext->solver) {
case NL_SUPERLU_EXT: {
context->options.ColPerm = NATURAL ;
} break ;
case NL_PERM_SUPERLU_EXT: {
context->options.ColPerm = COLAMD ;
} break ;
case NL_SYMMETRIC_SUPERLU_EXT: {
context->options.ColPerm = MMD_AT_PLUS_A ;
context->options.SymmetricMode = YES ;
} break ;
default: {
nl_assert_not_reached ;
} break ;
}
StatInit(&(context->stat)) ;
/* /*
* Step 1: convert matrix M into SuperLU compressed column * Step 1: convert matrix M into SUPERLU compressed column representation
* representation. * ----------------------------------------------------------------------
* -------------------------------------------------------
*/ */
NLint* xa = NL_NEW_ARRAY(NLint, n+1) ;
NLdouble* a = NL_NEW_ARRAY(NLdouble, nnz) ;
NLint* asub = NL_NEW_ARRAY(NLint, nnz) ;
count = 0 ; count = 0 ;
for(i=0; i<n; i++) { for(i = 0; i < n; i++) {
Ri = &(M->row[i]) ; Ci = &(M->row[i]) ;
xa[i] = count ; xa[i] = count ;
for(jj=0; jj<Ri->size; jj++) { for(j = 0; j < Ci->size; j++) {
a[count] = Ri->coeff[jj].value ; a[count] = Ci->coeff[j].value ;
asub[count] = Ri->coeff[jj].index ; asub[count] = Ci->coeff[j].index ;
count++ ; count++ ;
} }
} }
xa[n] = nnz ; xa[n] = nnz ;
/* Save memory for SuperLU */
nlSparseMatrixClear(M) ;
/*
* Rem: SuperLU does not support symmetric storage.
* In fact, for symmetric matrix, what we need
* is a SuperLLt algorithm (SuperNodal sparse Cholesky),
* but it does not exist, anybody wants to implement it ?
* However, this is not a big problem (SuperLU is just
* a superset of what we really need.
*/
dCreate_CompCol_Matrix( dCreate_CompCol_Matrix(
&A, n, n, nnz, a, asub, xa, &A, n, n, nnz, a, asub, xa,
SLU_NR, /* Row_wise, no supernode */ SLU_NR, /* Row wise */
SLU_D, /* doubles */ SLU_D, /* doubles */
SLU_GE /* general storage */ SLU_GE /* general storage */
); );
/* Step 2: create vector */ /*
dCreate_Dense_Matrix( * Step 2: factorize matrix
&B, n, 1, b, n, * ------------------------
SLU_DN, /* Fortran-type column-wise storage */ */
SLU_D, /* doubles */
SLU_GE /* general */
);
context->perm_c = NL_NEW_ARRAY(NLint, n) ;
context->perm_r = NL_NEW_ARRAY(NLint, n) ;
NLint* etree = NL_NEW_ARRAY(NLint, n) ;
get_perm_c(context->options.ColPerm, &A, context->perm_c) ;
sp_preorder(&(context->options), &A, context->perm_c, etree, &AC) ;
int panel_size = sp_ienv(1) ;
int relax = sp_ienv(2) ;
dgstrf(&(context->options),
&AC,
relax,
panel_size,
etree,
NULL,
0,
context->perm_c,
context->perm_r,
&(context->L),
&(context->U),
&(context->stat),
&info) ;
/* Step 3: set SuperLU options /*
* ------------------------------ * Step 3: cleanup
* ---------------
*/ */
set_default_options(&options) ; NL_DELETE_ARRAY(xa) ;
NL_DELETE_ARRAY(a) ;
NL_DELETE_ARRAY(asub) ;
NL_DELETE_ARRAY(etree) ;
Destroy_SuperMatrix_Store(&A);
Destroy_CompCol_Permuted(&AC);
StatFree(&(context->stat));
switch(nlCurrentContext->solver) { return NL_TRUE ;
case NL_SUPERLU_EXT: { }
options.ColPerm = NATURAL ;
} break ; NLboolean nlSolve_SUPERLU() {
case NL_PERM_SUPERLU_EXT: {
options.ColPerm = COLAMD ; /* OpenNL Context */
} break ; NLdouble* b = nlCurrentContext->b ;
case NL_SYMMETRIC_SUPERLU_EXT: { NLdouble* x = nlCurrentContext->x ;
options.ColPerm = MMD_AT_PLUS_A ; NLuint n = nlCurrentContext->n ;
options.SymmetricMode = YES ;
} break ; superlu_context* context = (superlu_context*)(nlCurrentContext->direct_solver_context) ;
default: { nl_assert(context != NULL) ;
nl_assert_not_reached ;
} break ; /* SUPERLU variables */
} SuperMatrix B ;
DNformat *vals = NULL ; /* access to result */
double *rvals = NULL ; /* access to result */
/* Temporary variables */
NLuint i ;
NLint info ;
StatInit(&(context->stat)) ;
StatInit(&stat) ; /*
* Step 1: convert right-hand side into SUPERLU representation
* -----------------------------------------------------------
*/
dCreate_Dense_Matrix(
&B, n, 1, b, n,
SLU_DN, /* Fortran-type column-wise storage */
SLU_D, /* doubles */
SLU_GE /* general storage */
);
/* Step 4: call SuperLU main routine /*
* --------------------------------- * Step 2: solve
* -------------
*/ */
dgssv(&options, &A, perm, perm_r, &L, &U, &B, &stat, &info); dgstrs(NOTRANS,
&(context->L),
&(context->U),
context->perm_c,
context->perm_r,