1 /*
2 XLiFE++ is an extended library of finite elements written in C++
3 Copyright (C) 2014 Lunéville, Eric; Kielbasiewicz, Nicolas; Lafranche, Yvon; Nguyen, Manh-Ha; Chambeyron, Colin
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 /*!
18 \file TermMatrix.cpp
19 \author E. Lunéville
20 \authors D. Martin, E. Lunéville
21 \since 03 apr 2012
22 \date 20 mar 2013
23
24 \brief Implementation of xlifepp::TermMatrix class members
25 */
26
27 #include "TermMatrix.hpp"
28
29 namespace xlifepp
30 {
31
32 //===============================================================================
33 //member functions of TermMatrix class
34 //===============================================================================
35 //constructors
TermMatrix(const string_t & na)36 TermMatrix::TermMatrix(const string_t& na)
37 {
38 termType_ = _termMatrix;
39 name_ = na;
40 entries_p = 0;
41 scalar_entries_p=0;
42 rhs_matrix_p=0;
43 constraints_u_p = 0;
44 constraints_v_p = 0;
45 }
46
TermMatrix(const BilinearForm & blf,const string_t & na,bool noass)47 TermMatrix::TermMatrix(const BilinearForm& blf, const string_t& na, bool noass)
48 {
49 initFromBlf(blf, na, noass);
50 constraints_u_p = 0;
51 constraints_v_p = 0;
52 }
53
54 //! constructor with no essential boundary conditions
TermMatrix(const BilinearForm & blf,const string_t & na)55 TermMatrix::TermMatrix(const BilinearForm& blf, const string_t& na)
56 {
57 std::vector<TermOption> opts;
58 build(blf,0,0,ReductionMethod(_noReduction),opts,na);
59 }
60
TermMatrix(const BilinearForm & blf,TermOption op1,const string_t & na)61 TermMatrix::TermMatrix(const BilinearForm& blf, TermOption op1, const string_t& na)
62 {
63 std::vector<TermOption> opts(1,op1);
64 build(blf,0,0,ReductionMethod(_noReduction),opts,na);
65 }
66
TermMatrix(const BilinearForm & blf,TermOption op1,TermOption op2,const string_t & na)67 TermMatrix::TermMatrix(const BilinearForm& blf, TermOption op1, TermOption op2, const string_t& na)
68 {
69 std::vector<TermOption> opts(2,op1); opts[1]=op2;
70 build(blf,0,0,ReductionMethod(_noReduction),opts,na);
71 }
72
TermMatrix(const BilinearForm & blf,TermOption op1,TermOption op2,TermOption op3,const string_t & na)73 TermMatrix::TermMatrix(const BilinearForm& blf, TermOption op1, TermOption op2, TermOption op3, const string_t& na)
74 {
75 std::vector<TermOption> opts(3,op1); opts[1]=op2; opts[2]=op3;
76 build(blf,0,0,ReductionMethod(_noReduction),opts,na);
77 }
78
79 //! constructor with one essential boundary conditions
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,const string_t & na)80 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, const string_t& na)
81 {
82 std::vector<TermOption> opts;
83 build(blf,&ec,0,ReductionMethod(_pseudoReduction),opts,na);
84 }
85
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,TermOption op1,const string_t & na)86 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, TermOption op1, const string_t& na)
87 {
88 std::vector<TermOption> opts(1,op1);
89 build(blf,&ec,0,ReductionMethod(_pseudoReduction),opts,na);
90 }
91
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,TermOption op1,TermOption op2,const string_t & na)92 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, TermOption op1, TermOption op2, const string_t& na)
93 {
94 std::vector<TermOption> opts(2,op1); opts[1]=op2;
95 build(blf,&ec,0,ReductionMethod(_pseudoReduction),opts,na);
96 }
97
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,TermOption op1,TermOption op2,TermOption op3,const string_t & na)98 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, TermOption op1, TermOption op2, TermOption op3, const string_t& na)
99 {
100 std::vector<TermOption> opts(3,op1); opts[1]=op2; opts[2]=op3;
101 build(blf,&ec,0,ReductionMethod(_pseudoReduction),opts,na);
102 }
103
104 //! constructor with essential boundary condition and explicit reduction method
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,const ReductionMethod & rm,const string_t & na)105 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, const ReductionMethod& rm, const string_t& na)
106 {
107 std::vector<TermOption> opts;
108 build(blf,&ec,0,rm,opts,na);
109 }
110
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,const ReductionMethod & rm,TermOption op1,const string_t & na)111 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, const ReductionMethod& rm, TermOption op1, const string_t& na)
112 {
113 std::vector<TermOption> opts(1,op1);
114 build(blf,&ec,0,rm,opts,na);
115 }
116
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,const ReductionMethod & rm,TermOption op1,TermOption op2,const string_t & na)117 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, const ReductionMethod& rm, TermOption op1, TermOption op2, const string_t& na)
118 {
119 std::vector<TermOption> opts(2,op1); opts[1]=op2;
120 build(blf,&ec,0,rm,opts,na);
121 }
122
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,const ReductionMethod & rm,TermOption op1,TermOption op2,TermOption op3,const string_t & na)123 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, const ReductionMethod& rm, TermOption op1, TermOption op2, TermOption op3, const string_t& na)
124 {
125 std::vector<TermOption> opts(3,op1); opts[1]=op2; opts[2]=op3;
126 build(blf,&ec,0,rm,opts,na);
127 }
128
129 //! constructor with two essential boundary conditions
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,const string_t & na)130 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, const string_t& na)
131 {
132 std::vector<TermOption> opts;
133 build(blf,&ecu,&ecv,ReductionMethod(_pseudoReduction),opts,na);
134 }
135
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,TermOption op1,const string_t & na)136 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, TermOption op1, const string_t& na)
137 {
138 std::vector<TermOption> opts(1,op1);
139 build(blf,&ecu,&ecv,ReductionMethod(_pseudoReduction),opts,na);
140 }
141
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,TermOption op1,TermOption op2,const string_t & na)142 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, TermOption op1, TermOption op2, const string_t& na)
143 {
144 std::vector<TermOption> opts(2,op1); opts[1]=op2;
145 build(blf,&ecu,&ecv,ReductionMethod(_pseudoReduction),opts,na);
146 }
147
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,TermOption op1,TermOption op2,TermOption op3,const string_t & na)148 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, TermOption op1, TermOption op2, TermOption op3, const string_t& na)
149 {
150 std::vector<TermOption> opts(3,op1); opts[1]=op2; opts[2]=op3;
151 build(blf,&ecu,&ecv,ReductionMethod(_pseudoReduction),opts,na);
152 }
153
154 //! constructor with two essential boundary conditions and explicit reduction method
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,const ReductionMethod & rm,const string_t & na)155 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, const ReductionMethod& rm, const string_t& na)
156 {
157 std::vector<TermOption> opts;
158 build(blf,&ecu,&ecv,rm,opts,na);
159 }
160
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,const ReductionMethod & rm,TermOption op1,const string_t & na)161 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, const ReductionMethod& rm, TermOption op1, const string_t& na)
162 {
163 std::vector<TermOption> opts(1,op1);
164 build(blf,&ecu,&ecv,rm,opts,na);
165 }
166
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,const ReductionMethod & rm,TermOption op1,TermOption op2,const string_t & na)167 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, const ReductionMethod& rm,TermOption op1, TermOption op2, const string_t& na)
168 {
169 std::vector<TermOption> opts(2,op1); opts[1]=op2;
170 build(blf,&ecu,&ecv,rm,opts,na);
171 }
172
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,const ReductionMethod & rm,TermOption op1,TermOption op2,TermOption op3,const string_t & na)173 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, const ReductionMethod& rm, TermOption op1, TermOption op2, TermOption op3, const string_t& na)
174 {
175 std::vector<TermOption> opts(3,op1); opts[1]=op2; opts[2]=op3;
176 build(blf,&ecu,&ecv,rm,opts,na);
177 }
178
179
180 //! effective constructor
build(const BilinearForm & blf,const EssentialConditions * ecu,const EssentialConditions * ecv,const ReductionMethod & rm,const std::vector<TermOption> & opts,const string_t & na)181 void TermMatrix::build(const BilinearForm& blf, const EssentialConditions* ecu, const EssentialConditions* ecv, const ReductionMethod& rm,
182 const std::vector<TermOption>& opts, const string_t& na)
183 {
184 std::vector<TermOption>::const_iterator ito=opts.begin();
185 computingInfo_.isComputed=false;
186 computingInfo_.noAssembly=false;
187 bool toCompute=true, toAssemble=true;
188 StorageType st=_noStorage; AccessType ac=_noAccess;
189 SymType sym=_undefSymmetry;
190 computingInfo_.reductionMethod = rm;
191 for (; ito!=opts.end(); ++ito)
192 {
193 switch (*ito)
194 {
195 case _compute : break;
196 case _notCompute : toCompute=false; break;
197 case _assembled : break;
198 case _unassembled : toAssemble=false; break;
199 case _csRowStorage : st=_cs; ac=_row; break;
200 case _csColStorage : st=_cs; ac=_col; break;
201 case _csDualStorage: st=_cs; ac=_dual; break;
202 case _csSymStorage : st=_cs; ac=_sym; break;
203 case _denseRowStorage : st=_dense; ac=_row; break;
204 case _denseColStorage : st=_dense; ac=_col; break;
205 case _denseDualStorage: st=_dense; ac=_dual; break;
206 case _skylineSymStorage : st=_skyline; ac=_sym; break;
207 case _skylineDualStorage: st=_skyline; ac=_dual; break;
208 case _nonSymmetricMatrix : sym=_noSymmetry; break;
209 case _symmetricMatrix : sym=_symmetric; break;
210 case _selfAdjointMatrix : sym=_selfAdjoint; break;
211 case _skewSymmetricMatrix: sym=_skewSymmetric; break;
212 case _skewAdjointMatrix : sym=_skewAdjoint; break;
213 case _pseudoReductionMethod : computingInfo_.reductionMethod.method=_pseudoReduction; break;
214 case _realReductionMethod : computingInfo_.reductionMethod.method=_realReduction; break;
215 case _penalizationReductionMethod : computingInfo_.reductionMethod.method=_penalizationReduction; break;
216 default:
217 where("TermMatrix::build(...)");
218 error("undef_option");
219 }
220 }
221
222 initFromBlf(blf, na, !toAssemble);
223 constraints_u_p = 0;
224 if (ecu!=0) constraints_u_p = new SetOfConstraints(buildConstraints(*ecu));
225 constraints_v_p = constraints_u_p;
226 if (ecv!=0 && ecv!=ecu) constraints_v_p = new SetOfConstraints(buildConstraints(*ecv));
227 if (sym!=_undefSymmetry)
228 {
229 where("TermMatrix::build(...)");
230 error("symmetry_not_handled", words("symmetry", sym));
231 }
232 if (st!=_noStorage) setStorage(st,ac);
233 if (toCompute) compute();
234 }
235
TermMatrix(const BilinearForm & blf,const EssentialConditions & ec,const string_t & na,bool noass)236 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ec, const string_t& na, bool noass)
237 {
238 initFromBlf(blf, na, noass);
239 constraints_u_p = new SetOfConstraints(buildConstraints(ec));
240 constraints_v_p = constraints_u_p;
241 computingInfo_.reductionMethod.method=_pseudoReduction;
242 }
243
TermMatrix(const BilinearForm & blf,const EssentialConditions & ecu,const EssentialConditions & ecv,const string_t & na,bool noass)244 TermMatrix::TermMatrix(const BilinearForm& blf, const EssentialConditions& ecu, const EssentialConditions& ecv, const string_t& na, bool noass)
245 {
246 initFromBlf(blf, na, noass);
247 constraints_u_p = new SetOfConstraints(buildConstraints(ecu));
248 constraints_v_p = new SetOfConstraints(buildConstraints(ecv));
249 computingInfo_.reductionMethod.method=_pseudoReduction;
250 }
251
TermMatrix(const BilinearForm & blf,const SetOfConstraints & soc,const string_t & na,bool noass)252 TermMatrix::TermMatrix(const BilinearForm& blf, const SetOfConstraints& soc, const string_t& na, bool noass)
253 {
254 initFromBlf(blf, na, noass);
255 constraints_u_p = new SetOfConstraints(soc); //full copy of soc !!!
256 constraints_v_p = constraints_u_p;
257 computingInfo_.reductionMethod.method=_pseudoReduction;
258 }
259
TermMatrix(const BilinearForm & blf,const SetOfConstraints & socu,const SetOfConstraints & socv,const string_t & na,bool noass)260 TermMatrix::TermMatrix(const BilinearForm& blf, const SetOfConstraints& socu, const SetOfConstraints& socv,
261 const string_t& na, bool noass)
262 {
263 initFromBlf(blf, na, noass);
264 constraints_u_p = new SetOfConstraints(socu);
265 constraints_v_p = new SetOfConstraints(socv);
266 computingInfo_.reductionMethod.method=_pseudoReduction;
267 }
268
269 //create suTermMatrix's
initFromBlf(const BilinearForm & blf,const string_t & na,bool noass)270 void TermMatrix::initFromBlf(const BilinearForm& blf, const string_t& na, bool noass)
271 {
272 bilinForm_ = blf; //copy the linearform
273 computingInfo_.noAssembly = noass;
274 termType_ = _termMatrix;
275 name_ = na;
276 entries_p = 0;
277 scalar_entries_p=0;
278 rhs_matrix_p=0;
279 for(it_mublc it = bilinForm_.begin(); it != bilinForm_.end(); it++) //travel the map of single unknown bilinear forms
280 {
281 string_t nam = name_ + "_" + it->second.up()->name() + "_" + it->second.vp()->name();
282 // string_t nam = name_ + "_sub";
283 suTerms_[it->first] = new SuTermMatrix(&(it->second), nam, computingInfo_); //construct SuTermMatrix objects
284 }
285 }
286
287 //constructor from a linear combination of TermVector's
TermMatrix(const LcTerm<TermMatrix> & lc,const string_t & na)288 TermMatrix::TermMatrix(const LcTerm<TermMatrix>& lc, const string_t& na)
289 {
290 trace_p->push("TermMatrix::TermMatrix(LcTerm)");
291 entries_p = 0;
292 scalar_entries_p=0;
293 rhs_matrix_p=0;
294 constraints_u_p = 0;
295 constraints_v_p = 0;
296 termType_ = _termMatrix;
297 compute(lc, na);
298 trace_p->pop();
299 }
300
301 // destructor
~TermMatrix()302 TermMatrix::~TermMatrix()
303 {
304 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) delete it->second;
305 if(suTerms_.size()>1 && entries_p != 0) delete entries_p;
306 if(scalar_entries_p != entries_p && scalar_entries_p != 0) delete scalar_entries_p;
307 if(rhs_matrix_p != 0) delete rhs_matrix_p;
308 if(constraints_u_p!=0) delete constraints_u_p;
309 if(constraints_v_p!=0 && constraints_v_p!= constraints_u_p) delete constraints_v_p;
310 }
311
312 //copy constructor
TermMatrix(const TermMatrix & mat,const string_t & na)313 TermMatrix::TermMatrix(const TermMatrix& mat, const string_t& na)
314 {
315 computingInfo_.noAssembly = false;
316 termType_ = _termMatrix;
317 name_ = na;
318 entries_p = 0;
319 scalar_entries_p=0;
320 rhs_matrix_p=0;
321 constraints_u_p = 0;
322 constraints_v_p = 0;
323 copy(mat);
324 if(na != "") name_ = na;
325 }
326
327 //! constructor from a SuTermMatrix, create a one block TermMatrix
TermMatrix(const SuTermMatrix & sutm,const string_t & na)328 TermMatrix::TermMatrix(const SuTermMatrix& sutm, const string_t& na)
329 {
330 trace_p->push("TermMatrix::TermMatrix(SuTermMatrix)");
331 computingInfo_.noAssembly = false;
332 termType_ = _termMatrix;
333 name_ = na;
334 entries_p = 0;
335 scalar_entries_p=0;
336 rhs_matrix_p=0;
337 constraints_u_p = 0;
338 constraints_v_p = 0;
339 suTerms_[uvPair(sutm.up(),sutm.vp())]=new SuTermMatrix(sutm); //full copy
340 computingInfo_.isComputed=sutm.computed();
341 trace_p->pop();
342 }
343
TermMatrix(SuTermMatrix * sutm,const string_t & na)344 TermMatrix::TermMatrix(SuTermMatrix* sutm, const string_t& na)
345 {
346 trace_p->push("TermMatrix::TermMatrix(SuTermMatrix*)");
347 computingInfo_.noAssembly = false;
348 termType_ = _termMatrix;
349 name_ = na;
350 entries_p = 0;
351 scalar_entries_p=0;
352 rhs_matrix_p=0;
353 constraints_u_p = 0;
354 constraints_v_p = 0;
355 suTerms_[uvPair(sutm->up(),sutm->vp())]=sutm; //pointer copy
356 computingInfo_.isComputed=sutm->computed();
357 trace_p->pop();
358 }
359
360 // insert a SuTermMatrix with full copy
insert(const SuTermMatrix & sutm)361 void TermMatrix::insert(const SuTermMatrix& sutm)
362 {
363 trace_p->push("TermMatrix::insert(SuTermMatrix)");
364 suTerms_[uvPair(sutm.up(),sutm.vp())]=new SuTermMatrix(sutm); //full copy
365 if(!sutm.computed()) computingInfo_.isComputed= false;
366 trace_p->pop();
367 }
368
369 // insert a SuTermMatrix with pointer copy
insert(SuTermMatrix * sutm)370 void TermMatrix::insert(SuTermMatrix* sutm)
371 {
372 trace_p->push("TermMatrix::insert(SuTermMatrix*)");
373 suTerms_[uvPair(sutm->up(),sutm->vp())]=sutm; //pointer copy
374 if(!sutm->computed()) computingInfo_.isComputed= false;
375 trace_p->pop();
376 }
377
378
379 /*! constructor of a diagonal TermMatrix from a TermVector
380 if TermVector is a multiple unknowns vector, the matrix will be a multiple unknowns TermMatrix, each block being diagonal !
381 */
TermMatrix(const TermVector & tv,const string_t & na)382 TermMatrix::TermMatrix(const TermVector& tv, const string_t& na)
383 {
384 trace_p->push("TermMatrix::TermMatrix(TermVector)");
385 computingInfo_.noAssembly = false;
386 termType_ = _termMatrix;
387 name_ = na;
388 entries_p = 0;
389 scalar_entries_p=0;
390 rhs_matrix_p=0;
391 constraints_u_p = 0;
392 constraints_v_p = 0;
393 for(cit_mustv it = tv.begin(); it != tv.end(); it++)
394 {
395 const Unknown* u=it->first;
396 suTerms_[uvPair(u,u)]=new SuTermMatrix(*it->second,na+"_"+u->name()+"_"+u->name());
397 }
398 computingInfo_.isComputed=true;
399 trace_p->pop();
400 }
401
402 /*! constructor of matrix opker(xi,yj) - Lagrange interpolation -
403 opker is evaluated on dof coordinates linked to Unknown and GeomDomains
404 ux, domx is associated to matrix rows and uy, domy to matrix columns
405 NOTE : do not use this constructor if kernel is singular on some couple of points
406 */
TermMatrix(const Unknown & ux,const GeomDomain & domx,const Unknown & uy,const GeomDomain & domy,const OperatorOnKernel & opk,const string_t & na)407 TermMatrix::TermMatrix(const Unknown& ux, const GeomDomain& domx,
408 const Unknown& uy, const GeomDomain& domy, const OperatorOnKernel& opk, const string_t& na)
409 {
410 trace_p->push("TermMatrix::TermMatrix(Unknown, GeomDomain, Unknown, GeomDomain, OperatorOnKernel)");
411 computingInfo_.noAssembly = false;
412 termType_ = _termMatrix;
413 name_ = na;
414 entries_p = 0;
415 scalar_entries_p=0;
416 rhs_matrix_p=0;
417 constraints_u_p = 0;
418 constraints_v_p = 0;
419 suTerms_[uvPair(&uy,&ux)]=new SuTermMatrix(ux, domx, uy, domy, opk, na+"_"+uy.name()+"_"+ux.name());
420 computingInfo_.isComputed=true;
421 trace_p->pop();
422 }
423
424 /*! construct special matrix from a structure given by a TermMatrix
425 up to now, only IdMatrix is available
426 */
TermMatrix(const TermMatrix & A,SpecialMatrix sm,const string_t & na)427 TermMatrix::TermMatrix(const TermMatrix& A, SpecialMatrix sm, const string_t& na)
428 {
429 trace_p->push("TermMatrix(TermMatrix, SpecialMatrix)");
430 if (sm!=_idMatrix) error("matrix_type_not_handled", words("matrix", sm));
431 computingInfo_.noAssembly = false;
432 termType_ = _termMatrix;
433 if (na=="") name_="Id"; else name_ = na;
434 entries_p = 0;
435 scalar_entries_p=0;
436 rhs_matrix_p=0;
437 constraints_u_p = 0;
438 constraints_v_p = 0;
439 for (cit_mustm it = A.begin(); it != A.end(); it++) //travel the map of single unknown linear forms
440 {
441 uvPair uv = it->first;
442 if(uv.first==uv.second || uv.first->dual_p()==uv.second) suTerms_[uv] = new SuTermMatrix(*it->second, sm);
443 }
444 computingInfo_ .isComputed=true;;
445 if (A.scalar_entries_p != 0)
446 {
447 cdofs_c= A.cdofs_c;
448 cdofs_r= A.cdofs_r;
449 }
450 trace_p->pop();
451 }
452
453 //assign operator
operator =(const TermMatrix & mat)454 TermMatrix& TermMatrix::operator=(const TermMatrix& mat)
455 {
456 if(this==&mat) return *this;
457 clear();
458 copy(mat);
459 return *this;
460 }
461
462 // specify the storage of SuTermMatrix's of TermMatrix
463 // induce a storage conversion if terms are computed
setStorage(StorageType st,AccessType at)464 void TermMatrix::setStorage(StorageType st, AccessType at)
465 {
466 trace_p->push("TermMatrix::setStorage(...)");
467 computingInfo_.storageType = st;
468 computingInfo_.storageAccess = at;
469 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
470 it->second->setStorage(st, at);
471 if(entries_p!=0)
472 {
473 if(entries_p->storageType()!=st || entries_p->accessType()!=at)
474 {
475 std::vector<std::vector<number_t> > colIndices = entries_p->storagep()->scalarColIndices(); //retry column indices
476 MatrixStorage* mstorage = buildStorage(st, at, entries_p->nbOfRows(), entries_p->nbOfCols(), colIndices);
477 entries_p->toStorage(mstorage);
478 }
479 }
480 if(scalar_entries_p!=0)
481 {
482 if(scalar_entries_p->storageType()!=st || scalar_entries_p->accessType()!=at)
483 {
484 std::vector<std::vector<number_t> > colIndices = scalar_entries_p->storagep()->scalarColIndices(); //retry column indices
485 MatrixStorage* mstorage = buildStorage(st, at, scalar_entries_p->nbOfRows(), scalar_entries_p->nbOfCols(), colIndices);
486 scalar_entries_p->toStorage(mstorage);
487 }
488 }
489 trace_p->pop();
490 }
491
492 // copy a TermMatrix into current TermMatrix
copy(const TermMatrix & mat)493 void TermMatrix::copy(const TermMatrix& mat)
494 {
495 trace_p->push("TermMatrix::copy(TermMatrix)");
496 bilinForm_ = mat.bilinForm_;
497 //if(name_=="" || name_=="?") name_ = mat.name_ + "_copy";
498 if(name_=="" || name_=="?") name_ = mat.name_ + "@";
499 termType_ = _termMatrix;
500 for(cit_mustm it = mat.begin(); it != mat.end(); it++) //travel the map of single unknown linear forms
501 {
502 uvPair uv = it->first;
503 SuTermMatrix* sutm = it->second;
504 suTerms_[uv] = new SuTermMatrix(*sutm);
505 suTerms_[uv]->sublfp() = bilinForm_.subLfp(uv); //maintain links between bilinearform and sublinearforms
506 }
507 computingInfo_ = mat.computingInfo_;
508 if(mat.entries_p != 0) entries_p = new MatrixEntry(*mat.entries_p);
509 if(mat.scalar_entries_p != 0)
510 {
511 if(mat.scalar_entries_p!=mat.entries_p) scalar_entries_p = new MatrixEntry(*mat.scalar_entries_p);
512 else scalar_entries_p = entries_p;
513 cdofs_c= mat.cdofs_c;
514 cdofs_r= mat.cdofs_r;
515 }
516 if(mat.rhs_matrix_p != 0) rhs_matrix_p = new MatrixEntry(*mat.rhs_matrix_p);
517 if(mat.constraints_u_p !=0) constraints_u_p = new SetOfConstraints(*mat.constraints_u_p);
518 if(mat.constraints_v_p !=0)
519 {
520 if(mat.constraints_v_p == mat.constraints_u_p) constraints_v_p = constraints_u_p;
521 else constraints_v_p = new SetOfConstraints(*mat.constraints_v_p);
522 }
523 trace_p->pop();
524 }
525
526 //deallocate memory used by a TermMatrix
clear()527 void TermMatrix::clear()
528 {
529 trace_p->push("TermMatrix::clear");
530 if(entries_p != 0) delete entries_p;
531 if(scalar_entries_p!=entries_p && scalar_entries_p != 0) delete scalar_entries_p;
532 if(rhs_matrix_p != 0) delete rhs_matrix_p;
533 if(constraints_u_p!=0) delete constraints_u_p;
534 if(constraints_v_p!=0 && constraints_v_p!= constraints_u_p) delete constraints_v_p;
535 entries_p = 0;
536 scalar_entries_p = 0;
537 rhs_matrix_p =0;
538 constraints_u_p = 0;
539 constraints_v_p = 0;
540 cdofs_r.clear();
541 cdofs_c.clear();
542 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) it->second->clear();
543 //suTerms_.clear();
544 computed() = false;
545 trace_p->pop();
546 }
547
548 /*! compute a LcTerm (linear combination of TermMatrix's) to a TermMatrix
549 all the TermMatrix's have to be computed before
550 and the current TermMatrix is 'void'
551
552 NOTE : this current version works only for "standard" representation (entries pointers) but NOT for scalar representation (scalar_entries pointers)
553 it means that TermMatrix that have been converted using toScalar or toGlobal functions cannot be used in linear combinations.
554 Such conversions occur when essential conditions have been applied to a TermMatrix
555 To be improved in future !
556 */
compute(const LcTerm<TermMatrix> & lc,const string_t & na)557 void TermMatrix::compute(const LcTerm<TermMatrix>& lc, const string_t& na)
558 {
559 trace_p->push("TermMatrix::compute(LcTerm)");
560 if(lc.size() == 0) error("is_void", "LcTerm"); //abnormal !!
561 if(lc.size() == 1)
562 {
563 const TermMatrix* tM = dynamic_cast<const TermMatrix*>(lc.begin()->first);
564 if(tM == 0) error("null_pointer", "TermMatrix");
565 complex_t a = lc.begin()->second;
566 for(cit_mustm it = tM->suTerms_.begin(); it != tM->suTerms_.end(); it++)
567 {
568 SuTermMatrix* sut = new SuTermMatrix(*it->second); //copy SuTermMatrix
569 sut->name() = tostring(a) + " * " + it->second->name();
570 if(a != complex_t(1., 0)) *sut *= a; //product if a!=1
571 suTerms_[it->first] = sut;
572 }
573 name_ = na;
574 if(na == "")
575 {
576 if(a.imag() == 0) name_ = tostring(a.real());
577 else name_ = tostring(a);
578 name_ += " * ( " + tM->name() + " )" ;
579 }
580 computed() = true;
581 trace_p->pop();
582 return;
583 }
584
585 //case of a linear combination
586 //create linear combinations of SuTermMatrix indexed by unknown pairs
587 std::map<uvPair, LcTerm<SuTermMatrix> > lcs;
588 std::map<uvPair, LcTerm<SuTermMatrix> >::iterator itm;
589 name_ = na;
590 string_t pl = "";
591 for(LcTerm<TermMatrix>::const_iterator itt = lc.begin(); itt != lc.end(); itt++)
592 {
593 const TermMatrix* tM = dynamic_cast<const TermMatrix*>(itt->first);
594 if(tM == 0) error("null_pointer", "TermMatrix");
595 complex_t a = itt->second;
596 for(cit_mustm it = tM->suTerms_.begin(); it != tM->suTerms_.end(); it++)
597 {
598 uvPair uv = it->first;
599 SuTermMatrix* sut = it->second;
600 itm = lcs.find(uv);
601 if(itm == lcs.end()) lcs.insert(std::pair<uvPair, LcTerm<SuTermMatrix> >(uv, LcTerm<SuTermMatrix>(sut, a)));
602 else
603 {
604 LcTerm<SuTermMatrix> lci = itm->second;
605 lci.push_back(sut, a);
606 itm->second = lci;
607 }
608 }
609 if(na == "")
610 {
611 if(a.imag() == 0) name_ += pl + tostring(a.real()) ;
612 else name_ += pl + tostring(a) ;
613 name_ += " * ( " + tM->name() + " )" ;
614 pl = " + ";
615 }
616 }
617
618 //compute linear combination of SuTermMatrix's
619 for(itm = lcs.begin(); itm != lcs.end(); itm++)
620 {
621 SuTermMatrix* sut = new SuTermMatrix(itm->second); //create SuTermMatrix
622 suTerms_[itm->first] = sut;
623 }
624
625 computed() = true;
626 trace_p->pop();
627 return;
628 }
629
630 // assign operator from a linear combinations of TermVector's
operator =(const LcTerm<TermMatrix> & lc)631 TermMatrix& TermMatrix::operator=(const LcTerm<TermMatrix>& lc)
632 {
633 trace_p->push("TermMatrix::operator =(LcTerm)");
634 //prevent self adding case (for instance Tm=Tm+Tm2+...), Tm has to be copied before cleared !!!
635 LcTerm<TermMatrix> lcc = lc;
636 TermMatrix* clone = 0;
637 for(LcTerm<TermMatrix>::iterator it = lcc.begin(); it != lcc.end(); it++)
638 {
639 if(it->first == const_cast<const TermMatrix*>(this)) //self adding
640 {
641 if(clone == 0) clone = new TermMatrix(*this); //full copy !!!
642 complex_t a = it->second;
643 *it = std::pair<const TermMatrix*, complex_t>(clone, a); //modify linear combination by replacing current TermMatrix by its copy
644 }
645 }
646
647 //clear current TermMatrix
648 bilinForm_.clear();
649 if(entries_p != 0)
650 {
651 delete entries_p;
652 entries_p = 0;
653 }
654 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) delete it->second; //delete SuTermMatrix's
655
656 //compute linear combination
657 compute(lcc);
658
659 if(clone != 0) delete clone;
660 trace_p->pop();
661 return *this;
662 }
663
664 // value type (_real,_complex)
valueType() const665 ValueType TermMatrix::valueType() const
666 {
667 if(scalar_entries_p!=0) return scalar_entries_p->valueType_;
668 if(entries_p!=0) return entries_p->valueType_;
669 if(suTerms_.size() > 0)
670 {
671 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
672 {
673 if(it->second!=0 && it->second->valueType() == _complex) return _complex;
674 }
675 }
676 return _real;
677 }
678
679 // is scalar if all SuTermMatrix's are scalar matrices
isScalar() const680 bool TermMatrix::isScalar() const
681 {
682 if(suTerms_.size() > 0)
683 {
684 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
685 {
686 if(it->first.first->nbOfComponents()>1 || it->first.second->nbOfComponents()>1) return false;
687 }
688 }
689 return true;
690 }
691
692 // TermMatrix and SutermMatrix's computed state = true or false
markAsComputed(bool c)693 void TermMatrix::markAsComputed(bool c)
694 {
695 computingInfo_.isComputed=c;
696 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
697 it->second->computed()=c;
698 }
699
700 // return factorization type if factorized else return _noFactorization
factorization() const701 FactorizationType TermMatrix::factorization() const
702 {
703 if(scalar_entries_p!=0) return scalar_entries_p->factorization();
704 if(entries_p!=0) return entries_p->factorization();
705 if(suTerms_.size()==1) return suTerms_.begin()->second->factorization();
706 return _noFactorization;
707 }
708
709 // return set of row/col Unknowns (say v/u unknowns)
rowUnknowns() const710 std::set<const Unknown*> TermMatrix::rowUnknowns() const
711 {
712 std::set<const Unknown*> sun;
713 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
714 sun.insert(it->first.second);
715 return sun;
716 }
717
colUnknowns() const718 std::set<const Unknown*> TermMatrix::colUnknowns() const
719 {
720 std::set<const Unknown*> sun;
721 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
722 sun.insert(it->first.first);
723 return sun;
724 }
725
726 //! list of involved unknown spaces
unknownSpaces() const727 std::set<const Space*> TermMatrix::unknownSpaces() const
728 {
729 std::set<const Space*> sps;
730 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
731 {
732 sps.insert(it->first.first->space());
733 sps.insert(it->first.second->space());
734 }
735 return sps;
736 }
737
738 /*!
739 update the name of a TermMatrix and its SuTermMatrixs
740 SuTermMatrix name is defined as follows: name(TermMatrix)_name(row_Unknown)_name(col_Unknown)
741 */
name(const string_t & nam)742 void TermMatrix::name(const string_t& nam)
743 {
744 name_=nam;
745 for(it_mustm it = begin(); it != end(); it++) //travel the map of single unknown linear forms
746 {
747 it->second->name() = nam + "_" + it->second->up()->name() + "_" + it->second->vp()->name();
748 }
749 }
750
751 // return the actual pointer to entries (priority to scalar entry), return 0 is no allocated pointer
actual_entries() const752 MatrixEntry* TermMatrix::actual_entries() const
753 {
754 MatrixEntry* me = scalar_entries_p;
755 if (me != 0) return me;
756 if (suTerms_.size() == 1)
757 {
758 me = firstSut()->scalar_entries();
759 if (me == 0) me = firstSut()->entries();
760 }
761 return me;
762 }
763
764 /*! return global symmetry property (_noSymmetry, _symmetric, _adjoint, _skewAdjoint, _skewSymmetric)
765 that is same symmetry property of diagonal unknowns blocks it there are no non diagonal blocks
766 if there are non diagonal blocks, their symmetry is not checked (to do later)
767 NOTE : this function works only for allocated SCALAR entries
768 */
symmetry() const769 SymType TermMatrix::symmetry() const
770 {
771 SymType sy=_symmetric;
772 if(suTerms_.size()==0) return sy;
773 bool unset = true; //symmetry property not set
774 //identify symmetry property from diagonal block
775 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown matrices
776 {
777 const Unknown* u=it->first.first, *v=it->first.second;
778 SuTermMatrix* sut = it->second;
779 if((u==v || u==v->dual_p())) //block diagonal
780 {
781 if(sut->scalar_entries()!=0) //priority to scalar entries
782 {
783 if(unset) {sy=sut->scalar_entries()->symmetry(); unset=false;}
784 else if(sut->scalar_entries()->symmetry()!=sy) return _noSymmetry;
785 }
786 else if(sut->entries()!=0) //matrix of matrices, use entries
787 {
788 if(unset) {sy=sut->entries()->symmetry(); unset=false;}
789 else if(sut->entries()->symmetry()!=sy) return _noSymmetry;
790 }
791 }
792 else return _noSymmetry; //TermMatrix has non diagonal blocks (symmetry test not yet performed)
793 }
794 return sy;
795 }
796
797 // number of rows (counted in scalar dof)
numberOfRows() const798 number_t TermMatrix::numberOfRows() const
799 {
800 if(scalar_entries_p!=0) return cdofs_r.size();
801 if(suTerms_.size()==1) return begin()->second->numberOfRows();
802 number_t n=0;
803 std::map<const Unknown*,std::set<number_t> > rowdofs;
804 std::map<const Unknown*,std::set<number_t> >::iterator itr;
805 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
806 {
807 const Unknown* v=it->first.second;
808 std::vector<number_t> dofs=it->second->space_vp()->dofIds();
809 itr=rowdofs.find(v);
810 if(itr==rowdofs.end()) rowdofs[v]=std::set<number_t>(dofs.begin(),dofs.end());
811 else rowdofs[v].insert(dofs.begin(),dofs.end());
812 }
813 for(itr=rowdofs.begin(); itr!=rowdofs.end(); itr++)
814 n+=itr->second.size() * itr->first->nbOfComponents();
815 return n;
816 }
817
818 // number of columns (counted in scalar dof)
numberOfCols() const819 number_t TermMatrix::numberOfCols() const
820 {
821 if(scalar_entries_p!=0) return cdofs_c.size();
822 if(suTerms_.size()==1) return begin()->second->numberOfCols();
823 number_t n=0;
824 std::map<const Unknown*,std::set<number_t> > coldofs;
825 std::map<const Unknown*,std::set<number_t> >::iterator itc;
826 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
827 {
828 const Unknown* u=it->first.first;
829 std::vector<number_t> dofs=it->second->space_up()->dofIds();
830 itc=coldofs.find(u);
831 if(itc==coldofs.end()) coldofs[u]=std::set<number_t>(dofs.begin(),dofs.end());
832 else coldofs[u].insert(dofs.begin(),dofs.end());
833 }
834 for(itc=coldofs.begin(); itc!=coldofs.end(); itc++)
835 n+=itc->second.size() * itc->first->nbOfComponents();
836 return n;
837 }
838
nnz() const839 number_t TermMatrix::nnz() const
840 {
841 if (scalar_entries_p != 0) return scalar_entries_p->size();
842 if (entries_p != 0) return entries_p->scalarSize();
843 number_t n=0;
844 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
845 n+=it->second->nnz();
846 return n;
847 }
848
849 // -----------------------------------------------------------------------------------------------------------
850 // access to matrix element
851 // -----------------------------------------------------------------------------------------------------------
852
853 //access to single unknown term matrix (internal use)
subMatrix(const Unknown * up,const Unknown * vp)854 SuTermMatrix& TermMatrix::subMatrix(const Unknown* up, const Unknown* vp)
855 {
856 if (up == 0)
857 {
858 where("TermMatrix::subMatrix(Unknown*, Unknown*)");
859 error("termmatrix_submatrix_not_found", "up=0");
860 }
861 if (vp == 0)
862 {
863 where("TermMatrix::subMatrix(Unknown*, Unknown*)");
864 error("termmatrix_submatrix_not_found", "vp=0");
865 }
866 uvPair uv(up, vp);
867 it_mustm it = suTerms_.find(uv);
868 if (it == suTerms_.end())
869 {
870 where("TermMatrix::subMatrix(Unknown*, Unknown*)");
871 error("termmatrix_submatrix_not_found", "(" + up->name() + " " + vp->name() + ")");
872 }
873 return *(it->second);
874 }
875
subMatrix(const Unknown * up,const Unknown * vp) const876 const SuTermMatrix& TermMatrix::subMatrix(const Unknown* up, const Unknown* vp) const
877 {
878 if (up == 0)
879 {
880 where("TermMatrix::subMatrix(Unknown*, Unknown*) const");
881 error("termmatrix_submatrix_not_found", "up=0");
882 }
883 if (vp == 0)
884 {
885
886 where("TermMatrix::subMatrix(Unknown*, Unknown*) const");
887 error("termmatrix_submatrix_not_found", "vp=0");
888 }
889 uvPair uv(up, vp);
890 cit_mustm it = suTerms_.find(uv);
891 if (it == suTerms_.end())
892 {
893 where("TermMatrix::subMatrix(Unknown*, Unknown*) const");
894 error("termmatrix_submatrix_not_found", "(" + up->name() + " " + vp->name() + ")");
895 }
896 return *(it->second);
897 }
898
899 //access to single unknown term matrix (internal use)
subMatrix_p(const Unknown * up,const Unknown * vp)900 SuTermMatrix* TermMatrix::subMatrix_p(const Unknown* up, const Unknown* vp)
901 {
902 if (up == 0)
903 {
904 where("TermMatrix::subMatrix_p(Unknown*, Unknown*)");
905 error("termmatrix_submatrix_not_found", "up=0");
906 }
907 if (vp == 0)
908 {
909 where("TermMatrix::subMatrix_p(Unknown*, Unknown*)");
910 error("termmatrix_submatrix_not_found", "vp=0");
911 }
912 uvPair uv(up, vp);
913 it_mustm it = suTerms_.find(uv);
914 if(it != suTerms_.end()) return it->second;
915 return 0;
916 }
subMatrix_p(const Unknown * up,const Unknown * vp) const917 const SuTermMatrix* TermMatrix::subMatrix_p(const Unknown* up, const Unknown* vp) const
918 {
919 if (up == 0)
920 {
921 where("TermMatrix::subMatrix_p(Unknown*, Unknown*) const");
922 error("termmatrix_submatrix_not_found", "up=0");
923 }
924 if (vp == 0)
925 {
926 where("TermMatrix::subMatrix_p(Unknown*, Unknown*) const");
927 error("termmatrix_submatrix_not_found", "vp=0");
928 }
929 uvPair uv(up, vp);
930 cit_mustm it = suTerms_.find(uv);
931 if(it != suTerms_.end()) return it->second;
932 return 0;
933 }
934
935 /*!return single unknown term matrix as TermMatrix (copy constructor like),
936 useful to extract single unknown term from multiple unknowns term
937 induce a full copy !!!
938 */
operator ()(const Unknown & u,const Unknown & v) const939 TermMatrix TermMatrix::operator()(const Unknown& u, const Unknown& v) const
940 {
941 const SuTermMatrix& sut = this->subMatrix(&u, &v);
942 //create a new single unknown TermVector
943 string_t na = name_ + "_" + u.name() + "_" + v.name();
944 BilinearForm blf(*sut.sublf_p); //linear form from single unknown linear form
945 TermMatrix tm(blf, na, sut.computingInfo_.noAssembly); //create new TermMatrix
946 SuTermMatrix& tmsu = *tm.suTerms_.begin()->second;
947 tmsu.entries_p=0;
948 if(sut.entries_p!=0) //suTermMatrix is computed
949 {
950 tmsu.entries_p = new MatrixEntry(*sut.entries_p); //copy MatrixEntries
951 tmsu.computed()=true;
952 tm.computed()=true;
953 }
954 tm.entries_p = tmsu.entries_p; //update MatrixEntry pointer of TermMatrix
955 return tm;
956 }
957
958 // return the i-th row or col as a TermVector (r=1,...)
959 // restrict to single unknown TermMatrix or multiple unknown TermMatrix having global representation
getRowCol(number_t i,AccessType at,TermVector & R) const960 TermVector& TermMatrix::getRowCol(number_t i, AccessType at, TermVector& R) const
961 {
962 bool single=isSingleUnknown();
963 if (!single && scalar_entries_p==0 && entries_p==0)
964 {
965 where("TermMatrix::getRowCol(Nuber, AccessType, TermVector");
966 error("term_not_global_rep", name());
967 }
968
969 //initTermVector(R,valueType(),at==_col);
970 initTermVector(R,valueType(),at==_row); // init using row unknown if at=col and col unknown if at=row
971 //retry matrix pointer
972 MatrixEntry* mat=scalar_entries_p;
973 bool scal = true;
974 if (single && suTerms_.size()==1)
975 {
976 mat = suTerms_.begin()->second->scalar_entries();
977 if (mat==0) {mat = suTerms_.begin()->second->entries(); scal=false;}
978
979 }
980 else if (mat==0) {mat=entries_p; scal=false;}
981 if (mat==0)
982 {
983 where("TermMatrix::getRowCol(Nuber, AccessType, TermVector");
984 error("term_no_entries");
985 }
986
987 number_t nbrc = mat->nbOfRows();
988 if (at==_col) nbrc = mat->nbOfCols();
989 if (i<1 || i>nbrc)
990 {
991 where("TermMatrix::getRowCol(Nuber, AccessType, TermVector");
992 error("index_out_of_range",i, 1, nbrc);
993 }
994
995 VectorEntry vr = mat->getRowCol(i,at);
996 if (single)
997 {
998 if (scal) R.firstSut()->scalar_entries() = new VectorEntry(vr);
999 else R.firstSut()->entries() = new VectorEntry(vr);
1000 }
1001 else
1002 {
1003 if (scal) R.scalar_entries() = new VectorEntry(vr);
1004 else R.entries() = new VectorEntry(vr);
1005 }
1006 return R;
1007 }
1008
row(number_t r) const1009 TermVector TermMatrix::row(number_t r) const
1010 {
1011 TermVector R;
1012 return getRowCol(r,_row, R);
1013 }
1014
column(number_t c) const1015 TermVector TermMatrix::column(number_t c) const
1016 {
1017 TermVector C;
1018 return getRowCol(c,_col, C);
1019 }
1020
1021 //initialize a TermVector consistent with matrix column unknown (col=true), with matrix row unknown (col=false)
initTermVector(TermVector & tv,ValueType vt,bool col) const1022 void TermMatrix::initTermVector(TermVector& tv, ValueType vt, bool col) const
1023 {
1024 string_t na = tv.name(); //preserving only name
1025 tv.clear();
1026 tv.name() = na;
1027 //make list of row unknowns
1028 std::map<const Unknown*, SuTermMatrix*> terms;
1029 for(cit_mustm itA = begin(); itA != end(); itA++)
1030 {
1031 const Unknown* u;
1032 if(col) u = itA->first.first;
1033 else u = itA->first.second;
1034 SuTermMatrix* Auv = itA->second;
1035 if(terms.find(u) == terms.end()) terms[u] = Auv;
1036 else //update terms if u-space is larger than previous one
1037 {
1038 if(terms[u]->space_up()->dimSpace() < Auv->space_up()->dimSpace()) terms[u] = Auv;
1039 //to be improved : determine the largest space
1040 }
1041 }
1042 std::map<const Unknown*, SuTermMatrix*>::iterator it;
1043 for(it = terms.begin(); it != terms.end(); it++)
1044 {
1045 const Unknown* u = it->first;
1046 SuTermMatrix* sut = it->second;
1047 dimen_t nv = u->nbOfComponents();
1048 Space* sp = sut->space_up();
1049 if(!col) sp = sut->space_vp();
1050 number_t n = sp->dimSpace();
1051 SuTermVector* sutX = new SuTermVector("", u, sp, vt, n, nv);
1052 sutX->computed()=true;
1053 tv.insert(u, sutX);
1054 }
1055 tv.computed() = true;
1056 }
1057
1058 // -----------------------------------------------------------------------------------------------------------
1059 // compute the matrix term from bilinear form
1060 // -----------------------------------------------------------------------------------------------------------
compute()1061 void TermMatrix::compute()
1062 {
1063 if (computed()) return; //already computed
1064 trace_p->push("TermMatrix::compute()");
1065 //compute each block
1066 for (it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown linear forms
1067 { it->second->compute(); }
1068 /* merge blocks
1069 to avoid complexity and efficiency lost in elementary computation, some blocks have to be merged after
1070 this is the case when a block has a component of unknown (say u_1) and an other block refers to u
1071 we have to merge them using the mergeBlocks function
1072 */
1073 mergeBlocks();
1074
1075 if (constraints_u_p==0 && constraints_v_p==0)
1076 {
1077 computed() = true;
1078 if(theVerboseLevel>0) printSummary(std::cout);
1079 trace_p->pop();
1080 return;
1081 }
1082
1083 /* deal with essential conditions (constraints data)
1084 first, we have to move the matrix into scalar representation if there are some vector unknowns
1085 and may be to global scalar representation if there are some coupled unknowns condition
1086 then four methods are handled :
1087 - pseudo reduction : replace some matrix coefficients, see pseudoReduction function for details
1088 - real reduction : remove some matrix coefficients, see realReduction function for details (storage is modified)
1089 - penalisation : add large coefficients to some matrix coefficients, see penalizationReduction function for details
1090 - duality : introduce new dual unknown in matrix, see dualReduction function for details
1091 */
1092 if (computingInfo_.reductionMethod.method!=_pseudoReduction)
1093 error("reduction_method_not_handled", words("reduction method",computingInfo_.reductionMethod.method));
1094 bool global=false;
1095
1096 //basic consistancy tests
1097 if (constraints_u_p!=0)
1098 {
1099 if (constraints_u_p->size()==0) error("is_void","SetOfConstraints");
1100 if (constraints_u_p->begin()->second==0) error("null_pointer","constraints_u_p");
1101 global=constraints_u_p->isGlobal();
1102 }
1103 if (constraints_v_p!=0)
1104 {
1105 if (constraints_v_p->size()==0) error("is_void","SetOfConstraints");
1106 if (constraints_v_p->begin()->second==0) error("null_pointer","constraints_v_p");
1107 if (!global) global=constraints_u_p->isGlobal();
1108 }
1109
1110 //convert matrix to scalar representation and to global if constraints are global
1111 if (global) toGlobal(storageType(), storageAccess(), _noSymmetry, true); //go to global scalar representation
1112 else toScalar(); //go to scalar representation
1113
1114 switch (computingInfo_.reductionMethod.method)
1115 {
1116 case _noReduction : break;
1117 case _pseudoReduction : pseudoReduction(); break;
1118 // case _realReduction : realReduction(); trace_p->pop(); break;
1119 // case _penalizationReduction : penalizationReduction(); trace_p->pop(); break;
1120 // case _dualReduction : dualReduction(); trace_p->pop(); break;
1121 default :
1122 error("reduction_method_not_handled", words("reduction method",computingInfo_.reductionMethod.method));
1123 }
1124
1125 computed() = true;
1126 if (theVerboseLevel>0)
1127 {
1128 printSummary(std::cout);
1129 if (theCout.traceOnFile) printSummary(theCout.printStream->currentStream());
1130 }
1131 trace_p->pop();
1132 }
1133
1134 // -----------------------------------------------------------------------------------------------------------
1135 // merge blocks referring to same vector unknown
1136 // - when a block has a component of unknown as row or col unknown, it is convert to its vector representation
1137 // - when some blocks have different components of same unknown as row or col unknown, the blocks are really merged
1138 // into a block with vector unknowns
1139 // see the function mergeSuTermMatrix
1140 // -----------------------------------------------------------------------------------------------------------
mergeBlocks()1141 void TermMatrix::mergeBlocks()
1142 {
1143 trace_p->push("TermMatrix::mergeBlocks()");
1144 std::map<uvPair, std::list<SuTermMatrix*> > suts; //to collect block by vector unknowns
1145 std::map<uvPair, std::list<SuTermMatrix*> >::iterator itm;
1146 bool mergeFlag=false;
1147 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) //travel the map of single unknown SuTermMatrix
1148 {
1149 SuTermMatrix* sut=it->second;
1150 const Unknown* up=sut->up(), *vp=sut->vp();
1151 if(up->isComponent()) {up=up->parent(); mergeFlag=true;}
1152 if(vp->isComponent()) {vp=vp->parent(); mergeFlag=true;}
1153 itm=suts.find(uvPair(up,vp));
1154 if(itm!=suts.end()) itm->second.push_back(sut);
1155 else suts[uvPair(up,vp)]=std::list<SuTermMatrix*>(1,sut);
1156 }
1157 if(!mergeFlag) {trace_p->pop(); return;} //nothing to merge
1158
1159 //now merge each collected block
1160 for(itm=suts.begin(); itm!=suts.end(); itm++)
1161 {
1162 std::list<SuTermMatrix*>::iterator itl;
1163 std::vector<uvPair> uvel(itm->second.size());
1164 std::vector<uvPair>::iterator ituv=uvel.begin();
1165 for(itl=itm->second.begin(); itl!=itm->second.end(); itl++,ituv++) //memorize uv pairs
1166 *ituv= uvPair((*itl)->up(),(*itl)->vp());
1167 SuTermMatrix* msut=mergeSuTermMatrix(itm->second); //merge blocks, NO DELETION
1168 if(msut!=0) //real merging
1169 {
1170 std::list<SuTermMatrix*>::iterator itl;
1171 ituv=uvel.begin();
1172 for(itl=itm->second.begin(); itl!=itm->second.end(); itl++, ituv++) //delete old SuTermMatrix's
1173 {
1174 suTerms_.erase(*ituv);
1175 delete *itl;
1176 }
1177 suTerms_[itm->first]=msut; //assign the merged SuTermMatrix
1178 }
1179 }
1180
1181 trace_p->pop();
1182 }
1183
1184 // -----------------------------------------------------------------------------------------------------------
1185 // deal with essential condition (constraints)
1186 // -----------------------------------------------------------------------------------------------------------
1187
1188 /*!
1189 perform pseudo reduction of reduced essential conditions in a matrix. Essential conditions have the following form :
1190 U_E + F*U_R = s for column unknown U
1191 V_E + G*V_R = 0 for row test function V (generally related to unknown U)
1192 where E are the eliminated unknown/test function indices and R are the reduced unknown/test function indices
1193 The pseudo reduction of matrix consists in
1194 - modifying column A.j for j in R by adding -Fjk*A.k for k in E and replacing column A.k for k in E by a 0 column
1195 - modifying row Ai. for i in R by adding -Gik*Ak. for k in E and replacing row Ak. for k in E by a 0 row
1196 - if eliminated v unknowns are dual of eliminated u unknowns, the VE rows are replaced by the equation (or a part of)
1197 U_E + F*U_R = s
1198 to delay the right hand side modification, the (A.k) columns (k in E) are stored in a new structure
1199
1200 At the end of the process, the eliminated system looks like
1201 U_E U_R U_S RHS
1202 ---------------------- ------
1203 | | | | | |
1204 V_E | Id | F | 0 | | S |
1205 | | | | | |
1206 --------------------- -----
1207 | | | | | |
1208 V_R | 0 | ARR | ARS | | FR |
1209 | | | | | |
1210 ---------------------- ------
1211 | | | | | |
1212 V_S | 0 | ASR | ASS | | FS |
1213 | | | | | |
1214 ---------------------- ------
1215
1216 In some cases (F=G=0 or local conditions u^n=g, ...) the storage is not modified but in other cases (transmission condition for instance)
1217 the storage is modified
1218
1219 */
pseudoReduction()1220 void TermMatrix::pseudoReduction()
1221 {
1222 trace_p->push("TermMatrix::pseudoReduction()");
1223 if (constraints_u_p == 0 && constraints_v_p ==0) //no essential condition
1224 {
1225 warning("free_warning", " in TermMatrix::pseudoReduction, no essential conditions to deal with");
1226 return;
1227 }
1228
1229 bool global = false;
1230 complex_t alpha=computingInfo().reductionMethod.alpha;
1231 if(constraints_u_p != 0 && constraints_u_p->isGlobal()) global=true;
1232 else if(constraints_v_p != 0 && constraints_v_p->isGlobal()) global=true;
1233 Constraints* cons_u=0, *cons_v=0;
1234
1235 if(global) //global reduction
1236 {
1237 //modify matrix storage and symmetry
1238 if(constraints_u_p != 0) cons_u=(*constraints_u_p)(0);
1239 if(constraints_v_p != 0) cons_v=(*constraints_v_p)(0);
1240 if(scalar_entries_p->symmetry()!=_noSymmetry && constraints_u_p != constraints_v_p) scalar_entries_p->toUnsymmetric(_sym);
1241 extendStorage(scalar_entries_p, cdofs_r, cdofs_c, cons_u, cons_v); //extend storage if required
1242 if(cons_u!=0) cons_u->pseudoColReduction(scalar_entries_p, cdofs_r, cdofs_c, rhs_matrix_p);
1243 else error("global_sub_reduction_not_yet_handled", words("column"));
1244 //if (cons_v!=0 && scalar_entries_p->symmetry()==_noSymmetry) //row reduction
1245 if(cons_v!=0) //row reduction
1246 cons_v->pseudoRowReduction(scalar_entries_p, cdofs_r, cdofs_c, alpha);
1247 else if(constraints_v_p!=0 && cons_v==0)
1248 error("global_sub_reduction_not_yet_handled", words("row"));
1249 }
1250 else //sub reduction (i.e on SuTermMatrix's)
1251 {
1252 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
1253 {
1254 SuTermMatrix* sutm=it->second;
1255 const Unknown* u=it->first.first, *v=it->first.second;
1256 Constraints* cons_u = (*constraints_u_p)(u), *cons_v = 0;
1257 if(constraints_v_p ==0) cons_v = (*constraints_v_p)(v->dual_p());
1258 if(cons_v == 0) cons_v = (*constraints_v_p)(v->dual_p()); //try with dual unknown
1259 MatrixEntry* submat=sutm->scalar_entries_p;
1260 if(submat->symmetry()!=_noSymmetry && cons_u != cons_v) submat->toUnsymmetric(_sym); //goto non symmetric matrix stored with a symmetric storage
1261 extendStorage(submat, sutm->cdofs_v, sutm->cdofs_u, cons_u, cons_v); //extend storage if required
1262 if(cons_u!=0) //col reduction
1263 cons_u->pseudoColReduction(submat, sutm->cdofs_v, sutm->cdofs_u, sutm->rhs_matrix_p);
1264 //if (cons_v!=0 && submat->symmetry()==_noSymmetry) //row reduction
1265 if(cons_v!=0) //row reduction
1266 cons_v->pseudoRowReduction(submat, sutm->cdofs_v, sutm->cdofs_u, alpha);
1267 }
1268 }
1269 trace_p->pop();
1270 }
1271
1272 // -----------------------------------------------------------------------------------------------------------
1273 // change representation of matrix (entries and storage)
1274 // -----------------------------------------------------------------------------------------------------------
1275 /*! regarding a multiple unknowns TermMatrix, suggest a storage according to the following rules:
1276 if dense part > 10*(cs part+skyline part) -> dense storage else -> cs storage
1277 if umfpack installed -> column access else dual row/col access
1278 if matrix has symmetry -> symmetric access */
findGlobalStorageType() const1279 std::pair<StorageType,AccessType> TermMatrix::findGlobalStorageType() const
1280 {
1281 number_t densePart=0, csPart=0, skyPart=0;
1282 number_t denseFull = numberOfRows()*numberOfCols();
1283 StorageType st=_noStorage; AccessType at=_noAccess;
1284 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
1285 {
1286 StorageType sts=it->second->storageType();
1287 number_t s = it->second->nnz();
1288 if(sts==_dense) densePart+=s;
1289 if(sts==_cs) csPart+=s;
1290 if(sts==_skyline) skyPart+=s;
1291 }
1292 at=_dual;
1293 //if(densePart > 10*(csPart+skyPart)) {st=_dense; at=_row;}
1294 if(4*densePart > denseFull) {st=_dense; at=_row;} //dense part represents 25% of the matrix, choose dense
1295 else
1296 {
1297 st=_cs;
1298 #ifdef XLIFEPP_WITH_UMFPACK
1299 at=_col; //well adapted to umfpack
1300 #endif
1301 }
1302
1303 //if(symmetry()!=_noSymmetry) at=_sym; //raises a bug in toglobal, sym -> sym
1304 return std::make_pair(st,at);
1305 }
1306
toSkyline()1307 void TermMatrix::toSkyline()
1308 {
1309 trace_p->push("TermMatrix::toSkyline()");
1310 if(!computed()) error("not_computed_term", name());
1311 if(isSingleUnknown())
1312 {
1313 SuTermMatrix* sutm = begin()->second;
1314 if(sutm->entries()->storageType() == _skyline)
1315 {
1316 warning("free_warning", "TermMatrix" + name() + " is already a skyline matrix, nothing to do!");
1317 trace_p->pop();
1318 return;
1319 }
1320 if(sutm->entries()->storageType() == _dense)
1321 error("storage_not_implemented", "TermMatrix::toSkyline", words("storage type",_dense));
1322 if(sutm->entries()->storageType() == _cs) sutm->entries()->toSkyline(); //convert entries to skyline storage
1323 }
1324 else
1325 {
1326 error("block_conversion_not_yet_implemented", words("storage type",_skyline));
1327 }
1328 trace_p->pop();
1329 }
1330
1331 /*! create scalar representation of TermMatrix
1332 for each SuTermMatrix (if computed, entries_!=0), if not exists create its scalar representation (set scalar_entries_p and cdofs vectors)
1333 if SuTermMatrix is already scalar, scalar_entries_p = entries_p
1334 NOTE : scalar_entries_p of TermMatrix is not update by this function (see toGlobal function)
1335
1336 */
toScalar(bool keepEntries)1337 void TermMatrix::toScalar(bool keepEntries)
1338 {
1339 trace_p->push("TermMatrix::toScalar()");
1340 for(it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) it->second->toScalar(keepEntries);
1341 trace_p->pop();
1342 }
1343
1344 /*! create scalar global representation of TermMatrix
1345 make scalar representations of SuTermMatrix's if not exist and merge it in a scalar global representation by allocating
1346 scalar_entries_p and setting the cdofs vectors
1347
1348 st, at : storage and access type of global matrix, if st = _nosStorage try to identify "best" storage
1349 symt : to force symmetry of matrix (default = _noSymmetry)
1350 keepSuterms : if false (default value), SutermMatrix entries are deleted
1351 */
toGlobal(StorageType st,AccessType at,SymType symt,bool keepSuTerms)1352 void TermMatrix::toGlobal(StorageType st, AccessType at, SymType symt, bool keepSuTerms)
1353 {
1354 if (scalar_entries_p!=0) return; //already done, delete it outside if you want to rebuild
1355 trace_p->push("TermMatrix::toGlobal()");
1356
1357 //create scalar representation
1358 toScalar(); //nothing is done if SuTermMatrix's already scalar !
1359
1360 //cpuTime("toGlobal:toScalar");
1361 if (suTerms_.size()==1) {trace_p->pop(); return;} //nothing to merge
1362
1363 //cpuTime("toGlobal:enter to");
1364 //merge all SutermMatrix's
1365 // compare row and col unknowns
1366 bool sameRowColUnknowns = true;
1367 std::set<const Unknown*> vs=rowUnknowns(), us=colUnknowns();
1368 std::set<const Unknown*>::iterator itvs=vs.begin(), itus;
1369 if (us.size()!=vs.size()) sameRowColUnknowns = false;
1370 else
1371 for (; itvs!=vs.end() && sameRowColUnknowns; itvs++)
1372 {
1373 itus=us.find(*itvs);
1374 if (itus==us.end()) itus=us.find((*itvs)->dual_p());
1375 if (itus==us.end()) sameRowColUnknowns=false;
1376 }
1377
1378 if (!sameRowColUnknowns && symt!=_noSymmetry) error("symmetry_not_handled", words("symmetry", symt));
1379
1380 //try to find storage type if not set (has to be improved)
1381 if (st==_noStorage)
1382 {
1383 std::pair<StorageType,AccessType> stat=findGlobalStorageType();
1384 st=stat.first; at=stat.second;
1385 }
1386
1387 //create numbering of blocks in global numbering (row and size)
1388 std::map<const Unknown*, std::list<SuTermMatrix*> > rowsut, colsut; //list of SuTermMatrix by row/col unknown
1389 std::map<SuTermMatrix*, std::vector<number_t> > rownum, colnum; //block row/col numbering map for each SuTermMatrix
1390 ValueType vt=_real;
1391 for (it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
1392 {
1393 SuTermMatrix* sut= it->second;
1394 rowsut[it->first.second].push_back(sut);
1395 colsut[it->first.first].push_back(sut);
1396 if(sut->scalar_entries_p->valueType_ ==_complex) vt=_complex;
1397 }
1398 mergeNumberingFast(rowsut, rownum, cdofs_r,_row);
1399 mergeNumberingFast(colsut, colnum, cdofs_c,_col);
1400 //cpuTime("toGlobal:mergeNumbering");
1401
1402 //buiding row indices of global matrix and calling buildstorage
1403 MatrixStorage* ms=0;
1404 if (st!=_dense) //update storage pointer
1405 {
1406 std::vector<std::set<number_t> > indices(cdofs_r.size()); //col indices by row
1407 for (it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
1408 {
1409 SuTermMatrix* sut= it->second;
1410 MatrixStorage* msu=sut->scalarStoragep();
1411 std::vector<number_t>& rowmap=rownum[sut];
1412 std::vector<number_t>& colmap=colnum[sut];
1413 addIndices(indices, msu, rowmap, colmap);
1414 }
1415 //cpuTime("toGlobal:prepare buildstorage");
1416 ms=buildStorage(st,at,cdofs_r.size(), cdofs_c.size(),indices);
1417 //cpuTime("toGlobal:buildstorage");
1418 }
1419 else ms=buildStorage(st,at,cdofs_r.size(), cdofs_c.size());
1420
1421 //cpuTime("toGlobal:create_storage");
1422 scalar_entries_p=new MatrixEntry(vt, _scalar, ms, dimPair(1,1), symt);
1423 //merge SutermMatrix's
1424 for (it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
1425 {
1426 SuTermMatrix* sut= it->second;
1427 scalar_entries_p->assign(*sut->scalar_entries_p, rownum[sut], colnum[sut]);
1428 }
1429 //cpuTime("toGlobal:merge_submatrices "+tostring(suTerms_.size()));
1430
1431 if (!keepSuTerms) //clear SuTermMatrix's
1432 for (it_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) it->second->clear();
1433
1434 if (theVerboseLevel>0)
1435 theCout<<"multiple unknown TermMatrix "<<name()<<" moves to global representation : "
1436 << words("value",scalar_entries_p->valueType())<<" scalar matrix "<<numberOfRows()<< " X "<<numberOfCols()
1437 <<" in "<<scalar_entries_p->storagep()->name()<<" ("<< scalar_entries_p->storagep()->size()<<" coefficients)"<< eol;
1438 trace_p->pop();
1439 }
1440
1441 // Turns to scalar representation in case of multiple unknowns and returns pointer to data held in the matrix
matrixData()1442 MatrixEntry* TermMatrix::matrixData() {
1443 MatrixEntry* matA=0;
1444
1445 if (isSingleUnknown()) {
1446 SuTermMatrix* sutmA = begin()->second;
1447 if (sutmA->space_up() != sutmA->space_vp())
1448 error("term_inconsistent_unknown_spaces", name());
1449 matA = sutmA->entries();
1450 if (sutmA->scalar_entries()!=0) matA= sutmA->scalar_entries();
1451 }
1452 else { //multiple unknowns (goto scalar global representation)
1453 SymType syA=symmetry(); //detect global symmetry of TermMatrix
1454 if (entries()==0 && scalar_entries()==0) toGlobal(storageType(), storageAccess(), syA, true);
1455 else if (scalar_entries()==0) toScalar(false);
1456 matA = scalar_entries();
1457 }
1458 return matA;
1459 }
1460
1461 //toGlobal tool : add col indices of a matrix storage to current set of col indices with index mapping
addIndices(std::vector<std::set<number_t>> & indices,MatrixStorage * msu,const std::vector<number_t> & rowmap,const std::vector<number_t> & colmap)1462 void TermMatrix::addIndices(std::vector<std::set<number_t> >& indices, MatrixStorage* msu,
1463 const std::vector<number_t>& rowmap, const std::vector<number_t>& colmap)
1464 {
1465 std::vector<number_t>::const_iterator itrc;
1466 std::set<number_t>::iterator its;
1467 number_t k=1, shr=0, shc=0, nbc=msu->nbOfColumns(), nbr=msu->nbOfRows(), m;
1468 AccessType msuat=msu->accessType();
1469 if(rowmap.size()==1) shr=rowmap[0];
1470 if(colmap.size()==1) shc=colmap[0];
1471
1472 if(msuat==_row || msuat==_dual || msuat==_sym) //row in row
1473 {
1474 m = nbc;
1475 for(k=1; k<=nbr; ++k)
1476 {
1477 if(msuat!=_row) m=k; //restrict to lower part
1478 std::set<number_t> cols=msu->getCols(k,1,m); // retry col indices of row k in ms storage
1479 std::set<number_t>* indr=&indices[k+shr-1];
1480 if(rowmap.size()>1) indr=&indices[rowmap[k-1]-1];
1481 if(colmap.size()==1)
1482 {
1483 if(shc==0) indr->insert(cols.begin(), cols.end());
1484 else
1485 for(its=cols.begin(); its!=cols.end(); ++its) indr->insert((*its)+shc); // insert col numbering shift
1486 }
1487 else
1488 for(its=cols.begin(); its!=cols.end(); ++its) indr->insert(colmap[(*its)-1]); // insert col numbering map
1489 }
1490 }
1491 if(msuat==_col || msuat==_dual || msuat==_sym) //col in row
1492 {
1493 m = nbr;
1494 number_t d=2;
1495 if(msuat==_col) d=1;
1496 for(k=d; k<=nbc; ++k)
1497 {
1498 number_t c=k+shc;
1499 if(colmap.size()>1) c=colmap[k-1];
1500 if(msuat!=_col) m=k-1; // restrict to upper part, diag term has been already taken into account
1501 std::set<number_t> rows=msu->getRows(k,1,m); // retry row indices of col k in msu storage
1502 if(rowmap.size()==1)
1503 for(its=rows.begin(); its!=rows.end(); ++its) indices[(*its)+shr-1].insert(c); // insert col numbering map
1504 else
1505 for(its=rows.begin(); its!=rows.end(); ++its) indices[rowmap[(*its)-1]-1].insert(c); // insert col numbering map
1506 }
1507 }
1508 }
1509
1510 //tool for TermMatrix::toGlobal function
1511 // create the list of merged row/col dofs
1512 // and for each SuTermMatrix the map between is row/col numbering and the global row/col numbering
mergeNumbering(std::map<const Unknown *,std::list<SuTermMatrix * >> & rcsut,std::map<SuTermMatrix *,std::vector<number_t>> & rcnum,std::vector<DofComponent> & rcdof,AccessType rc)1513 void TermMatrix::mergeNumbering(std::map<const Unknown*, std::list<SuTermMatrix*> >& rcsut,
1514 std::map<SuTermMatrix*, std::vector<number_t > >& rcnum,
1515 std::vector<DofComponent>& rcdof, AccessType rc)
1516 {
1517 //order unknowns according to their ranks
1518 std::map<const Unknown*, std::list<SuTermMatrix*> >::iterator itmus;
1519 std::map<number_t,const Unknown*> order;
1520 for(itmus=rcsut.begin(); itmus!=rcsut.end(); itmus++)
1521 {
1522 const Unknown* u=itmus->first;
1523 number_t r=u->rank();
1524 if(order.find(r)==order.end()) order.insert(std::make_pair(r,u));
1525 }
1526 //merge global numbering
1527 std::vector<DofComponent>::iterator itd;
1528 std::map<number_t,const Unknown*>::iterator itmnu;
1529 for(itmnu=order.begin(); itmnu!=order.end(); itmnu++)
1530 {
1531 const Unknown* u=itmnu->second;
1532 std::list<SuTermMatrix* >::iterator itl=rcsut[u].begin(), itle=rcsut[u].end();
1533 if(rcsut[u].size()==1) //simple case only one SutermMatrix
1534 {
1535 SuTermMatrix* sut = *itl;
1536 std::vector<DofComponent>* cd=&sut->cdofsu();
1537 if(rc==_row) cd=&sut->cdofsv();
1538 number_t nbr=cd->size();
1539 rcnum[sut]=trivialNumbering<number_t>(rcdof.size()+1,rcdof.size()+nbr);
1540 rcdof.insert(rcdof.end(),cd->begin(),cd->end());
1541 }
1542 else //merge local numbering
1543 {
1544 std::map<DofComponent, number_t> dofmap;
1545 std::map<DofComponent, number_t>::iterator itmc;
1546 number_t ld=rcdof.size();
1547 for(; itl!=itle; itl++) //travel SuTermMatrix list
1548 {
1549 SuTermMatrix* sut = *itl;
1550 std::vector<DofComponent>* cd=&sut->cdofsu();
1551 if(rc==_row) cd=&sut->cdofsv();
1552 number_t nbcd=cd->size();
1553 std::vector<DofComponent> locd(nbcd);
1554 std::vector<number_t >& num = rcnum[sut];
1555 num.resize(nbcd);
1556 std::vector<number_t >::iterator itc=num.begin();
1557 number_t k=0;
1558 for(itd=cd->begin(); itd!=cd->end(); itd++, itc++)
1559 {
1560 itmc=dofmap.find(*itd);
1561 if(itmc==dofmap.end())
1562 {
1563 ld++; //increase global dof index
1564 dofmap[*itd]=ld; //update dofmap
1565 *itc=ld; //update local->global numbering
1566 locd[k]=*itd; //update local cdof
1567 k++;
1568 }
1569 else *itc=itmc->second;
1570 }
1571 locd.resize(k);
1572 rcdof.insert(rcdof.end(),locd.begin(),locd.end());
1573 }
1574 }
1575 }
1576 }
1577
1578 //tool for TermMatrix::toGlobal function, fast version
1579 // create the list of merged row/col dofs
1580 // and for each SuTermMatrix the map between is row/col numbering and the global row/col numbering
1581 // trivial list n->n+p are encoded only using the shift n : rcnum[sut]=[n]
mergeNumberingFast(std::map<const Unknown *,std::list<SuTermMatrix * >> & rcsut,std::map<SuTermMatrix *,std::vector<number_t>> & rcnum,std::vector<DofComponent> & rcdof,AccessType rc)1582 void TermMatrix::mergeNumberingFast(std::map<const Unknown*, std::list<SuTermMatrix*> >& rcsut,
1583 std::map<SuTermMatrix*, std::vector<number_t > >& rcnum,
1584 std::vector<DofComponent>& rcdof, AccessType rc)
1585 {
1586 //order unknowns according to their ranks
1587 std::map<const Unknown*, std::list<SuTermMatrix*> >::iterator itmus;
1588 std::map<number_t,const Unknown*> order;
1589 for(itmus=rcsut.begin(); itmus!=rcsut.end(); itmus++)
1590 {
1591 const Unknown* u=itmus->first;
1592 number_t r=u->rank();
1593 if(order.find(r)==order.end()) order.insert(std::make_pair(r,u));
1594 }
1595 //merge global numbering
1596 std::vector<DofComponent>::iterator itd;
1597 std::map<number_t,const Unknown*>::iterator itmnu;
1598 for(itmnu=order.begin(); itmnu!=order.end(); itmnu++)
1599 {
1600 const Unknown* u=itmnu->second;
1601 //order u-SuTermMatrix's by their row/col sizes largest to smallest
1602 std::vector<SuTermMatrix*> ordsut(rcsut[u].begin(),rcsut[u].end());
1603 //std::sort(ordsut.begin(),ordsut.end(),compNnzSutermMatrix); //rearrange from the largest to the smallest SuTermMatrix
1604 if(rc==_row) std::sort(ordsut.begin(),ordsut.end(),compRowSize); //rearrange from the largest to the smallest row sizes
1605 else std::sort(ordsut.begin(),ordsut.end(),compColSize); //rearrange from the largest to the smallest col sizes
1606
1607 //deal with first SuTermMatrix
1608 std::vector<SuTermMatrix* >::iterator itl=ordsut.begin(), itle=ordsut.end();
1609 SuTermMatrix* sut = *itl;
1610 std::vector<DofComponent>* cd=&sut->cdofsu();
1611 if(rc==_row) cd=&sut->cdofsv();
1612 number_t ld=rcdof.size()+1;
1613 rcnum[sut]=std::vector<number_t >(1,rcdof.size()); //trivial numbering
1614 rcdof.insert(rcdof.end(),cd->begin(),cd->end());
1615 std::map<DofComponent, number_t> dofmap;
1616 std::map<DofComponent, number_t>::iterator itmc;
1617 if(ordsut.size()>1)
1618 for(itd=cd->begin(); itd!=cd->end(); ++itd, ++ld) dofmap[*itd]=ld;
1619 itl++;
1620 ld=rcdof.size();
1621
1622 for(; itl!=itle; itl++) //travel SuTermMatrix list
1623 {
1624 bool trivial=true;
1625 SuTermMatrix* sut = *itl;
1626 std::vector<DofComponent>* cd=&sut->cdofsu();
1627 if(rc==_row) cd=&sut->cdofsv();
1628 number_t nbcd=cd->size();
1629 std::vector<DofComponent> locd(nbcd);
1630 std::vector<number_t >& num = rcnum[sut];
1631 num.resize(nbcd);
1632 std::vector<number_t >::iterator itc=num.begin();
1633 number_t k=0;
1634 for(itd=cd->begin(); itd!=cd->end(); itd++, itc++)
1635 {
1636 itmc=dofmap.find(*itd);
1637 if(itmc==dofmap.end())
1638 {
1639 ld++; //increase global dof index
1640 dofmap[*itd]=ld; //update dofmap
1641 *itc=ld; //update local->global numbering
1642 locd[k]=*itd; //update local cdof
1643 k++;
1644 }
1645 else {*itc=itmc->second; trivial=false;}
1646 }
1647 locd.resize(k);
1648 if(trivial) rcnum[sut]= std::vector<number_t >(1,rcdof.size()); //trivial numbering
1649 rcdof.insert(rcdof.end(),locd.begin(),locd.end());
1650 }
1651 }
1652 }
1653
1654 // -----------------------------------------------------------------------------------------------------------
1655 // Algebraic operations on TermMatrix (+=, -=)
1656 // -----------------------------------------------------------------------------------------------------------
1657
1658 /*! Algebraic operation += and -=
1659 the result of these operations is a TermMatrix with all unknown blocks of current TermMatrix and added Termatrix
1660 | Avu Avp | | Mvu | | Avu+Mvu Avp |
1661 | Aqu | += | Mqu Mqp | ==> | Aqu+Mqu Mqp |
1662 | Atp Ats| | Mtu Mts| | Mtu Atp Ats+Mts|
1663 in other words, the matrices are merged and summation is a real one on common unknowns blocks
1664 */
operator +=(const TermMatrix & tM)1665 TermMatrix& TermMatrix::operator+=(const TermMatrix& tM)
1666 {
1667 bilinForm_ += tM.bilinForm_;
1668 if(! computed()) return *this; //no hard copy
1669
1670 for(it_mustm it = begin(); it != end(); it++) //travel the blocks of current matrix
1671 {
1672 const Unknown* up = it->first.first, *vp = it->first.second; //unknowns of current block
1673 SuTermMatrix* sut = it->second; //current block
1674 const SuTermMatrix* stM = tM.subMatrix_p(up, vp); //find (up,vp) block in tM
1675 if(stM != 0)(*sut) += *stM; //add block to current block
1676 }
1677 for(cit_mustm itM = tM.begin(); itM != tM.end(); itM++) //travel the blocks of added matrix
1678 {
1679 const Unknown* up = itM->first.first, *vp = itM->first.second; //unknowns of current block
1680 SuTermMatrix* sutM = itM->second; //current block
1681 const SuTermMatrix* sut = subMatrix_p(up, vp); //find (up,vp) block in current matrix
1682 if(sut == 0) suTerms_[uvPair(up, vp)] = new SuTermMatrix(*sutM); //create new block in current matrix
1683 }
1684 return *this;
1685 }
1686
operator -=(const TermMatrix & tM)1687 TermMatrix& TermMatrix::operator-=(const TermMatrix& tM)
1688 {
1689 bilinForm_ -= tM.bilinForm_;
1690 if(! computed()) return *this; //no hard copy
1691
1692 for(it_mustm it = begin(); it != end(); it++) //travel the blocks of current matrix
1693 {
1694 const Unknown* up = it->first.first, *vp = it->first.second; //unknowns of current block
1695 SuTermMatrix* sut = it->second; //current block
1696 const SuTermMatrix* stM = tM.subMatrix_p(up, vp); //find (up,vp) block in tM
1697 if(stM != 0)(*sut) -= *stM; //add block to current block
1698 }
1699 for(cit_mustm itM = tM.begin(); itM != tM.end(); itM++) //travel the blocks of added matrix
1700 {
1701 const Unknown* up = itM->first.first, *vp = itM->first.second; //unknowns of current block
1702 SuTermMatrix* sutM = itM->second; //current block
1703 const SuTermMatrix* sut = subMatrix_p(up, vp); //find (up,vp) block in current matrix
1704 if(sut == 0) //create new block in current matrix
1705 {
1706 SuTermMatrix* nsut = new SuTermMatrix(*sutM);
1707 *nsut *= -1.;
1708 suTerms_[uvPair(up, vp)] = nsut;
1709 }
1710 }
1711 return *this;
1712 }
1713
1714 // -----------------------------------------------------------------------------------------------------------
1715 // get real/imaginary part or move from real/complex to complex/real representation
1716 // -----------------------------------------------------------------------------------------------------------
toReal()1717 TermMatrix& TermMatrix::toReal()
1718 {
1719 if(valueType()==_real) return *this;
1720 for(it_mustm it = begin(); it != end(); it++) it->second->toReal();
1721 return *this;
1722 }
1723
real(const TermMatrix & tm)1724 TermMatrix real(const TermMatrix& tm)
1725 {
1726 TermMatrix atm=tm;
1727 atm.name()="real("+tm.name()+")";
1728 if(atm.valueType()==_complex) atm.toReal();
1729 return atm;
1730 }
1731
toComplex()1732 TermMatrix& TermMatrix::toComplex()
1733 {
1734 for(it_mustm it = begin(); it != end(); it++) it->second->toComplex();
1735 return *this;
1736 }
1737
toComplex(const TermMatrix & tm)1738 TermMatrix toComplex(const TermMatrix& tm)
1739 {
1740 TermMatrix atm=tm;
1741 atm.name()="complex("+tm.name()+")";
1742 atm.toComplex();
1743 return atm;
1744 }
1745
toImag()1746 TermMatrix& TermMatrix::toImag()
1747 {
1748 for(it_mustm it = begin(); it != end(); it++) it->second->toImag();
1749 return *this;
1750 }
1751
imag(const TermMatrix & tm)1752 TermMatrix imag(const TermMatrix& tm)
1753 {
1754 TermMatrix atm=tm;
1755 atm.name()="imag("+tm.name()+")";
1756 atm.toImag();
1757 return atm;
1758 }
1759
toConj()1760 TermMatrix& TermMatrix::toConj()
1761 {
1762 for(it_mustm it = begin(); it != end(); it++) it->second->toConj();
1763 return *this;
1764 }
1765
conj(const TermMatrix & tm)1766 TermMatrix conj(const TermMatrix& tm)
1767 {
1768 TermMatrix atm=tm;
1769 if(tm.valueType()==_real) warning("free_warning"," taking the conjugate of the REAL TermMatrix "+tm.name()+" is useless");
1770 else
1771 {
1772 atm.name()="conj("+tm.name()+")";
1773 atm.toConj();
1774 }
1775 return atm;
1776 }
1777
1778
1779
roundToZero(real_t aszero)1780 TermMatrix& TermMatrix::roundToZero(real_t aszero)
1781 {
1782 for(it_mustm it = begin(); it != end(); it++) it->second->roundToZero(aszero);
1783 return *this;
1784 }
1785
roundToZero(const TermMatrix & tm,real_t aszero=10* theEpsilon)1786 TermMatrix roundToZero(const TermMatrix& tm, real_t aszero = 10*theEpsilon ) //! return the 0 rounded TermMatrix)
1787 {
1788 TermMatrix atm=tm;
1789 atm.name()="roundTo0("+tm.name()+")";
1790 atm.roundToZero(aszero);
1791 return atm;
1792 }
1793
1794 // Frobenius norm : sqrt(sum|a_ij|^2)
norm2() const1795 real_t TermMatrix::norm2() const
1796 {
1797 if(scalar_entries_p!=0) return scalar_entries_p->norm2();
1798 real_t n=0.;
1799 for(cit_mustm it = begin(); it != end(); it++) //travel the blocks of current matrix
1800 {
1801 real_t nb=it->second->norm2();
1802 n+=nb*nb;
1803 }
1804 return std::sqrt(n);
1805 }
1806
1807 // infinite norm : sup|a_ij|
norminfty() const1808 real_t TermMatrix::norminfty() const
1809 {
1810 if(scalar_entries_p!=0) return scalar_entries_p->norminfty();
1811 real_t n=0.;
1812 for(cit_mustm it = begin(); it != end(); it++) //travel the blocks of current matrix
1813 n=std::max(n,it->second->norminfty());
1814 return n;
1815 }
1816
1817 // -----------------------------------------------------------------------------------------------------------
1818 // direct solver tools
1819 // -----------------------------------------------------------------------------------------------------------
1820
1821 // member functions
1822 // solve linear system using LU factorization (current matrix is preserved)
luSolve(const TermVector & B,TermVector & X)1823 void TermMatrix::luSolve(const TermVector& B, TermVector& X)
1824 {
1825 TermMatrix Af;
1826 factorize((*this), Af, _lu);
1827 X=factSolve(Af, B);
1828 }
1829
1830 // solve linear system using LDLt factorization (current matrix is preserved)
ldltSolve(const TermVector & B,TermVector & X)1831 void TermMatrix::ldltSolve(const TermVector& B, TermVector& X)
1832 {
1833 TermMatrix Af;
1834 factorize((*this), Af, _ldlt);
1835 X=factSolve(Af, B);
1836 }
1837
1838 // solve linear system using LDL* factorization (current matrix is preserved)
ldlstarSolve(const TermVector & B,TermVector & X)1839 void TermMatrix::ldlstarSolve(const TermVector& B, TermVector& X)
1840 {
1841 TermMatrix Af;
1842 factorize((*this), Af, _ldlstar);
1843 X=factSolve(Af, B);
1844 }
1845
1846 // solve linear system using umfpack(current matrix is preserved)
umfpackSolve(const TermVector & B,TermVector & X)1847 void TermMatrix::umfpackSolve(const TermVector& B, TermVector& X)
1848 {
1849 X = xlifepp::umfpackSolve(*this, B);
1850 }
1851
1852 //------------------------------------------------------------------------------------------------------------
1853 // particular solver used by SOR and SSOR iterative method
1854 //------------------------------------------------------------------------------------------------------------
sorDiagonalMatrixVector(const TermVector & B,TermVector & X,const real_t w)1855 void TermMatrix::sorDiagonalMatrixVector(const TermVector& B, TermVector& X, const real_t w)
1856 {
1857 sorSolve(B, X, w, _matrixVectorSorS);
1858 }
sorUpperSolve(const TermVector & B,TermVector & X,const real_t w)1859 void TermMatrix::sorUpperSolve(const TermVector& B, TermVector& X, const real_t w)
1860 {
1861 sorSolve(B, X, w, _upperSorS);
1862 }
sorLowerSolve(const TermVector & B,TermVector & X,const real_t w)1863 void TermMatrix::sorLowerSolve(const TermVector& B, TermVector& X, const real_t w)
1864 {
1865 sorSolve(B, X, w, _lowerSorS);
1866 }
sorDiagonalSolve(const TermVector & B,TermVector & X,const real_t w)1867 void TermMatrix::sorDiagonalSolve(const TermVector& B, TermVector& X, const real_t w)
1868 {
1869 sorSolve(B, X, w, _diagSorS);
1870 }
1871
sorSolve(const TermVector & B,TermVector & X,const real_t w,SorSolverType sType)1872 void TermMatrix::sorSolve(const TermVector& B, TermVector& X, const real_t w, SorSolverType sType)
1873 {
1874 trace_p->push("sorSolver(TermMatrix&, const TermVector&, real_t , SorSolvertype)");
1875 //create TermVector X
1876 ValueType vtX = _real;
1877 if (this->valueType() == _complex || B.valueType() == _complex) vtX = _complex;
1878 this->initTermVector(X, vtX, true);
1879
1880 //solve linear system
1881 if (this->isSingleUnknown())
1882 {
1883 const Unknown* v = this->begin()->first.second, *u=this->begin()->first.first;
1884 SuTermMatrix* sutm = this->begin()->second;
1885 //check (*this), B unknown consistancy
1886 const SuTermVector* vB = B.subVector_p(u);
1887 if (vB == 0)
1888 {
1889 vB=B.subVector_p(u->dual_p());
1890 if (vB==0) error("term_inconsistent_unknowns");
1891 }
1892 //prepare matrix, right hand side and solution
1893 if (sutm->strucType()==_matrix) sutm->toScalar(true);
1894 SuTermVector cvB(*vB); //copy B entries
1895 SuTermVector* vX = X.subVector_p(u);
1896 if (vX == 0) {vX = X.subVector_p(u->dual_p()); }
1897 MatrixEntry* mat=0;
1898 VectorEntry* b=0, *x=0;
1899 if (sutm->scalar_entries()==0) //scalar system
1900 {
1901 mat=sutm->entries();
1902 b=cvB.entries();
1903 std::vector<number_t> renum = renumber(sutm->space_up(), vB->spacep());
1904 if (renum.size() != 0) b->extendEntries(renum,sutm->space_up()->dimSpace()); //extend vector to matrix column numbering
1905 x=vX->entries();
1906 }
1907 else //vector system in scalar form
1908 {
1909 mat=sutm->scalar_entries();
1910 b=cvB.scalar_entries();
1911 if (b==0) {cvB.toScalar(); b=cvB.scalar_entries();}
1912 std::vector<number_t> renum;
1913 if (cvB.up() == v) renum = renumber(sutm->cdofsv(), cvB.cdofs());
1914 else renum = renumber(sutm->cdofsv(), dualDofComponents(cvB.cdofs()));
1915 if (renum.size() != 0) b->extendEntries(renum,sutm->cdofsv().size()); //extend vector to matrix column numbering
1916 vX->toScalar();
1917 x=vX->scalar_entries();
1918 }
1919 if ((*this).hasConstraints()) // case of constraints on (*this)
1920 {
1921 mat=sutm->scalar_entries();
1922 if (vX->scalar_entries()==0) x->toScalar();
1923 else x=vX->scalar_entries();
1924 cvB.toScalar(); //force scalar representation
1925 b=cvB.scalar_entries();
1926 Constraints* cons_u = 0, *cons_v = 0;
1927 if (this->constraints_u_p !=0) cons_u = (*(this->constraints_u_p))(u);
1928 if (this->constraints_v_p !=0)
1929 {
1930 cons_v = (*(*this).constraints_v_p)(v);
1931 if(cons_v == 0) cons_v = (*(*this).constraints_v_p)(v->dual_p()); //try with dual unknown
1932 }
1933 appliedRhsCorrectorTo(b, cvB.cdofs(), sutm->rhs_matrix(), cons_u, cons_v, this->computingInfo_.reductionMethod); //correct rhs to take into account constraints
1934 }
1935 //goto solvers
1936 switch(sType)
1937 {
1938 case _diagSorS :
1939 mat->sorDiagonalSolve(*b, *x, w);
1940 break;
1941 case _upperSorS :
1942 mat->sorUpperSolve(*b, *x, w);
1943 break;
1944 case _lowerSorS :
1945 mat->sorLowerSolve(*b, *x, w);
1946 break;
1947 case _matrixVectorSorS :
1948 mat->sorDiagonalMatrixVector(*b, *x, w);
1949 break;
1950 default :
1951 error("undef_option", "SorSolverType");
1952 }
1953 if (vX->up() == sutm->up()) vX->cdofs()=sutm->cdofsu(); //update cdofs
1954 else vX->cdofs()=dualDofComponents(sutm->cdofsu());
1955 if (vX->up()->nbOfComponents() > 1) vX->toVector(true); //return to vector representation
1956 vX->computed() = true;
1957 X.computed() = true;
1958 }
1959 else
1960 {
1961 TermVector Bc(B); //copy of B
1962 if (this->hasConstraints()) // case of constraints on (*this), applied rhs correction
1963 {
1964 Constraints* cons_u = 0, *cons_v = 0;
1965 if (this->constraints_u_p !=0) cons_u = (*(this->constraints_u_p))(0);
1966 if (this->constraints_v_p !=0) cons_v = (*(this->constraints_v_p))(0);
1967 if (cons_u!=0 || cons_v!=0) //global constraint
1968 {
1969 this->toGlobal(_noStorage, _noAccess, _noSymmetry, false);
1970 Bc.toGlobal(false); //go to scalar global representation
1971 Bc.adjustScalarEntries(this->cdofsr()); //adjust vector to matrix column scalar numbering
1972 appliedRhsCorrectorTo(Bc.scalar_entries(), Bc.cdofs(), this->rhs_matrix(),
1973 cons_u, cons_v, this->computingInfo_.reductionMethod);
1974 }
1975 else //local constraints, correction of subsystems
1976 {
1977 Bc.toScalar();
1978 for (it_mustm it = this->begin(); it != this->end(); it++)
1979 {
1980 const Unknown* u=it->first.first, *v=it->first.second;
1981 SuTermMatrix* sutm= it->second;
1982 SuTermVector* sutv= Bc.subVector_p(u);
1983 if (sutv==0) sutv= Bc.subVector_p(u->dual_p()); //try with dual
1984 if (this->constraints_u_p !=0) cons_u = (*(this->constraints_u_p))(u);
1985 if (this->constraints_v_p !=0)
1986 {
1987 cons_v = (*(this->constraints_v_p))(v);
1988 if (cons_v == 0) cons_v = (*(this->constraints_v_p))(v->dual_p()); //try with dual unknown
1989 }
1990 if (cons_u!=0 && cons_v!=0 && sutv!=0)
1991 appliedRhsCorrectorTo(sutv->scalar_entries(), sutv->cdofs(), sutm->rhs_matrix(),
1992 cons_u, cons_v, this->computingInfo_.reductionMethod);
1993 }
1994 Bc.toGlobal();
1995 this->toGlobal(_noStorage, _noAccess, _noSymmetry, false);
1996 Bc.adjustScalarEntries(this->cdofsr()); //adjust vector to matrix column scalar numbering
1997 }
1998 }
1999 else //no constraints to appply
2000 {
2001 this->toGlobal(_noStorage, _noAccess, _noSymmetry, false);
2002 Bc.toGlobal();
2003 Bc.adjustScalarEntries(this->cdofsr()); //adjust vector to matrix column scalar numbering
2004 }
2005
2006 //goto solvers
2007 X.toGlobal(false);
2008 VectorEntry* x=X.scalar_entries();
2009 VectorEntry* b=Bc.scalar_entries();
2010 MatrixEntry* mat=this->scalar_entries();
2011
2012 //goto solvers
2013 switch(sType)
2014 {
2015 case _diagSorS :
2016 mat->sorDiagonalSolve(*b, *x, w);
2017 break;
2018 case _upperSorS :
2019 mat->sorUpperSolve(*b, *x, w);
2020 break;
2021 case _lowerSorS :
2022 mat->sorLowerSolve(*b, *x, w);
2023 break;
2024 default :
2025 error("undef_option", "SorSolverType");
2026 }
2027 X.computed() = true;
2028 X.toLocal(false);
2029 }
2030 trace_p->pop();
2031 }
2032
2033 // -----------------------------------------------------------------------------------------------------------
2034 // in/out utilities
2035 // -----------------------------------------------------------------------------------------------------------
2036
2037 //print storage on stream
viewStorage(std::ostream & out) const2038 void TermMatrix::viewStorage(std::ostream& out) const
2039 {
2040 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
2041 {
2042 out << "SuTermMatrix " << it->second->name() << "\n";
2043 it->second->viewStorage(out);
2044 }
2045 }
2046
2047 //print TermMatrix
print(std::ostream & out) const2048 void TermMatrix::print(std::ostream& out) const
2049 {
2050 if(theVerboseLevel == 0) return;
2051 out << "TermMatrix " << name() << " : ";
2052 if(suTerms_.size() == 0)
2053 {
2054 out << " " << words("void") << " ";
2055 return;
2056 }
2057 cit_mustm it = suTerms_.begin();
2058 if(suTerms_.size() == 1)
2059 {
2060 out << words("unknown") << " \"" << it->first.first->name() << "\" ";
2061 out << words("test function") << " \"" << it->first.second->name() << "\"\n";
2062 }
2063 else
2064 {
2065 out << "("<<words("unknowns")<<", " << words("test functions")<<") : ";
2066 for(it = suTerms_.begin(); it != suTerms_.end(); it++)
2067 out << "(" << it->first.first->name() << ", "<< it->first.second->name() << ") ";
2068 out << eol;
2069 }
2070 if(theVerboseLevel < 2) return;
2071
2072 //print SuTermMatrix's
2073 number_t vb = theVerboseLevel;
2074 if(theVerboseLevel < 5) verboseLevel(2);
2075 bool header = (suTerms_.size() > 1);
2076 for(it = suTerms_.begin(); it != suTerms_.end(); it++) it->second->print(out, header);
2077 verboseLevel(vb);
2078
2079 //print global entries
2080 if(entries_p != 0) out << " global entries : "<<*entries_p<<eol;
2081 if(scalar_entries_p != 0)
2082 {
2083 out << " global scalar entries : "<<eol;
2084 out << words("firste") << " " << words("row") << " cdofs : ";
2085 number_t nbd=cdofs_r.size();
2086 number_t m = std::min(number_t(theVerboseLevel),nbd);
2087 std::vector<DofComponent>::const_iterator itd=cdofs_r.begin();
2088 for(number_t i = 0; i < m; i++, itd++) out << *itd << " ";
2089 if(m < nbd) out<<"...";
2090 out<<eol;
2091 out << words("firste") << " " << words("column") << " cdofs : ";
2092 nbd=cdofs_c.size();
2093 m = std::min(number_t(theVerboseLevel),nbd);
2094 itd=cdofs_c.begin();
2095 for(number_t i = 0; i < m; i++, itd++) out << *itd << " ";
2096 if(m < nbd) out<<"...";
2097 out<<eol;
2098 if(scalar_entries_p==entries_p) out<<" same values as global entries"<<eol;
2099 else out << (*scalar_entries_p)<<eol;
2100 }
2101
2102 //print SetOfConstraints
2103 if(constraints_u_p!=0)
2104 out << " constraints on unknown (column) : "<<*constraints_u_p;
2105 if(constraints_v_p!=0)
2106 {
2107 out << " constraints on test fuction (row) : ";
2108 if(constraints_v_p == constraints_u_p) out<<" same as constraints on column"<<eol;
2109 else out <<*constraints_v_p<<eol;
2110 }
2111 if(constraints_u_p!=0 || constraints_v_p!=0) out<<" "<<words("reduction method", computingInfo_.reductionMethod.method)<<eol;
2112 }
2113
2114 //print brief computation report
printSummary(std::ostream & out) const2115 void TermMatrix::printSummary(std::ostream& out) const
2116 {
2117 out << "TermMatrix " << name() << " computed, size "<<numberOfRows()<< " X "<<numberOfCols()<<" : ";
2118 if(!isSingleUnknown()) out<<eol;
2119 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++) it->second->printSummary(out);
2120 if(scalar_entries_p!=0) out<<eol<<" has global representation in "<< scalar_entries_p->storagep()->name();
2121 if(rhs_matrix_p!=0) out<<eol<<" has an essential condition correction matrix "<< rhs_matrix_p->nbOfRows()<<" X "<<rhs_matrix_p->nbOfCols();
2122 out << eol;
2123 }
2124
2125 // save TermMatrix to file (dense or Matlab format)
saveToFile(const string_t & fn,StorageType st,bool encode) const2126 void TermMatrix::saveToFile(const string_t& fn, StorageType st, bool encode) const
2127 {
2128 if(!computed() || suTerms_.size() == 0)
2129 {
2130 warning("free_warning", "matrix is not computed, no saving");
2131 return;
2132 }
2133
2134 //save global representation if exists, priority to scalar representation
2135 if(scalar_entries_p!=0)
2136 {
2137 scalar_entries_p->saveToFile(fn,st,encode);
2138 return;
2139 }
2140 if(entries_p!=0)
2141 {
2142 entries_p->saveToFile(fn,st,encode);
2143 return;
2144 }
2145
2146 //save SuTermmMatrix's
2147 if(suTerms_.size() == 0)
2148 {
2149 warning("free_warning", "matrix seems to be empty, no saving");
2150 return;
2151 }
2152
2153 cit_mustm it = suTerms_.begin();
2154 if(isSingleUnknown())
2155 {
2156 it->second->saveToFile(fn, st, encode);
2157 return;
2158 }
2159
2160 std::pair<string_t, string_t> rootext = fileRootExtension(fn);
2161 for(cit_mustm it = suTerms_.begin(); it != suTerms_.end(); it++)
2162 {
2163 string_t fnb = rootext.first + "_" + it->first.first->name() + "_" + it->first.second->name() + "."+rootext.second;
2164 it->second->saveToFile(fnb, st, encode);
2165 }
2166 }
2167
2168 } // end of namespace xlifepp
2169