$search
00001 /* 00002 * OpenNL: Numerical Library 00003 * Copyright (C) 2004 Bruno Levy 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program; if not, write to the Free Software 00017 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00018 * 00019 * If you modify this software, you should include a notice giving the 00020 * name of the person performing the modification, the date of modification, 00021 * and the reason for such modification. 00022 * 00023 * Contact: Bruno Levy 00024 * 00025 * levy@loria.fr 00026 * 00027 * ISA Project 00028 * LORIA, INRIA Lorraine, 00029 * Campus Scientifique, BP 239 00030 * 54506 VANDOEUVRE LES NANCY CEDEX 00031 * FRANCE 00032 * 00033 * Note that the GNU General Public License does not permit incorporating 00034 * the Software into proprietary programs. 00035 */ 00036 00037 #include <NL/nl_context.h> 00038 #include <NL/nl_iterative_solvers.h> 00039 #include <NL/nl_preconditioners.h> 00040 #include <NL/nl_superlu.h> 00041 00042 NLContextStruct* nlCurrentContext = NULL ; 00043 00044 void nlMatrixVectorProd_default(NLdouble* x, NLdouble* y) { 00045 nlSparseMatrixMult(&(nlCurrentContext->M), x, y) ; 00046 } 00047 00048 NLContext nlNewContext() { 00049 NLContextStruct* result = NL_NEW(NLContextStruct) ; 00050 result->state = NL_STATE_INITIAL ; 00051 result->solver = NL_BICGSTAB ; 00052 result->max_iterations = 100 ; 00053 result->threshold = 1e-6 ; 00054 result->omega = 1.5 ; 00055 result->row_scaling = 1.0 ; 00056 result->right_hand_side = 0.0 ; 00057 result->inner_iterations = 5 ; 00058 result->matrix_vector_prod = nlMatrixVectorProd_default ; 00059 result->solver_func = nlDefaultSolver ; 00060 nlMakeCurrent(result) ; 00061 return result ; 00062 } 00063 00064 void nlDeleteContext(NLContext context_in) { 00065 NLContextStruct* context = (NLContextStruct*)(context_in) ; 00066 if(nlCurrentContext == context) { 00067 nlCurrentContext = NULL ; 00068 } 00069 if(context->alloc_M) { 00070 nlSparseMatrixDestroy(&context->M) ; 00071 } 00072 if(context->alloc_af) { 00073 nlRowColumnDestroy(&context->af) ; 00074 } 00075 if(context->alloc_al) { 00076 nlRowColumnDestroy(&context->al) ; 00077 } 00078 if(context->alloc_xl) { 00079 nlRowColumnDestroy(&context->xl) ; 00080 } 00081 if(context->alloc_variable) { 00082 NL_DELETE_ARRAY(context->variable) ; 00083 } 00084 if(context->alloc_x) { 00085 NL_DELETE_ARRAY(context->x) ; 00086 } 00087 if(context->alloc_b) { 00088 NL_DELETE_ARRAY(context->b) ; 00089 } 00090 00091 #ifdef NL_PARANOID 00092 NL_CLEAR(NLContextStruct, context) ; 00093 #endif 00094 NL_DELETE(context) ; 00095 } 00096 00097 void nlMakeCurrent(NLContext context) { 00098 nlCurrentContext = (NLContextStruct*)(context) ; 00099 } 00100 00101 NLContext nlGetCurrent() { 00102 return nlCurrentContext ; 00103 } 00104 00105 /************************************************************************/ 00106 /* Finite state automaton */ 00107 00108 void nlCheckState(NLenum state) { 00109 nl_assert(nlCurrentContext->state == state) ; 00110 } 00111 00112 void nlTransition(NLenum from_state, NLenum to_state) { 00113 nlCheckState(from_state) ; 00114 nlCurrentContext->state = to_state ; 00115 } 00116 00117 /************************************************************************/ 00118 /* Default solver */ 00119 00120 static void nlSetupPreconditioner() { 00121 switch(nlCurrentContext->preconditioner) { 00122 case NL_PRECOND_NONE: 00123 nlCurrentContext->precond_vector_prod = NULL ; 00124 break ; 00125 case NL_PRECOND_JACOBI: 00126 nlCurrentContext->precond_vector_prod = nlPreconditioner_Jacobi ; 00127 break ; 00128 case NL_PRECOND_SSOR: 00129 nlCurrentContext->precond_vector_prod = nlPreconditioner_SSOR ; 00130 break ; 00131 default: 00132 nl_assert_not_reached ; 00133 break ; 00134 } 00135 /* Check compatibility between solver and preconditioner */ 00136 if( 00137 nlCurrentContext->solver == NL_BICGSTAB && 00138 nlCurrentContext->preconditioner == NL_PRECOND_SSOR 00139 ) { 00140 nlWarning( 00141 "nlSolve", 00142 "cannot use SSOR preconditioner with non-symmetric matrix, switching to Jacobi" 00143 ) ; 00144 nlCurrentContext->preconditioner = NL_PRECOND_JACOBI ; 00145 nlCurrentContext->precond_vector_prod = nlPreconditioner_Jacobi ; 00146 } 00147 if( 00148 nlCurrentContext->solver == NL_GMRES && 00149 nlCurrentContext->preconditioner != NL_PRECOND_NONE 00150 ) { 00151 nlWarning("nlSolve", "Preconditioner not implemented yet for GMRES") ; 00152 nlCurrentContext->preconditioner = NL_PRECOND_NONE ; 00153 nlCurrentContext->precond_vector_prod = NULL ; 00154 } 00155 if( 00156 nlCurrentContext->solver == NL_SUPERLU_EXT && 00157 nlCurrentContext->preconditioner != NL_PRECOND_NONE 00158 ) { 00159 nlWarning("nlSolve", "Preconditioner not implemented yet for SUPERLU") ; 00160 nlCurrentContext->preconditioner = NL_PRECOND_NONE ; 00161 nlCurrentContext->precond_vector_prod = NULL ; 00162 } 00163 if( 00164 nlCurrentContext->solver == NL_PERM_SUPERLU_EXT && 00165 nlCurrentContext->preconditioner != NL_PRECOND_NONE 00166 ) { 00167 nlWarning("nlSolve", "Preconditioner not implemented yet for PERMSUPERLU") ; 00168 nlCurrentContext->preconditioner = NL_PRECOND_NONE ; 00169 nlCurrentContext->precond_vector_prod = NULL ; 00170 } 00171 if( 00172 nlCurrentContext->solver == NL_SYMMETRIC_SUPERLU_EXT && 00173 nlCurrentContext->preconditioner != NL_PRECOND_NONE 00174 ) { 00175 nlWarning("nlSolve", "Preconditioner not implemented yet for PERMSUPERLU") ; 00176 nlCurrentContext->preconditioner = NL_PRECOND_NONE ; 00177 nlCurrentContext->precond_vector_prod = NULL ; 00178 } 00179 } 00180 00181 NLboolean nlDefaultSolver() { 00182 NLboolean result = NL_TRUE ; 00183 nlSetupPreconditioner() ; 00184 switch(nlCurrentContext->solver) { 00185 case NL_CG: { 00186 if(nlCurrentContext->preconditioner == NL_PRECOND_NONE) { 00187 nlCurrentContext->used_iterations = nlSolve_CG() ; 00188 } else { 00189 nlCurrentContext->used_iterations = nlSolve_CG_precond() ; 00190 } 00191 } break ; 00192 case NL_BICGSTAB: { 00193 if(nlCurrentContext->preconditioner == NL_PRECOND_NONE) { 00194 nlCurrentContext->used_iterations = nlSolve_BICGSTAB() ; 00195 } else { 00196 nlCurrentContext->used_iterations = nlSolve_BICGSTAB_precond() ; 00197 } 00198 } break ; 00199 case NL_GMRES: { 00200 nlCurrentContext->used_iterations = nlSolve_GMRES() ; 00201 } break ; 00202 #ifdef NL_USE_SUPERLU 00203 case NL_SUPERLU_EXT: 00204 case NL_PERM_SUPERLU_EXT: 00205 case NL_SYMMETRIC_SUPERLU_EXT: { 00206 result = nlSolve_SUPERLU() ; 00207 } break ; 00208 #else 00209 case NL_SUPERLU_EXT: 00210 case NL_PERM_SUPERLU_EXT: 00211 case NL_SYMMETRIC_SUPERLU_EXT: { 00212 nl_assert_not_reached ; 00213 } break ; 00214 #endif 00215 default: 00216 nl_assert_not_reached ; 00217 } 00218 return result ; 00219 }