OOFEM  2.4
OOFEM.org - Object Oriented Finite Element Solver
spoolessolver.C
Go to the documentation of this file.
1 /*
2  *
3  * ##### ##### ###### ###### ### ###
4  * ## ## ## ## ## ## ## ### ##
5  * ## ## ## ## #### #### ## # ##
6  * ## ## ## ## ## ## ## ##
7  * ## ## ## ## ## ## ## ##
8  * ##### ##### ## ###### ## ##
9  *
10  *
11  * OOFEM : Object Oriented Finite Element Code
12  *
13  * Copyright (C) 1993 - 2013 Borek Patzak
14  *
15  *
16  *
17  * Czech Technical University, Faculty of Civil Engineering,
18  * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19  *
20  * This library is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU Lesser General Public
22  * License as published by the Free Software Foundation; either
23  * version 2.1 of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28  * Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU Lesser General Public
31  * License along with this library; if not, write to the Free Software
32  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33  */
34 
35 #include "spoolessolver.h"
36 #include "spoolessparsemtrx.h"
37 #include "floatarray.h"
38 #include "verbose.h"
39 #include "timer.h"
40 #include "classfactory.h"
41 
42 namespace oofem {
43 REGISTER_SparseLinSolver(SpoolesSolver, ST_Spooles);
44 
46 {
47  Lhs = NULL;
48  msglvl = 0;
49  msgFile = NULL;
50  msgFileCloseFlag = 0;
51 
52  frontmtx = NULL;
53  oldToNewIV = newToOldIV = NULL;
54  frontETree = NULL;
55  adjIVL = symbfacIVL = NULL;
56  mtxmanager = NULL;
57  graph = NULL;
58 }
59 
60 
62 {
63  if ( msgFileCloseFlag ) {
64  fclose(msgFile);
65  }
66 
67  if ( frontmtx ) {
68  FrontMtx_free(frontmtx);
69  }
70 
71  if ( newToOldIV ) {
72  IV_free(newToOldIV);
73  }
74 
75  if ( oldToNewIV ) {
76  IV_free(oldToNewIV);
77  }
78 
79  if ( frontETree ) {
80  ETree_free(frontETree);
81  }
82 
83  if ( symbfacIVL ) {
84  IVL_free(symbfacIVL);
85  }
86 
87  if ( mtxmanager ) {
88  SubMtxManager_free(mtxmanager);
89  }
90 
91  if ( graph ) {
92  Graph_free(graph);
93  }
94 }
95 
98 {
99  IRResultType result; // Required by IR_GIVE_FIELD macro
100 
101  int val;
102  std :: string msgFileName;
103 
104  val = -3;
106  msglvl = val;
108  if ( !msgFileName.empty() ) {
109  msgFile = fopen(msgFileName.c_str(), "w");
110  msgFileCloseFlag = 1;
111  } else {
112  msgFile = stdout;
113  msgFileCloseFlag = 0;
114  }
115 
116  return IRRT_OK;
117 }
118 
119 
120 NM_Status
122 {
123  int errorValue, mtxType, symmetryflag;
124  int seed = 30145, pivotingflag = 0;
125  int *oldToNew, *newToOld;
126  double droptol = 0.0, tau = 1.e300;
127  double cpus [ 10 ];
128  int stats [ 20 ];
129 
130  ChvManager *chvmanager;
131  Chv *rootchv;
132  InpMtx *mtxA;
133  DenseMtx *mtxY, *mtxX;
134 
135  x.resize(b.giveSize();
136 
137  Timer timer;
138  timer.startTimer();
139 
140  SpoolesSparseMtrx *As = dynamic_cast< SpoolesSparseMtrx * >(&A);
141  if ( !As ) {
142  OOFEM_ERROR("SpoolesSparseMtrx Expected");
143  }
144 
145  mtxA = As->giveInpMtrx();
146  mtxType = As->giveValueType();
147  symmetryflag = As->giveSymmetryFlag();
148 
149  int i;
150  int neqns = A->giveNumberOfRows();
151  int nrhs = 1;
152  /* convert right-hand side to DenseMtx */
153  mtxY = DenseMtx_new();
154  DenseMtx_init(mtxY, mtxType, 0, 0, neqns, nrhs, 1, neqns);
155  DenseMtx_zero(mtxY);
156  for ( i = 0; i < neqns; i++ ) {
157  DenseMtx_setRealEntry( mtxY, i, 0, b->at(i + 1) );
158  }
159 
160  if ( ( Lhs != &A ) || ( this->lhsVersion != A.giveVersion() ) ) {
161  //
162  // lhs has been changed -> new factorization
163  //
165  Lhs = &A;
166  this->lhsVersion = A.giveVersion();
167 
168  if ( frontmtx ) {
169  FrontMtx_free(frontmtx);
170  }
171 
172  if ( newToOldIV ) {
173  IV_free(newToOldIV);
174  }
175 
176  if ( oldToNewIV ) {
177  IV_free(oldToNewIV);
178  }
179 
180  if ( frontETree ) {
181  ETree_free(frontETree);
182  }
183 
184  if ( symbfacIVL ) {
185  IVL_free(symbfacIVL);
186  }
187 
188  if ( mtxmanager ) {
189  SubMtxManager_free(mtxmanager);
190  }
191 
192  if ( graph ) {
193  Graph_free(graph);
194  }
195 
196  /*
197  * -------------------------------------------------
198  * STEP 3 : find a low-fill ordering
199  * (1) create the Graph object
200  * (2) order the graph using multiple minimum degree
201  * -------------------------------------------------
202  */
203  int nedges;
204  graph = Graph_new();
205  adjIVL = InpMtx_fullAdjacency(mtxA);
206  nedges = IVL_tsize(adjIVL);
207  Graph_init2(graph, 0, neqns, 0, nedges, neqns, nedges, adjIVL,
208  NULL, NULL);
209  if ( msglvl > 2 ) {
210  fprintf(msgFile, "\n\n graph of the input matrix");
211  Graph_writeForHumanEye(graph, msgFile);
212  fflush(msgFile);
213  }
214 
215  frontETree = orderViaMMD(graph, seed, msglvl, msgFile);
216  if ( msglvl > 0 ) {
217  fprintf(msgFile, "\n\n front tree from ordering");
218  ETree_writeForHumanEye(frontETree, msgFile);
219  fflush(msgFile);
220  }
221 
222  /*
223  * ----------------------------------------------------
224  * STEP 4: get the permutation, permute the front tree,
225  * permute the matrix and right hand side, and
226  * get the symbolic factorization
227  * ----------------------------------------------------
228  */
229  oldToNewIV = ETree_oldToNewVtxPerm(frontETree);
230  oldToNew = IV_entries(oldToNewIV);
231  newToOldIV = ETree_newToOldVtxPerm(frontETree);
232  newToOld = IV_entries(newToOldIV);
233  ETree_permuteVertices(frontETree, oldToNewIV);
234  InpMtx_permute(mtxA, oldToNew, oldToNew);
235  if ( symmetryflag == SPOOLES_SYMMETRIC ||
236  symmetryflag == SPOOLES_HERMITIAN ) {
237  InpMtx_mapToUpperTriangle(mtxA);
238  }
239 
240  InpMtx_changeCoordType(mtxA, INPMTX_BY_CHEVRONS);
241  InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS);
242  symbfacIVL = SymbFac_initFromInpMtx(frontETree, mtxA);
243  if ( msglvl > 2 ) {
244  fprintf(msgFile, "\n\n old-to-new permutation vector");
245  IV_writeForHumanEye(oldToNewIV, msgFile);
246  fprintf(msgFile, "\n\n new-to-old permutation vector");
247  IV_writeForHumanEye(newToOldIV, msgFile);
248  fprintf(msgFile, "\n\n front tree after permutation");
249  ETree_writeForHumanEye(frontETree, msgFile);
250  fprintf(msgFile, "\n\n input matrix after permutation");
251  InpMtx_writeForHumanEye(mtxA, msgFile);
252  fprintf(msgFile, "\n\n symbolic factorization");
253  IVL_writeForHumanEye(symbfacIVL, msgFile);
254  fflush(msgFile);
255  }
256 
257  Tree_writeToFile(frontETree->tree, ( char * ) "haggar.treef");
258  /*--------------------------------------------------------------------*/
259  /*
260  * ------------------------------------------
261  * STEP 5: initialize the front matrix object
262  * ------------------------------------------
263  */
264  frontmtx = FrontMtx_new();
265  mtxmanager = SubMtxManager_new();
266  SubMtxManager_init(mtxmanager, NO_LOCK, 0);
267  FrontMtx_init(frontmtx, frontETree, symbfacIVL, mtxType, symmetryflag,
268  FRONTMTX_DENSE_FRONTS, pivotingflag, NO_LOCK, 0, NULL,
270  /*--------------------------------------------------------------------*/
271  /*
272  * -----------------------------------------
273  * STEP 6: compute the numeric factorization
274  * -----------------------------------------
275  */
276  chvmanager = ChvManager_new();
277  ChvManager_init(chvmanager, NO_LOCK, 1);
278  DVfill(10, cpus, 0.0);
279  IVfill(20, stats, 0);
280  rootchv = FrontMtx_factorInpMtx(frontmtx, mtxA, tau, droptol,
281  chvmanager, & errorValue, cpus, stats, msglvl, msgFile);
282  ChvManager_free(chvmanager);
283  if ( msglvl > 0 ) {
284  fprintf(msgFile, "\n\n factor matrix");
285  FrontMtx_writeForHumanEye(frontmtx, msgFile);
286  fflush(msgFile);
287  }
288 
289  if ( rootchv != NULL ) {
290  fprintf(msgFile, "\n\n matrix found to be singular\n");
291  exit(-1);
292  }
293 
294  if ( errorValue >= 0 ) {
295  fprintf(msgFile, "\n\n error encountered at front %d", errorValue);
296  exit(-1);
297  }
298 
299  /*--------------------------------------------------------------------*/
300  /*
301  * --------------------------------------
302  * STEP 7: post-process the factorization
303  * --------------------------------------
304  */
305  FrontMtx_postProcess(frontmtx, msglvl, msgFile);
306  if ( msglvl > 2 ) {
307  fprintf(msgFile, "\n\n factor matrix after post-processing");
308  FrontMtx_writeForHumanEye(frontmtx, msgFile);
309  fflush(msgFile);
310  }
311 
312  /*--------------------------------------------------------------------*/
313  }
314 
315  /*
316  * ----------------------------------------------------
317  * STEP 4: permute the right hand side
318  * ----------------------------------------------------
319  */
320  DenseMtx_permuteRows(mtxY, oldToNewIV);
321  if ( msglvl > 2 ) {
322  fprintf(msgFile, "\n\n right hand side matrix after permutation");
323  DenseMtx_writeForHumanEye(mtxY, msgFile);
324  }
325 
326  /*
327  * -------------------------------
328  * STEP 8: solve the linear system
329  * -------------------------------
330  */
331  mtxX = DenseMtx_new();
332  DenseMtx_init(mtxX, mtxType, 0, 0, neqns, nrhs, 1, neqns);
333  DenseMtx_zero(mtxX);
334  FrontMtx_solve(frontmtx, mtxX, mtxY, mtxmanager,
335  cpus, msglvl, msgFile);
336  if ( msglvl > 2 ) {
337  fprintf(msgFile, "\n\n solution matrix in new ordering");
338  DenseMtx_writeForHumanEye(mtxX, msgFile);
339  fflush(msgFile);
340  }
341 
342  /*--------------------------------------------------------------------*/
343  /*
344  * -------------------------------------------------------
345  * STEP 9: permute the solution into the original ordering
346  * -------------------------------------------------------
347  */
348  DenseMtx_permuteRows(mtxX, newToOldIV);
349  if ( msglvl > 0 ) {
350  fprintf(msgFile, "\n\n solution matrix in original ordering");
351  DenseMtx_writeForHumanEye(mtxX, msgFile);
352  fflush(msgFile);
353  }
354 
355  // DenseMtx_writeForMatlab(mtxX, "x", msgFile) ;
356  /*--------------------------------------------------------------------*/
357  /* fetch data to oofem vectors */
358  double *xptr = x.givePointer();
359  for ( i = 0; i < neqns; i++ ) {
360  DenseMtx_realEntry(mtxX, i, 0, xptr + i);
361  // printf ("x(%d) = %e\n", i+1, *(xptr+i));
362  }
363 
364  // DenseMtx_copyRowIntoVector(mtxX, 0, x->givePointer());
365 
366  timer.stopTimer();
367  OOFEM_LOG_DEBUG( "SpoolesSolver info: user time consumed by solution: %.2fs\n", timer.getUtime() );
368 
369  /*
370  * -----------
371  * free memory
372  * -----------
373  */
374  DenseMtx_free(mtxX);
375  DenseMtx_free(mtxY);
376  /*--------------------------------------------------------------------*/
377  return ( 1 );
378 }
379 } // end namespace oofem
virtual ~SpoolesSolver()
Destructor.
Definition: spoolessolver.C:61
virtual NM_Status solve(SparseMtrx &A, FloatArray &b, FloatArray &x)
Solves the given linear system by LDL^T factorization.
#define _IFT_SpoolesSolver_msglvl
Definition: spoolessolver.h:50
Class and object Domain.
Definition: domain.h:115
#define _IFT_SpoolesSolver_msgfile
Definition: spoolessolver.h:51
Base class for all matrices stored in sparse format.
Definition: sparsemtrx.h:60
double & at(int i)
Coefficient access function.
Definition: floatarray.h:131
This base class is an abstraction for all numerical methods solving sparse linear system of equations...
This class provides an sparse matrix interface to SPOOLES InpMtrx.
virtual IRResultType initializeFrom(InputRecord *ir)
Initializes receiver from given record.
Definition: spoolessolver.C:97
unsigned long NM_Status
Mask defining NumMetod Status; which can be asked after finishing computation by Numerical Method...
Definition: nmstatus.h:44
#define OOFEM_LOG_DEBUG(...)
Definition: logger.h:128
SparseMtrx * Lhs
Last mapped LHS matrix.
Definition: spoolessolver.h:67
SparseMtrx::SparseMtrxVersionType lhsVersion
Last mapped matrix version.
Definition: spoolessolver.h:69
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition: sparsemtrx.h:114
#define OOFEM_ERROR(...)
Definition: error.h:61
Initializes the variable VERBOSE, in order to get a few intermediate messages on screen: beginning an...
Class representing vector of real numbers.
Definition: floatarray.h:82
IRResultType
Type defining the return values of InputRecord reading operations.
Definition: irresulttype.h:47
SpoolesSolver(Domain *d, EngngModel *m)
Constructor.
Definition: spoolessolver.C:45
Class representing the general Input Record.
Definition: inputrecord.h:101
REGISTER_SparseLinSolver(IMLSolver, ST_IML)
Definition: imlsolver.C:56
Class implementing single timer, providing wall clock and user time capabilities. ...
Definition: timer.h:46
const double * givePointer() const
Gives the pointer to the raw data, breaking encapsulation.
Definition: floatarray.h:469
Abstract base class representing the "problem" under consideration.
Definition: engngm.h:181
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Macro facilitating the use of input record reading methods.
Definition: inputrecord.h:78
int giveSize() const
Returns the size of receiver.
Definition: floatarray.h:218
the oofem namespace is to define a context or scope in which all oofem names are defined.
SubMtxManager * mtxmanager
Definition: spoolessolver.h:78
void startTimer()
Definition: timer.C:69
double getUtime()
Returns total user time elapsed in seconds.
Definition: timer.C:105
void stopTimer()
Definition: timer.C:77
void resize(int s)
Resizes receiver towards requested size.
Definition: floatarray.C:631
SparseMtrxVersionType giveVersion()
Return receiver version.
Definition: sparsemtrx.h:94

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Tue Jan 2 2018 20:07:31 for OOFEM by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2011