![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand * 00004 * Copyright (C) 2009 Sergio Galindo * 00005 * * 00006 * This program is free software: you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation, either version 3 of the License, or * 00009 * any later version. * 00010 * * 00011 * This program is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00018 ************************************************************************/ 00019 00020 #ifndef MECHSYS_MUMPS_H 00021 #define MECHSYS_MUMPS_H 00022 00023 // MUMPS 00024 #ifdef HAS_MPI 00025 extern "C" { 00026 #include "dmumps_c.h" 00027 } 00028 #endif 00029 00030 // MechSys 00031 #include <mechsys/linalg/matvec.h> 00032 #include <mechsys/linalg/sparse_triplet.h> 00033 #include <mechsys/util/fatal.h> 00034 00035 namespace MUMPS 00036 { 00037 00046 inline void Solve (Sparse::Triplet<double,int> & A, Vec_t const & B, Vec_t & X, bool Prod=false) 00047 { 00048 #ifdef HAS_MPI 00049 // collect B from all processors into X==RHS in processor # 0 00050 int neq = A.Rows(); 00051 if (Prod) 00052 { 00053 MPI::COMM_WORLD.Reduce (B.data, X.data, neq, MPI::DOUBLE, MPI::PROD, /*dest*/0); 00054 } 00055 else 00056 { 00057 MPI::COMM_WORLD.Reduce (B.data, X.data, neq, MPI::DOUBLE, MPI::SUM, /*dest*/0); 00058 } 00059 00060 // initialize MUMPS 00061 DMUMPS_STRUC_C ms; 00062 ms.comm_fortran = -987654; 00063 ms.sym = 0; // 0=unsymmetric, 1=sym(pos-def), 2=symmetric(undef) 00064 ms.par = 1; // host also works 00065 ms.job = -1; // initialisation code 00066 dmumps_c (&ms); // do initialize 00067 00068 // set matrix and rhs 00069 A.IncIndices (1); // increment indices since MUMS is 1-based (FORTRAN) 00070 ms.n = neq; 00071 ms.nz_loc = A.Top(); 00072 ms.irn_loc = A.GetAiPtr(); 00073 ms.jcn_loc = A.GetAjPtr(); 00074 ms.a_loc = A.GetAxPtr(); 00075 if (MPI::COMM_WORLD.Get_rank()==0) ms.rhs = X.data; // only proc # 0 needs the RHS 00076 00077 // solve 00078 ms.icntl[1 -1] = -1; // no output messages 00079 ms.icntl[2 -1] = -1; // no warnings 00080 ms.icntl[3 -1] = -1; // no global information 00081 ms.icntl[4 -1] = -1; // message level 00082 ms.icntl[5 -1] = 0; // assembled matrix (needed for distributed matrix) 00083 ms.icntl[7 -1] = 5; // use metis for pivoting 00084 ms.icntl[8 -1] = 0; // no scaling 00085 ms.icntl[18 -1] = 3; // distributed matrix 00086 ms.job = 6; // reorder, factor and solve codes 00087 dmumps_c (&ms); // do solve 00088 int info = ms.info[1-1]; // info code 00089 00090 // finalize MUMPS 00091 ms.job = -2; // finalize code 00092 dmumps_c (&ms); // do finalize 00093 00094 // check for errors 00095 if (info<0) 00096 { 00097 switch (info) 00098 { 00099 case -6: throw new Fatal("MUMPS::Solve: Error # -6: singular matrix"); 00100 case -10: throw new Fatal("MUMPS::Solve: Error # -10: singular matrix"); 00101 case -13: throw new Fatal("MUMPS::Solve: Error # -13: out of memory"); 00102 default: throw new Fatal("MUMPS::Solve: Error # %d: unknown error",info); 00103 } 00104 } 00105 00106 // distribute solution 00107 MPI::COMM_WORLD.Bcast (X.data, neq, MPI::DOUBLE, /*from*/0); 00108 00109 #else 00110 throw new Fatal("MUMPS::Solve: This method requires the flag HAS_MPI"); 00111 #endif 00112 } 00113 00114 }; // namespace MUMPS 00115 00116 #endif // MECHSYS_MUMPS_H