OOFEM 3.0
Loading...
Searching...
No Matches
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 - 2025 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
42namespace oofem {
44
45SpoolesSolver :: SpoolesSolver(Domain *d, EngngModel *m) : SparseLinearSystemNM(d, m)
46{
47 Lhs = NULL;
48 msglvl = 0;
49 msgFile = NULL;
51
52 frontmtx = NULL;
53 oldToNewIV = newToOldIV = NULL;
54 frontETree = NULL;
55 adjIVL = symbfacIVL = NULL;
56 mtxmanager = NULL;
57 graph = NULL;
58}
59
60
61SpoolesSolver :: ~SpoolesSolver()
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
96void
97SpoolesSolver :: initializeFrom(InputRecord &ir)
98{
99 int val;
100 std :: string msgFileName;
101
102 val = -3;
104 msglvl = val;
106 if ( !msgFileName.empty() ) {
107 msgFile = fopen(msgFileName.c_str(), "w");
109 } else {
110 msgFile = stdout;
112 }
113}
114
115
117SpoolesSolver :: solve(SparseMtrx &A, FloatArray &b, FloatArray &x)
118{
119 int errorValue, mtxType, symmetryflag;
120 int seed = 30145, pivotingflag = 0;
121 int *oldToNew, *newToOld;
122 double droptol = 0.0, tau = 1.e300;
123 double cpus [ 10 ];
124 int stats [ 20 ];
125
126 ChvManager *chvmanager;
127 Chv *rootchv;
128 InpMtx *mtxA;
129 DenseMtx *mtxY, *mtxX;
130
131 x.resize(b.giveSize());
132
133 Timer timer;
134 timer.startTimer();
135
136 SpoolesSparseMtrx *As = dynamic_cast< SpoolesSparseMtrx * >(&A);
137 if ( !As ) {
138 OOFEM_ERROR("SpoolesSparseMtrx Expected");
139 }
140
141 mtxA = As->giveInpMtrx();
142 mtxType = As->giveValueType();
143 symmetryflag = As->giveSymmetryFlag();
144
145 int i;
146 int neqns = A.giveNumberOfRows();
147 int nrhs = 1;
148 /* convert right-hand side to DenseMtx */
149 mtxY = DenseMtx_new();
150 DenseMtx_init(mtxY, mtxType, 0, 0, neqns, nrhs, 1, neqns);
151 DenseMtx_zero(mtxY);
152 for ( i = 0; i < neqns; i++ ) {
153 DenseMtx_setRealEntry( mtxY, i, 0, b.at(i + 1) );
154 }
155
156 if ( ( Lhs != &A ) || ( this->lhsVersion != A.giveVersion() ) ) {
157 //
158 // lhs has been changed -> new factorization
159 //
161 Lhs = &A;
162 this->lhsVersion = A.giveVersion();
163
164 if ( frontmtx ) {
165 FrontMtx_free(frontmtx);
166 }
167
168 if ( newToOldIV ) {
169 IV_free(newToOldIV);
170 }
171
172 if ( oldToNewIV ) {
173 IV_free(oldToNewIV);
174 }
175
176 if ( frontETree ) {
177 ETree_free(frontETree);
178 }
179
180 if ( symbfacIVL ) {
181 IVL_free(symbfacIVL);
182 }
183
184 if ( mtxmanager ) {
185 SubMtxManager_free(mtxmanager);
186 }
187
188 if ( graph ) {
189 Graph_free(graph);
190 }
191
192 /*
193 * -------------------------------------------------
194 * STEP 3 : find a low-fill ordering
195 * (1) create the Graph object
196 * (2) order the graph using multiple minimum degree
197 * -------------------------------------------------
198 */
199 int nedges;
200 graph = Graph_new();
201 adjIVL = InpMtx_fullAdjacency(mtxA);
202 nedges = IVL_tsize(adjIVL);
203 Graph_init2(graph, 0, neqns, 0, nedges, neqns, nedges, adjIVL,
204 NULL, NULL);
205 if ( msglvl > 2 ) {
206 fprintf(msgFile, "\n\n graph of the input matrix");
207 Graph_writeForHumanEye(graph, msgFile);
208 fflush(msgFile);
209 }
210
211 frontETree = orderViaMMD(graph, seed, msglvl, msgFile);
212 if ( msglvl > 0 ) {
213 fprintf(msgFile, "\n\n front tree from ordering");
214 ETree_writeForHumanEye(frontETree, msgFile);
215 fflush(msgFile);
216 }
217
218 /*
219 * ----------------------------------------------------
220 * STEP 4: get the permutation, permute the front tree,
221 * permute the matrix and right hand side, and
222 * get the symbolic factorization
223 * ----------------------------------------------------
224 */
225 oldToNewIV = ETree_oldToNewVtxPerm(frontETree);
226 oldToNew = IV_entries(oldToNewIV);
227 newToOldIV = ETree_newToOldVtxPerm(frontETree);
228 newToOld = IV_entries(newToOldIV);
229 ETree_permuteVertices(frontETree, oldToNewIV);
230 InpMtx_permute(mtxA, oldToNew, oldToNew);
231 if ( symmetryflag == SPOOLES_SYMMETRIC ||
232 symmetryflag == SPOOLES_HERMITIAN ) {
233 InpMtx_mapToUpperTriangle(mtxA);
234 }
235
236 InpMtx_changeCoordType(mtxA, INPMTX_BY_CHEVRONS);
237 InpMtx_changeStorageMode(mtxA, INPMTX_BY_VECTORS);
238 symbfacIVL = SymbFac_initFromInpMtx(frontETree, mtxA);
239 if ( msglvl > 2 ) {
240 fprintf(msgFile, "\n\n old-to-new permutation vector");
241 IV_writeForHumanEye(oldToNewIV, msgFile);
242 fprintf(msgFile, "\n\n new-to-old permutation vector");
243 IV_writeForHumanEye(newToOldIV, msgFile);
244 fprintf(msgFile, "\n\n front tree after permutation");
245 ETree_writeForHumanEye(frontETree, msgFile);
246 fprintf(msgFile, "\n\n input matrix after permutation");
247 InpMtx_writeForHumanEye(mtxA, msgFile);
248 fprintf(msgFile, "\n\n symbolic factorization");
249 IVL_writeForHumanEye(symbfacIVL, msgFile);
250 fflush(msgFile);
251 }
252
253 Tree_writeToFile(frontETree->tree, ( char * ) "haggar.treef");
254 /*--------------------------------------------------------------------*/
255 /*
256 * ------------------------------------------
257 * STEP 5: initialize the front matrix object
258 * ------------------------------------------
259 */
260 frontmtx = FrontMtx_new();
261 mtxmanager = SubMtxManager_new();
262 SubMtxManager_init(mtxmanager, NO_LOCK, 0);
263 FrontMtx_init(frontmtx, frontETree, symbfacIVL, mtxType, symmetryflag,
264 FRONTMTX_DENSE_FRONTS, pivotingflag, NO_LOCK, 0, NULL,
266 /*--------------------------------------------------------------------*/
267 /*
268 * -----------------------------------------
269 * STEP 6: compute the numeric factorization
270 * -----------------------------------------
271 */
272 chvmanager = ChvManager_new();
273 ChvManager_init(chvmanager, NO_LOCK, 1);
274 DVfill(10, cpus, 0.0);
275 IVfill(20, stats, 0);
276 rootchv = FrontMtx_factorInpMtx(frontmtx, mtxA, tau, droptol,
277 chvmanager, & errorValue, cpus, stats, msglvl, msgFile);
278 ChvManager_free(chvmanager);
279 if ( msglvl > 0 ) {
280 fprintf(msgFile, "\n\n factor matrix");
281 FrontMtx_writeForHumanEye(frontmtx, msgFile);
282 fflush(msgFile);
283 }
284
285 if ( rootchv != NULL ) {
286 fprintf(msgFile, "\n\n matrix found to be singular\n");
287 return CR_FAILED;
288 }
289
290 if ( errorValue >= 0 ) {
291 fprintf(msgFile, "\n\n error encountered at front %d", errorValue);
292 return CR_FAILED;
293 }
294
295 /*--------------------------------------------------------------------*/
296 /*
297 * --------------------------------------
298 * STEP 7: post-process the factorization
299 * --------------------------------------
300 */
301 FrontMtx_postProcess(frontmtx, msglvl, msgFile);
302 if ( msglvl > 2 ) {
303 fprintf(msgFile, "\n\n factor matrix after post-processing");
304 FrontMtx_writeForHumanEye(frontmtx, msgFile);
305 fflush(msgFile);
306 }
307
308 /*--------------------------------------------------------------------*/
309 }
310
311 /*
312 * ----------------------------------------------------
313 * STEP 4: permute the right hand side
314 * ----------------------------------------------------
315 */
316 DenseMtx_permuteRows(mtxY, oldToNewIV);
317 if ( msglvl > 2 ) {
318 fprintf(msgFile, "\n\n right hand side matrix after permutation");
319 DenseMtx_writeForHumanEye(mtxY, msgFile);
320 }
321
322 /*
323 * -------------------------------
324 * STEP 8: solve the linear system
325 * -------------------------------
326 */
327 mtxX = DenseMtx_new();
328 DenseMtx_init(mtxX, mtxType, 0, 0, neqns, nrhs, 1, neqns);
329 DenseMtx_zero(mtxX);
330 FrontMtx_solve(frontmtx, mtxX, mtxY, mtxmanager,
331 cpus, msglvl, msgFile);
332 if ( msglvl > 2 ) {
333 fprintf(msgFile, "\n\n solution matrix in new ordering");
334 DenseMtx_writeForHumanEye(mtxX, msgFile);
335 fflush(msgFile);
336 }
337
338 /*--------------------------------------------------------------------*/
339 /*
340 * -------------------------------------------------------
341 * STEP 9: permute the solution into the original ordering
342 * -------------------------------------------------------
343 */
344 DenseMtx_permuteRows(mtxX, newToOldIV);
345 if ( msglvl > 0 ) {
346 fprintf(msgFile, "\n\n solution matrix in original ordering");
347 DenseMtx_writeForHumanEye(mtxX, msgFile);
348 fflush(msgFile);
349 }
350
351 // DenseMtx_writeForMatlab(mtxX, "x", msgFile) ;
352 /*--------------------------------------------------------------------*/
353 /* fetch data to oofem vectors */
354 double *xptr = x.givePointer();
355 for ( i = 0; i < neqns; i++ ) {
356 DenseMtx_realEntry(mtxX, i, 0, xptr + i);
357 // printf ("x(%d) = %e\n", i+1, *(xptr+i));
358 }
359
360 // DenseMtx_copyRowIntoVector(mtxX, 0, x->givePointer());
361
362 timer.stopTimer();
363 OOFEM_LOG_DEBUG( "SpoolesSolver info: user time consumed by solution: %.2fs\n", timer.getUtime() );
364
365 /*
366 * -----------
367 * free memory
368 * -----------
369 */
370 DenseMtx_free(mtxX);
371 DenseMtx_free(mtxY);
372 /*--------------------------------------------------------------------*/
373 return ( CR_CONVERGED );
374}
375} // end namespace oofem
#define REGISTER_SparseLinSolver(class, type)
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
const double * givePointer() const
Definition floatarray.h:506
SparseLinearSystemNM(Domain *d, EngngModel *m)
Constructor.
SparseMtrxVersionType giveVersion()
Return receiver version.
Definition sparsemtrx.h:94
int giveNumberOfRows() const
Returns number of rows of receiver.
Definition sparsemtrx.h:114
SparseMtrx::SparseMtrxVersionType lhsVersion
Last mapped matrix version.
SparseMtrx * Lhs
Last mapped LHS matrix.
SubMtxManager * mtxmanager
double getUtime()
Returns total user time elapsed in seconds.
Definition timer.C:105
void startTimer()
Definition timer.C:69
void stopTimer()
Definition timer.C:77
#define OOFEM_ERROR(...)
Definition error.h:79
#define IR_GIVE_OPTIONAL_FIELD(__ir, __value, __id)
Definition inputrecord.h:75
#define OOFEM_LOG_DEBUG(...)
Definition logger.h:144
#define _IFT_SpoolesSolver_msgfile
#define _IFT_SpoolesSolver_msglvl

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011