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 SuTermVector.cpp
19 \authors D. Martin, E. Lunéville
20 \since 03 apr 2012
21 \date 13 jan 2014
22
23 \brief Implementation of xlifepp::SuTermVector class members and related utilities
24 */
25
26 #include "SuTermVector.hpp"
27 #include "BilinearFormAsLinearForm.hpp"
28 #include "TermMatrix.hpp"
29 #include "geometry.h"
30 #include "utils.h"
31 #include <numeric>
32
33
34 namespace xlifepp
35 {
36 //===============================================================================
37 //member functions of SuTermVector class
38 //===============================================================================
39 //constructors, destructor, assignment
SuTermVector(SuLinearForm * sulf,const string_t & na,bool noass)40 SuTermVector::SuTermVector(SuLinearForm* sulf, const string_t& na, bool noass)
41 {
42 termType_ = _sutermVector;
43 sulf_p = sulf;
44 name_ = na;
45 if(sulf_p != 0) u_p = sulf_p->unknown();
46 else u_p = 0;
47 space_p = 0;
48 computingInfo_.noAssembly = noass;
49 entries_p = 0;
50 scalar_entries_p = 0;
51 if(sulf_p != 0) buildSubspaces(); //construct the required subspaces
52 }
53
SuTermVector(const string_t & na,const Unknown * u,Space * sp,ValueType vt,number_t n,dimen_t nv,bool noass)54 SuTermVector::SuTermVector(const string_t& na, const Unknown* u, Space* sp,
55 ValueType vt, number_t n, dimen_t nv, bool noass)
56 {
57 termType_ = _sutermVector;
58 name_ = na;
59 sulf_p = 0;
60 u_p = u;
61 space_p = sp;
62 computingInfo_.noAssembly = noass;
63 entries_p = 0;
64 scalar_entries_p = 0;
65 if(n > 0) entries_p = new VectorEntry(vt, nv, n);
66 }
67
68 //copy constructor (full copy of entries)
SuTermVector(const SuTermVector & suV)69 SuTermVector::SuTermVector(const SuTermVector& suV)
70 {
71 copy(suV);
72 }
73
74 //full copy of entries assuming SutermVector is clean
copy(const SuTermVector & suV)75 void SuTermVector::copy(const SuTermVector& suV)
76 {
77 termType_ = _sutermVector;
78 sulf_p = suV.sulf_p;
79 name_ = suV.name_;
80 u_p = suV.u_p;
81 space_p = suV.space_p;
82 subspaces = suV.subspaces;
83 computingInfo_ = suV.computingInfo_;
84 entries_p = 0;
85 scalar_entries_p = 0;
86 if(suV.entries_p != 0) entries_p = new VectorEntry(*suV.entries_p);
87 if(suV.scalar_entries_p != suV.entries_p && suV.scalar_entries_p != 0)
88 {
89 scalar_entries_p = new VectorEntry(*suV.scalar_entries_p);
90 }
91 cdofs_ = suV.cdofs_;
92 }
93
94 //SuTermVector constructor from Unknown and function (no linear form). Specialization of Function or OperatorOnFunction
95 //compute f(Mi) for all Mi,Lagrange Dof of space
96 template <>
SuTermVector(const Unknown & u,const GeomDomain & dom,const OperatorOnFunction & opf,const string_t & na,bool noass)97 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, const OperatorOnFunction& opf, const string_t& na, bool noass)
98 {
99 initFromFunction(u, dom, opf, na, noass);
100 }
101
102 template <>
SuTermVector(const Unknown & u,const GeomDomain & dom,const Function & f,const string_t & na,bool noass)103 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, const Function& f, const string_t& na, bool noass)
104 {
105 initFromFunction(u, dom, OperatorOnFunction(f), na, noass);
106 }
107
SuTermVector(const Unknown & u,const GeomDomain & dom,funSR_t & f,const string_t & na,bool noass)108 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, funSR_t& f, const string_t& na, bool noass)
109 {
110 Function F(f);
111 OperatorOnFunction opf(F);
112 initFromFunction(u, dom, opf, na, noass);
113 }
114
SuTermVector(const Unknown & u,const GeomDomain & dom,funSC_t & f,const string_t & na,bool noass)115 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, funSC_t& f, const string_t& na, bool noass)
116 {
117 Function F(f);
118 OperatorOnFunction opf(F);
119 initFromFunction(u, dom, opf, na, noass);
120 }
121
SuTermVector(const Unknown & u,const GeomDomain & dom,funVR_t & f,const string_t & na,bool noass)122 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, funVR_t& f, const string_t& na, bool noass)
123 {
124 Function F(f);
125 OperatorOnFunction opf(F);
126 initFromFunction(u, dom, opf, na, noass);
127 }
128
SuTermVector(const Unknown & u,const GeomDomain & dom,funVC_t & f,const string_t & na,bool noass)129 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, funVC_t& f, const string_t& na, bool noass)
130 {
131 Function F(f);
132 OperatorOnFunction opf(F);
133 initFromFunction(u, dom, opf, na, noass);
134 }
135
136 //specialization of SuTermVector constructor from Unknown and SymbolicFunction
137 template <>
SuTermVector(const Unknown & u,const GeomDomain & dom,const SymbolicFunction & fs,const string_t & na,bool noass)138 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, const SymbolicFunction& fs, const string_t& na, bool noass)
139 {
140 if(u.nbOfComponents() > 1)
141 {
142 where("SuTermVector::SuTermVector(Unknown, DOmain, SymbolicFunction, String, bool)");
143 error("unknown_not_vector");
144 }
145 termType_ = _sutermVector;
146 computingInfo_.noAssembly = noass;
147 name_ = na;
148 sulf_p = 0;
149 u_p = &u;
150 //find subspace or create it
151 Space* spu = u.space();
152 space_p = spu->findSubSpace(&dom, spu);
153 if(space_p == 0) space_p = new Space(dom, *spu, spu->name() + "_" + dom.name());
154 //allocate entries
155 number_t n = space_p->nbDofs();
156 entries_p = 0;
157 scalar_entries_p = 0;
158 if(n == 0) return; // no entries
159 //fill entries with fs values
160 ValueType vt = fs.valueType();
161 entries_p = new VectorEntry(vt, _scalar, n, 1);
162 if(vt == _real)
163 {
164 Vector<real_t>::iterator ite = entries_p->rEntries_p->begin();
165 for(number_t i = 1; i <= n; i++, ite++) *ite = fs(space_p->dof(i).coords());
166 }
167 else
168 {
169 Vector<complex_t>::iterator ite = entries_p->cEntries_p->begin();
170 for(number_t i = 1; i <= n; i++, ite++) *ite = fs(space_p->dof(i).coords());
171 }
172 computingInfo_.isComputed = true;
173 }
174
175 //specialization of SuTermVector constructor from Unknown and VariableName
176 template <>
SuTermVector(const Unknown & u,const GeomDomain & dom,const VariableName & vn,const string_t & na,bool noass)177 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, const VariableName& vn, const string_t& na, bool noass)
178 {
179 if(u.nbOfComponents() > 1)
180 {
181 where("SuTermVector::SuTermVector(Unknown, Domain, VariableName, String, bool)");
182 error("unknown_not_vector");
183 }
184 termType_ = _sutermVector;
185 computingInfo_.noAssembly = noass;
186 name_ = na;
187 sulf_p = 0;
188 u_p = &u;
189 //find subspace or create it
190 Space* spu = u.space();
191 space_p = spu->findSubSpace(&dom, spu);
192 if(space_p == 0) space_p = new Space(dom, *spu, spu->name() + "_" + dom.name());
193 //allocate entries
194 number_t n = space_p->nbDofs();
195 entries_p = 0;
196 scalar_entries_p = 0;
197 if(n == 0) return; // no entries
198 //create symbolic function
199 SymbolicFunction fs(vn);
200 //fill entries with fs values
201 ValueType vt = fs.valueType();
202 entries_p = new VectorEntry(vt, _scalar, n, 1);
203 if(vt == _real)
204 {
205 Vector<real_t>::iterator ite = entries_p->rEntries_p->begin();
206 for(number_t i = 1; i <= n; i++, ite++) *ite = fs(space_p->dof(i).coords());
207 }
208 else
209 {
210 Vector<complex_t>::iterator ite = entries_p->cEntries_p->begin();
211 for(number_t i = 1; i <= n; i++, ite++) *ite = fs(space_p->dof(i).coords());
212 }
213 computingInfo_.isComputed = true;
214 }
215
216 /*! apply function to SutermVector
217 build new SutermVector Y from SuTermVector X with Y(i)=f(X(i))
218 function f has to be consistent with SuTermVector coefficients
219 use a scalar function for scalar SuTermVector and vector function for vector SuTermVector
220 */
SuTermVector(const SuTermVector & X,funSR1_t & f,const string_t & na)221 SuTermVector::SuTermVector(const SuTermVector& X, funSR1_t& f, const string_t& na)
222 {
223 if(X.strucType() != _scalar || X.valueType() != _real)
224 {
225 where("SuTermVector::SuTermVector(SuTermVector, funSR1_t, String)");
226 error("value_wrongtype", words("structure", X.strucType()), words("value", X.valueType()),
227 words("structure", _scalar), words("value", _real));
228 }
229 copy(X);
230 name_ = na;
231 if(entries_p == 0 || entries_p->rEntries_p == 0)
232 {
233 where("SuTermVector::SuTermVector(SuTermVector, funSR1_t, String)");
234 error("term_no_entries");
235 }
236 Vector<real_t>::iterator itv = entries_p->rEntries_p->begin();
237 for(; itv != entries_p->rEntries_p->end(); ++itv) *itv = f(*itv);
238 if(scalar_entries_p != 0)
239 {
240 delete scalar_entries_p;
241 scalar_entries_p = 0;
242 }
243 }
244
SuTermVector(const SuTermVector & X,funSC1_t & f,const string_t & na)245 SuTermVector::SuTermVector(const SuTermVector& X, funSC1_t& f, const string_t& na)
246 {
247 if(X.strucType() != _scalar || X.valueType() != _complex)
248 {
249 where("SuTermVector::SuTermVector(SuTermVector, funSC1_t, String)");
250 error("value_wrongtype", words("structure", X.strucType()), words("value", X.valueType()),
251 words("structure", _scalar), words("value", _complex));
252 }
253 copy(X);
254 name_ = na;
255 if(entries_p == 0 || entries_p->cEntries_p == 0)
256 {
257 where("SuTermVector::SuTermVector(SuTermVector, funSC1_t, String)");
258 error("term_no_Entries");
259 }
260 Vector<complex_t>::iterator itv = entries_p->cEntries_p->begin();
261 for(; itv != entries_p->cEntries_p->end(); ++itv) *itv = f(*itv);
262 if(scalar_entries_p != 0)
263 {
264 delete scalar_entries_p;
265 scalar_entries_p = 0;
266 }
267 }
268
269 /*! apply function to two SutermVector's
270 build new SutermVector Z from SuTermVectors X and Y with Z(i)=f(X(i),Y(i))
271 */
SuTermVector(const SuTermVector & X,const SuTermVector & Y,funSR2_t & f,const string_t & na)272 SuTermVector::SuTermVector(const SuTermVector& X, const SuTermVector& Y, funSR2_t& f, const string_t& na)
273 {
274 if(X.space_p != Y.space_p)
275 {
276 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSR2_t, String);");
277 error("term_mismatch_spaces", X.space_p->name(), Y.space_p->name());
278 }
279 if(X.strucType() != _scalar || X.valueType() != _real)
280 {
281 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSR2_t, String);");
282 error("value_wrongtype", words("structure", X.strucType()), words("value", X.valueType()),
283 words("structure", _scalar), words("value", _real));
284 }
285 if(X.entries_p == 0 || Y.entries_p == 0 || X.entries_p->rEntries_p == 0 || Y.entries_p->rEntries_p == 0)
286 {
287 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSR2_t, String);");
288 error("term_no_entries");
289 }
290 if(X.entries_p->rEntries_p->size() != Y.entries_p->rEntries_p->size())
291 {
292 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSR2_t, String);");
293 error("entry_mismatch_dims", X.entries_p->rEntries_p->size(), Y.entries_p->rEntries_p->size());
294 }
295 copy(X);
296 name_ = na;
297 Vector<real_t>::iterator itv = entries_p->rEntries_p->begin(), itX = X.entries_p->rEntries_p->begin(), itY = Y.entries_p->rEntries_p->begin();
298 for(; itv != entries_p->rEntries_p->end(); ++itv, ++itX, ++itY) *itv = f(*itX, *itY);
299 if(scalar_entries_p != 0)
300 {
301 delete scalar_entries_p;
302 scalar_entries_p = 0;
303 }
304 }
305
SuTermVector(const SuTermVector & X,const SuTermVector & Y,funSC2_t & f,const string_t & na)306 SuTermVector::SuTermVector(const SuTermVector& X, const SuTermVector& Y, funSC2_t& f, const string_t& na)
307 {
308 if(X.space_p != Y.space_p)
309 {
310 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSC2_t, String);");
311 error("term_mismatch_spaces", X.space_p->name(), Y.space_p->name());
312 }
313 if(X.strucType() != _scalar || X.valueType() != _complex)
314 {
315 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSC2_t, String)");
316 error("value_wrongtype", words("structure", X.strucType()), words("value", X.valueType()),
317 words("structure", _scalar), words("value", _complex));
318 }
319 if(X.entries_p == 0 || Y.entries_p == 0 || X.entries_p->cEntries_p == 0 || Y.entries_p->cEntries_p == 0)
320 {
321 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSC2_t, String);");
322 error("term_no_entries");
323 }
324 if(X.entries_p->cEntries_p->size() != Y.entries_p->cEntries_p->size())
325 {
326 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, funSC2_t, String);");
327 error("entry_mismatch_dims", X.entries_p->cEntries_p->size(), Y.entries_p->cEntries_p->size());
328 }
329 copy(X);
330 name_ = na;
331 Vector<complex_t>::iterator itv = entries_p->cEntries_p->begin(), itX = X.entries_p->cEntries_p->begin(), itY = Y.entries_p->cEntries_p->begin();
332 for(; itv != entries_p->cEntries_p->end(); ++itv, ++itX, ++itY) *itv = f(*itX, *itY);
333 if(scalar_entries_p != 0)
334 {
335 delete scalar_entries_p;
336 scalar_entries_p = 0;
337 }
338 }
339
340 //constructor from symbolic function of TermVector's
341 /*!
342 build the SuTermVector R = fs(X) where fs is a symbolic function of x
343 when X is a scalar SuTermVector, performs
344 R(i)=fs(X(i)) i=1,n result is a scalar SuTermVector with X unknown
345 when X is a vector SuTermVector (dim=d), performs component by component
346 R_k(i)=fs(X_k(i)) i=1,n, k=1,d, result is a vector SuTermVector with X unknown
347 */
SuTermVector(const SuTermVector & X,const SymbolicFunction & fs,const string_t & na)348 SuTermVector::SuTermVector(const SuTermVector& X, const SymbolicFunction& fs, const string_t& na)
349 {
350 copy(X);
351 name_ = na;
352 bool isComplex = (fs.valueType()==_complex || X.valueType()==_complex);
353 if(isComplex && X.valueType()==_real) toComplex();
354 if(entries_p->rEntries_p != 0) //real scalar case
355 {
356 Vector<real_t>::iterator itx = X.entries_p->rEntries_p->begin();
357 if(!isComplex)
358 {
359 Vector<real_t>::iterator itr = entries_p->rEntries_p->begin();
360 for(; itr != entries_p->rEntries_p->end(); ++itx, ++itr) *itr = fs(*itx);
361 }
362 else
363 {
364 Vector<complex_t>::iterator itr = entries_p->cEntries_p->begin();
365 for(; itr != entries_p->cEntries_p->end(); ++itx, ++itr) *itr = fs(complex_t(*itx));
366 }
367 }
368 else if(entries_p->cEntries_p != 0) //complex scalar case
369 {
370 Vector<complex_t>::iterator itx = X.entries_p->cEntries_p->begin();
371 Vector<complex_t>::iterator itr = entries_p->cEntries_p->begin();
372 for(; itr != entries_p->cEntries_p->end(); ++itx,++itr) *itr = fs(*itx);
373 }
374
375 else // real/complex vector case
376 {
377 Unknown* us = const_cast<Unknown*>(X.up());
378 dimen_t nbc=us->nbOfComponents();
379 for(dimen_t k=0; k<nbc; ++k)
380 {
381 SuTermVector sut = SuTermVector(X(*(*us)[k+1].asComponent()),fs); //compute kth component
382 if(!isComplex)
383 {
384 Vector<Vector<real_t> >::iterator itr = entries_p->rvEntries_p->begin();
385 Vector<real_t>::iterator itxk = sut.entries_p->rEntries_p->begin();
386 for(; itr!=entries_p->rvEntries_p->end(); ++itr,++itxk)(*itr)[k]=*itxk;
387 }
388 else
389 {
390 Vector<Vector<complex_t> >::iterator itr = entries_p->cvEntries_p->begin();
391 Vector<complex_t>::iterator itxk = sut.entries_p->cEntries_p->begin();
392 for(; itr!=entries_p->cvEntries_p->end(); ++itr,++itxk)(*itr)[k]=*itxk;
393 }
394 }
395 }
396 if(scalar_entries_p != 0)
397 {
398 delete scalar_entries_p;
399 scalar_entries_p = 0;
400 }
401 }
402
403 /*!
404 build the SuTermVector R = fs(X1,X2) where fs is a symbolic function of x1_ x2_
405 when X1 and X2 are scalar SuTermVector, performs
406 R(i)=fs(X1(i),X2(i)) i=1,n result is a scalar SuTermVector with X1 unknown
407 when X1 is a vector SuTermVector (dim=d) and X2 a scalar SuTermvector, performs component by component
408 R_k(i)=fs(X1_k(i),X2(i)) i=1,n, k=1,d, result is a vector SuTermVector with X1 unknown
409 when X1 is a scalar SuTermVector and X2 a vector SuTermvector (dim=d), performs component by component
410 R_k(i)=fs(X1(i),X2_k(i)) i=1,n, k=1,d, result is a vector SuTermVector with X2 unknown
411 when X1 and X2 are both vector SuTermvector, computation is not available
412
413 NB : unknown can be change later using changeUnknown function
414 */
SuTermVector(const SuTermVector & X1,const SuTermVector & X2,const SymbolicFunction & fs,const string_t & na)415 SuTermVector::SuTermVector(const SuTermVector& X1, const SuTermVector& X2, const SymbolicFunction& fs, const string_t& na)
416 {
417 if(X1.space_p != X2.space_p)
418 {
419 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SymbolicFunction, String);");
420 error("term_mismatch_spaces", X1.space_p->name(), X2.space_p->name());
421 }
422 if(X1.entries_p == 0 || X2.entries_p == 0)
423 {
424 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SymbolicFunction, String)");
425 error("term_no_entries");
426 }
427
428 bool fsIsComplex = (fs.valueType()==_complex);
429 name_ = na;
430 if(X1.strucType() == _scalar && X2.strucType() ==_scalar) //scalar case
431 {
432
433 if(X1.entries_p->rEntries_p != 0) //X1 is real
434 {
435 Vector<real_t>::const_iterator itv1 = X1.entries_p->rEntries_p->begin();
436 copy(X1);
437 if(X2.entries_p->rEntries_p != 0) //X2 is real
438 {
439 if(!fsIsComplex) //real result
440 {
441 Vector<real_t>::iterator itv2 = X2.entries_p->rEntries_p->begin();
442 Vector<real_t>::iterator itvr = entries_p->rEntries_p->begin();
443 for(; itvr != entries_p->rEntries_p->end(); ++itv1, ++itv2, ++itvr) *itvr = fs(*itv1, *itv2);
444 }
445 else //complex result
446 {
447 toComplex(); //move to complex
448 Vector<real_t>::iterator itv2 = entries_p->rEntries_p->begin();
449 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
450 for(; itvr != entries_p->cEntries_p->end(); ++itv1, ++itv2, ++itvr) *itvr = fs(complex_t(*itv1), complex_t(*itv2));
451 }
452 }
453 else if(X2.entries_p->cEntries_p != 0) //X2 is complex
454 {
455 toComplex(); //move to complex
456 Vector<complex_t>::iterator itv2 = X2.entries_p->cEntries_p->begin();
457 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
458 for(; itvr != entries_p->cEntries_p->end(); ++itv1, ++itv2, ++itvr) *itvr = fs(complex_t(*itv1), *itv2);
459 }
460 }
461 else // X1 is complex, result is complex
462 {
463 copy(X1);
464 Vector<complex_t>::iterator itv1 = entries_p->cEntries_p->begin();
465 if(X2.entries_p->rEntries_p != 0) // X2 is real
466 {
467 Vector<real_t>::const_iterator itv2 = X2.entries_p->rEntries_p->begin();
468 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
469 for(; itvr != entries_p->cEntries_p->end(); ++itv1, ++itv2, ++itvr) *itv1 = fs(*itv1, complex_t(*itv2));
470 }
471 else
472 {
473 Vector<complex_t>::const_iterator itv2 = X2.entries_p->cEntries_p->begin();
474 for(; itv1 != entries_p->cEntries_p->end(); ++itv1, ++itv2) *itv1 = fs(*itv1, *itv2);
475 }
476 }
477 //remove scalar representation
478 if(scalar_entries_p != 0)
479 {
480 delete scalar_entries_p;
481 scalar_entries_p = 0;
482 }
483 return; //end of scalar case
484 }
485
486 //vector case
487 if(X1.strucType() != _scalar && X2.strucType() !=_scalar) //two vector SuTermVector not available
488 {
489 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SymbolicFunction, String)");
490 error("term_unhandled_structures", words("structure", X1.strucType()), words("structure", X2.strucType()),fs.asString());
491 }
492 Unknown* us =0;
493 dimen_t nbc=0;
494 bool isComplex = false;
495 bool X1isVector=true;
496 if(X1.strucType() != _scalar) // X1 vector, X2 scalar
497 {
498 us = const_cast<Unknown*>(X1.up());
499 nbc=us->nbOfComponents();
500 copy(X1);
501 isComplex = (fs.valueType()==_complex || X2.valueType()==_complex || X1.valueType()==_complex);
502 if(isComplex && X1.valueType()==_real) toComplex();
503 }
504 else // X2 vector, X1 scalar
505 {
506 X1isVector=false;
507 us = const_cast<Unknown*>(X2.up());
508 nbc=us->nbOfComponents();
509 copy(X2);
510 isComplex = (fs.valueType()==_complex || X2.valueType()==_complex || X1.valueType()==_complex);
511 if(isComplex && X2.valueType()==_real) toComplex();
512 }
513 for(dimen_t k=0; k<nbc; ++k)
514 {
515 SuTermVector sut;
516 if(X1isVector) sut = SuTermVector(X1(*(*us)[k+1].asComponent()),X2,fs); //compute kth component
517 else sut = SuTermVector(X1,X2(*(*us)[k+1].asComponent()),fs); //compute kth component
518 if(!isComplex)
519 {
520 Vector<Vector<real_t> >::iterator itvr = entries_p->rvEntries_p->begin();
521 Vector<real_t>::iterator itvk = sut.entries_p->rEntries_p->begin();
522 for(; itvr!=entries_p->rvEntries_p->end(); ++itvr,++itvk)(*itvr)[k]=*itvk;
523 }
524 else
525 {
526 Vector<Vector<complex_t> >::iterator itvr = entries_p->cvEntries_p->begin();
527 Vector<complex_t>::iterator itvk = sut.entries_p->cEntries_p->begin();
528 for(; itvr!=entries_p->cvEntries_p->end(); ++itvr,++itvk)(*itvr)[k]=*itvk;
529 }
530 }
531 //remove scalar representation
532 if(scalar_entries_p != 0)
533 {
534 delete scalar_entries_p;
535 scalar_entries_p = 0;
536 }
537 }
538
539 /*!
540 build the SuTermVector R = fs(X1,X2,X3) where fs is a symbolic function of x_1 x_2 x_3 :
541 R(i)=fs(X1(i),X2(i),X3(i)) i=1,n
542 X1, X2, X3 have to be three scalar SutermVectors defined on the same space
543 the unknown of the SuTermVector result is the unknown of X1
544 it can be change later using changeUnknown function
545 */
SuTermVector(const SuTermVector & X1,const SuTermVector & X2,const SuTermVector & X3,const SymbolicFunction & fs,const string_t & na)546 SuTermVector::SuTermVector(const SuTermVector& X1, const SuTermVector& X2, const SuTermVector& X3,
547 const SymbolicFunction& fs, const string_t& na)
548 {
549 if(X1.space_p != X2.space_p)
550 {
551 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SuTermVector, SymbolicFunction, String);");
552 error("term_mismatch_spaces", X1.space_p->name(), X2.space_p->name());
553 }
554 if(X1.space_p != X3.space_p)
555 {
556 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SuTermVector, SymbolicFunction, String);");
557 error("term_mismatch_spaces", X1.space_p->name(), X2.space_p->name());
558 }
559 if(X1.strucType() != _scalar)
560 {
561 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SuTermVector, SymbolicFunction, String)");
562 error("term_mismatch_structures", words("structure", X1.strucType()), words("structure", _scalar));
563 }
564 if(X2.strucType() != _scalar)
565 {
566 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SuTermVector, SymbolicFunction, String)");
567 error("term_mismatch_structures", words("structure", X2.strucType()), words("structure", _scalar));
568 }
569 if(X3.strucType() != _scalar)
570 {
571 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SuTermVector, SymbolicFunction, String)");
572 error("term_mismatch_structures", words("structure", X3.strucType()), words("structure", _scalar));
573 }
574 if(X1.entries_p == 0 || X2.entries_p == 0 || X3.entries_p == 0)
575 {
576 where("SuTermVector::SuTermVector(SuTermVector, SuTermVector, SuTermVector, SymbolicFunction, String)");
577 error("term_no_entries");
578 }
579
580 name_ = na;
581 bool fsIsComplex = (fs.valueType()==_complex);
582 ValueType vt1 = X1.valueType(), vt2 = X2.valueType(), vt3 = X3.valueType();
583 copy(X1);
584 if((vt2==_complex || vt3==_complex || fsIsComplex) && vt1==_real) toComplex();
585
586 if(vt1 == _real)
587 {
588 Vector<real_t>::const_iterator itv1 = X1.entries_p->rEntries_p->begin();
589 if(vt2 == _real)
590 {
591 Vector<real_t>::const_iterator itv2 = X2.entries_p->rEntries_p->begin();
592 if(vt3 == _real)
593 {
594 Vector<real_t>::const_iterator itv3 = X3.entries_p->rEntries_p->begin();
595 if(!fsIsComplex)
596 {
597 Vector<real_t>::iterator itvr = entries_p->rEntries_p->begin();
598 for(; itvr != entries_p->rEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(*itv1, *itv2, *itv3);
599 }
600 else
601 {
602 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
603 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(complex_t(*itv1), complex_t(*itv2), complex_t(*itv3));
604 }
605 }
606 else // X3 is complex
607 {
608 Vector<complex_t>::const_iterator itv3 = entries_p->cEntries_p->begin();
609 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
610 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(complex_t(*itv1), complex_t(*itv2), *itv3);
611 }
612 }
613 else // X2 is complex
614 {
615 Vector<complex_t>::const_iterator itv2 = entries_p->cEntries_p->begin();
616 if(vt3 == _real) //X3 is real
617 {
618 Vector<real_t>::const_iterator itv3 = X3.entries_p->rEntries_p->begin();
619 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
620 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(complex_t(*itv1), *itv2, complex_t(*itv3));
621 }
622 else //X3 is complex
623 {
624 Vector<complex_t>::const_iterator itv3 = X3.entries_p->cEntries_p->begin();
625 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
626 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(complex_t(*itv1), *itv2, *itv3);
627 }
628 }
629 }
630 else //X1 is complex
631 {
632 Vector<complex_t>::iterator itv1 = entries_p->cEntries_p->begin();
633 if(vt2 == _real) //X2 is real
634 {
635 Vector<real_t>::const_iterator itv2 = X2.entries_p->rEntries_p->begin();
636 if(vt3 == _real) //X3 is real
637 {
638 Vector<real_t>::const_iterator itv3 = X3.entries_p->rEntries_p->begin();
639 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
640 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(*itv1, complex_t(*itv2), complex_t(*itv3));
641 }
642 else //X3 is complex
643 {
644 Vector<complex_t>::const_iterator itv3 = X3.entries_p->cEntries_p->begin();
645 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
646 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(*itv1, complex_t(*itv2), *itv3);
647 }
648 }
649 else //X2 is complex
650 {
651 Vector<complex_t>::const_iterator itv2 = X2.entries_p->cEntries_p->begin();
652 if(vt3 == _real) //X3 is real
653 {
654 Vector<real_t>::const_iterator itv3 = X3.entries_p->rEntries_p->begin();
655 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
656 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(*itv1, *itv2, complex_t(*itv3));
657 }
658 else //X3 is complex
659 {
660 Vector<complex_t>::const_iterator itv3 = X3.entries_p->cEntries_p->begin();
661 Vector<complex_t>::iterator itvr = entries_p->cEntries_p->begin();
662 for(; itvr != entries_p->cEntries_p->end(); ++itvr, ++itv1, ++itv2, ++itv3) *itvr = fs(*itv1, *itv2, *itv3);
663 }
664 }
665 }
666 if(scalar_entries_p != 0)
667 {
668 delete scalar_entries_p;
669 scalar_entries_p = 0;
670 }
671 }
672
673 /*! construct vector SutermVector from 2 scalar SuTermVector's
674 scalar SuTermVector's have to be defined on the same space
675 vu has to be a vector unknown at least d=2 */
SuTermVector(const Unknown & vu,const SuTermVector & X1,const SuTermVector & X2,const string_t & na)676 SuTermVector::SuTermVector(const Unknown& vu, const SuTermVector& X1, const SuTermVector& X2, const string_t& na)
677 {
678 if(X1.strucType()!=_scalar || X2.strucType()!=_scalar)
679 {
680 where("SuTermVector::SuTermVector(Unknown, SuTermVector,SuTermVector)");
681 error("term_nonscalar");
682 }
683 number_t nbc=vu.nbOfComponents();
684 if(nbc<2)
685 {
686 where("SuTermVector::SuTermVector(Unknown, SuTermVector,SuTermVector)");
687 error("unknown_vector",2);
688 }
689 if(X1.space_p!=X2.space_p)
690 {
691 where("SuTermVector::SuTermVector(Unknown, SuTermVector,SuTermVector)");
692 error("term_mismatch_spaces", X1.space_p->name(), X2.space_p->name());
693 }
694 name_ = na;
695 ValueType vt=X1.valueType();
696 if(X2.valueType()==_complex) vt = _complex;
697 space_p=X1.space_p;
698 sulf_p=0;
699 u_p=&vu;
700 scalar_entries_p = 0;
701 entries_p=new VectorEntry(vt, _vector, X1.nbDofs(), nbc);
702 if(vt==_real)
703 {
704 Vector<real_t>::const_iterator it1 = X1.entries_p->rEntries_p->begin(),
705 it2 = X2.entries_p->rEntries_p->begin();
706 Vector<Vector<real_t> >::iterator itv = entries_p->rvEntries_p->begin();
707 for(; itv!=entries_p->rvEntries_p->end(); ++itv,++it1,++it2)
708 {(*itv)[0]=*it1; (*itv)[1]=*it2;}
709 }
710 else
711 {
712 Vector<Vector<complex_t> >::iterator itv = entries_p->cvEntries_p->begin();
713 if(X1.valueType()==_real) // X2 is complex
714 {
715 Vector<real_t>::const_iterator it1 = X1.entries_p->rEntries_p->begin();
716 Vector<complex_t>::const_iterator it2 = X2.entries_p->cEntries_p->begin();
717 for(; itv!=entries_p->cvEntries_p->end(); ++itv,++it1,++it2)
718 {(*itv)[0]=*it1; (*itv)[1]=*it2;}
719 }
720 else //X1 is complex
721 {
722 if(X2.valueType()==_real) // X2 is real
723 {
724 Vector<complex_t>::const_iterator it1 = X1.entries_p->cEntries_p->begin();
725 Vector<real_t>::const_iterator it2 = X2.entries_p->rEntries_p->begin();
726 for(; itv!=entries_p->cvEntries_p->end(); ++itv,++it1,++it2)
727 {(*itv)[0]=*it1; (*itv)[1]=*it2;}
728 }
729 else //X3 complex
730 {
731 Vector<complex_t>::const_iterator it1 = X1.entries_p->cEntries_p->begin();
732 Vector<complex_t>::const_iterator it2 = X2.entries_p->cEntries_p->begin();
733 for(; itv!=entries_p->cvEntries_p->end(); ++itv,++it1,++it2)
734 {(*itv)[0]=*it1; (*itv)[1]=*it2;}
735 }
736 }
737 }
738 computingInfo_.isComputed = true;
739 }
740
741 /*! construct vector SutermVector from n scalar SuTermVector's
742 scalar SuTermVector's have to be defined on the same space
743 vu has to be a vector unknown at least n */
SuTermVector(const Unknown & vu,const std::list<const SuTermVector * > & Xs,const string_t & na)744 SuTermVector::SuTermVector(const Unknown& vu, const std::list<const SuTermVector*>& Xs, const string_t& na)
745 {
746 number_t nbX=Xs.size();
747 if(nbX<2)
748 {
749 where("SuTermVector::SuTermVector(Unknown,list<const SuTermVector*>)");
750 error("term_not_enough",2);
751 }
752 number_t nbc=vu.nbOfComponents();
753 if(nbc<nbX)
754 {
755 where("SuTermVector::SuTermVector(Unknown,list<const SuTermVector*>)");
756 error("unknown_vector",nbX);
757 }
758 Space* sp=0;
759 ValueType vt=_real;
760 std::list<const SuTermVector*>::const_iterator itX=Xs.begin();
761 sp=(*itX)->space_p;
762 number_t n=(*itX)->nbDofs();
763 for(; itX!=Xs.end(); ++itX)
764 {
765 const SuTermVector& X=**itX;
766 if(X.space_p!=sp)
767 {
768 where("SuTermVector::SuTermVector(Unknown,list<const SuTermVector*>)");
769 error("term_mismatch_spaces", X.space_p->name(), sp->name());
770 }
771 if(X.valueType()==_complex) vt=_complex;
772 }
773 name_ = na;
774 space_p=sp;
775 sulf_p=0;
776 u_p=&vu;
777 scalar_entries_p = 0;
778 entries_p=new VectorEntry(vt, _vector, n, nbc);
779 if(vt==_real) //all SuTermVector are real
780 {
781 std::list<Vector<real_t>::const_iterator> itlist;
782 for(itX=Xs.begin(); itX!=Xs.end(); ++itX) itlist.push_back((*itX)->entries_p->rEntries_p->begin());
783 std::list<Vector<real_t>::const_iterator>::iterator itl;
784 Vector<Vector<real_t> >::iterator itv = entries_p->rvEntries_p->begin();
785 for(; itv!=entries_p->rvEntries_p->end(); ++itv)
786 {
787 Vector<real_t>::iterator it=itv->begin();
788 for(itl=itlist.begin(); itl!=itlist.end(); ++it,++itl) {*it=**itl; (*itl)++;}
789 }
790 }
791 else // complex result
792 {
793 Vector<Vector<complex_t> >::iterator itv;
794 number_t k=0;
795 for(itX=Xs.begin(); itX!=Xs.end(); ++itX, k++)
796 {
797 const SuTermVector& X=**itX;
798 if(X.valueType()==_real)
799 {
800 Vector<real_t>::const_iterator it=X.entries_p->rEntries_p->begin();
801 for(itv = entries_p->cvEntries_p->begin(); itv!=entries_p->cvEntries_p->end(); ++itv,++it)(*itv)[k]=*it;
802 }
803
804 else
805 {
806 Vector<complex_t>::const_iterator it=X.entries_p->cEntries_p->begin();
807 for(itv = entries_p->cvEntries_p->begin(); itv!=entries_p->cvEntries_p->end(); ++itv,++it)(*itv)[k]=*it;
808 }
809 }
810 }
811 computingInfo_.isComputed = true;
812 }
813
initFromFunction(const Unknown & u,const GeomDomain & dom,const OperatorOnFunction & opf,const string_t & na,bool noass)814 void SuTermVector::initFromFunction(const Unknown& u, const GeomDomain& dom, const OperatorOnFunction& opf,
815 const string_t& na, bool noass)
816 {
817 termType_ = _sutermVector;
818 computingInfo_.noAssembly = noass;
819 name_ = na;
820 sulf_p = 0;
821 u_p = &u;
822
823 //find subspace or create it
824 Space* spu = u.space();
825 space_p = spu->findSubSpace(&dom, spu);
826 if(space_p == 0) space_p = new Space(dom, *spu, spu->name() + "_" + dom.name());
827
828 //allocate entries
829 number_t n = space_p->nbDofs(), nv = number_t(u.nbOfComponents());
830 entries_p = 0;
831 scalar_entries_p = 0;
832 if(n == 0) return; // no entries
833
834 //check structure of function
835 if(opf.strucType()==_matrix)
836 {
837 where("SuTermVector::initFromFunction(Unknown, Domain, OperatorOnFunction, String, bool)");
838 error("scalar_or_vector");
839 }
840 if(nv != opf.dims().first)
841 {
842 where("SuTermVector::initFromFunction(Unknown, Domain, OperatorOnFunction, String, bool)");
843 error("operator_fct_mismatch_dims", nv, opf.dims().first);
844 }
845
846 //compute normal vectors if function required them (function parameters contains "_n" parameter)
847 bool nor = opf.normalRequired(), norf = opf.funp()->requireNx;
848 const MeshDomain* mdom = dom.meshDomain();
849 if(mdom == 0)
850 {
851 where("SuTermVector::initFromFunction(Unknown, Domain, OperatorOnFunction, String, bool)");
852 error("domain_notmesh", dom.name(), words("domain type", dom.domType()));
853 }
854
855 if(nor && !(mdom->isSideDomain() || mdom->spaceDim() > mdom->dim())) //when function has "_n" as parameter but computation does not occur on a side domain
856 {
857 where("SuTermVector::initFromFunction(Unknown, Domain, OperatorOnFunction, String, bool)");
858 warning("normal_ignored",mdom->name());
859 nor = false;
860 }
861 std::vector<Vector<real_t> > ns;
862 if(nor)
863 {
864 if(dom.meshDomain() == 0)
865 {
866 where("SuTermVector::initFromFunction(const Unknown&, const GeomDomain&, const OperatorOnFunction&, const String&, bool)");
867 error("domain_notmesh", dom.name(), words("domain type", dom.domType()));
868 }
869 if(!dom.meshDomain()->orientationComputed) dom.meshDomain()->setNormalOrientation();
870 interpolatedNormals(*space_p, ns);
871 }
872
873 //flag to transmit dof pointer tp function parameters
874 bool assDof = opf.funp()->requireDof;
875
876 //fill entries with f values
877 Vector<real_t>* np = 0;
878 ValueType vt = opf.valueType();
879 StrucType st = opf.strucType();
880 entries_p = new VectorEntry(vt, st, n, nv);
881 if(vt == _real)
882 {
883 if(st == _scalar)
884 {
885 Vector<real_t>::iterator ite = entries_p->rEntries_p->begin();
886 #ifdef XLIFEPP_WITH_OMP
887 #pragma omp parallel for firstprivate(np)
888 #endif // XLIFEPP_WITH_OMP
889 for(number_t i = 0; i < n; i++)
890 {
891 if(nor)
892 {
893 np = &ns[i];
894 if(norf) setNx(np);
895 }
896 if(assDof) setDof(const_cast<Dof*>(&space_p->dof(i + 1)));
897 opf.eval(space_p->dof(i + 1).coords(), *(ite+i), np);
898 }
899 }
900 if(st == _vector)
901 {
902 Vector<Vector<real_t> >::iterator ite = entries_p->rvEntries_p->begin();
903 #ifdef XLIFEPP_WITH_OMP
904 #pragma omp parallel for firstprivate(np)
905 #endif // XLIFEPP_WITH_OMP
906 for(number_t i = 0; i < n; i++)
907 {
908 if(nor)
909 {
910 np = &ns[i];
911 if(norf) setNx(np);
912 }
913 if(assDof) setDof(const_cast<Dof*>(&space_p->dof(i + 1)));
914 opf.eval(space_p->dof(i + 1).coords(), *(ite+i), np);
915 }
916 }
917 }
918 if(vt == _complex)
919 {
920 if(st == _scalar)
921 {
922 Vector<complex_t>::iterator ite = entries_p->cEntries_p->begin();
923 #ifdef XLIFEPP_WITH_OMP
924 #pragma omp parallel for firstprivate(np)
925 #endif // XLIFEPP_WITH_OMP
926 for(number_t i = 0; i < n; i++)
927 {
928 if(nor)
929 {
930 np = &ns[i];
931 if(norf) setNx(np);
932 }
933 if(assDof) setDof(const_cast<Dof*>(&space_p->dof(i + 1)));
934 opf.eval(space_p->dof(i + 1).coords(), *(ite+i), np);
935 }
936 }
937 if(st == _vector)
938 {
939 Vector<Vector<complex_t> >::iterator ite = entries_p->cvEntries_p->begin();
940 #ifdef XLIFEPP_WITH_OMP
941 #pragma omp parallel for firstprivate(np)
942 #endif // XLIFEPP_WITH_OMP
943 for(number_t i = 0; i < n; i++)
944 {
945 if(nor)
946 {
947 np = &ns[i];
948 if(norf) setNx(np);
949 }
950 if(assDof) setDof(const_cast<Dof*>(&space_p->dof(i + 1)));
951 opf.eval(space_p->dof(i + 1).coords(), *(ite+i), np);
952 }
953 }
954 }
955 computingInfo_.isComputed = true;
956 }
957
958 /*! SuTermVector from the restriction of a SuTermVector to a given domain dom
959 raise an error if dom does not intersect the SutermVector domain
960 SutermVector sutv has to be computed and its entries_p has to be non zero
961 In case of entries_p==0 and scalar_entries_p!=0 goto vector representation before calling this
962 */
SuTermVector(const SuTermVector & sutv,const GeomDomain & dom,const string_t & na)963 SuTermVector::SuTermVector(const SuTermVector& sutv, const GeomDomain& dom, const string_t& na)
964 {
965 termType_ = _sutermVector;
966 sulf_p = 0;
967 u_p = 0;
968 space_p = 0;
969 entries_p = 0;
970 scalar_entries_p = 0;
971 if(!sutv.computed())
972 {
973 where("SuTermVector::SuTermVector");
974 error("not_computed_term", sutv.name());
975 }
976 if(domain() == &dom) //same domain
977 {
978 copy(sutv);
979 where("SuTermVector::SuTermVector");
980 warning("free_warning", "SuTermVector(SuTermVector,GeomDomain): no restriction to do, full copy");
981 }
982
983 Space* spu = sutv.u_p->space();
984 space_p = spu->findSubSpace(&dom, spu);
985 if(space_p == 0) space_p = new Space(dom, *spu, spu->name() + "_" + dom.name());
986 u_p = sutv.u_p;
987 number_t n = space_p->nbDofs(), nv = number_t(sutv.u_p->nbOfComponents());
988 if(n == 0)
989 {
990 where("SuTermVector::SuTermVector");
991 error("space_no_dof", space_p->name());
992 }
993 VectorEntry* ove = sutv.entries_p;
994 VectorEntry* sove = sutv.scalar_entries_p;
995 if(ove == 0) //no standard entries
996 {
997 if(sove == 0)
998 {
999 where("SuTermVector::SuTermVector");
1000 error("term_no_entries");
1001 }
1002 else
1003 {
1004 where("SuTermVector::SuTermVector");
1005 error("entry_inconsistent_structure");
1006 }
1007 }
1008
1009 std::vector<number_t> r = renumber(spu, space_p);
1010 number_t p = number_t(r.size());
1011 if(n == 0) //no renumbering, copy all entries
1012 {
1013 entries_p = new VectorEntry(*sutv.entries_p);
1014 }
1015 else
1016 {
1017 entries_p = new VectorEntry(sutv.entries_p->valueType_, sutv.entries_p->strucType_, p, nv);
1018 std::vector<number_t>::iterator itr = r.begin();
1019 number_t k = 1;
1020 for(; itr != r.end(); itr++, k++)
1021 {
1022 number_t i = *itr;
1023 if(i != 0) entries_p->setValue(k, ove->getValue(i));
1024 }
1025 }
1026 computingInfo_.isComputed = true;
1027 }
1028
1029 // SuTermVector from a linear combination of SuTermVector's
SuTermVector(const LcTerm<SuTermVector> & lc)1030 SuTermVector::SuTermVector(const LcTerm<SuTermVector>& lc)
1031 {
1032 termType_ = _sutermVector;
1033 sulf_p = 0;
1034 u_p = 0;
1035 space_p = 0;
1036 entries_p = 0;
1037 scalar_entries_p = 0;
1038 compute(lc);
1039 }
1040
1041 // assign operator (full copy)
operator =(const SuTermVector & suV)1042 SuTermVector& SuTermVector::operator=(const SuTermVector& suV)
1043 {
1044 clear();
1045 copy(suV);
1046 return *this;
1047 }
1048
1049 /*! construct SuTermVector from a SuTermVector with geometrical mapping, the unknowns may differ
1050 this process involves mesh interpolation and is restricted to Lagrange interpolation spaces
1051 it is assumed that the two unknowns have same structure
1052 - if fmap =0, identity is assumed
1053 - if errorOnOutDom = true the program stop on error, else the interpolated value is set to 0
1054 */
SuTermVector(const Unknown & u,const GeomDomain & dom,const SuTermVector & sut,const Function * fmap,bool errorOnOutDom,const string_t & na)1055 SuTermVector::SuTermVector(const Unknown& u, const GeomDomain& dom, const SuTermVector& sut,
1056 const Function* fmap, bool errorOnOutDom, const string_t& na)
1057 {
1058 termType_ = _sutermVector;
1059 name_ = na;
1060 sulf_p = 0;
1061 u_p = &u;
1062 Space* spu = u.space();
1063 space_p = spu->findSubSpace(&dom, spu);
1064 if(space_p == 0) space_p = new Space(dom, *spu, spu->name() + "_" + dom.name());
1065 number_t n = space_p->nbDofs(), nv = number_t(u.nbOfComponents());
1066 entries_p = 0;
1067 scalar_entries_p = 0;
1068 if(!sut.computed())
1069 {
1070 where("SuTermVector::SuTermVector");
1071 error("not_computed_term", "SuTermVector");
1072 }
1073 //if (nv!=sut.nbOfComponents())
1074 if(nv != sut.entries()->nbOfComponents)
1075 {
1076 where("SuTermVector::SuTermVector");
1077 error("term_mismatch_nb_components", nv, sut.entries()->nbOfComponents);
1078 }
1079 if(!spu->isFE())
1080 {
1081 where("SuTermVector::SuTermVector");
1082 error("not_fe_space_type", spu->name());
1083 }
1084 if(spu->feSpace()->interpolation()->type != _Lagrange)
1085 {
1086 where("SuTermVector::SuTermVector");
1087 error("lagrange_fe_space_only", spu->name());
1088 }
1089 ValueType vt = sut.valueType();
1090 StrucType st = sut.strucType();
1091 entries_p = new VectorEntry(vt, st, n, nv);
1092 //prepare interpolation
1093 Space* spdom = sut.space_p;
1094 const MeshDomain* mdom = spdom->domain()->meshDomain();
1095 mdom->buildKdTree(); //if not exist, create kdtree for fast location of points
1096 std::map<GeomElement*, const Element*> gelt2elt;
1097
1098 for(number_t k = 0; k < spdom->nbOfElements(); k++)
1099 {
1100 const Element* elt = spdom->element_p(k);
1101 gelt2elt[elt->geomElt_p] = elt;
1102 }
1103 std::vector<real_t> v;
1104 //do interpolation
1105 if(vt == _real)
1106 {
1107 if(st == _scalar)
1108 {
1109 Vector<real_t>::iterator ite = entries_p->rEntries_p->begin();
1110 for(number_t i = 0; i < n; i++, ite++)
1111 {
1112 Point pt = space_p->dof(i + 1).coords();
1113 if(fmap != 0) pt = (*fmap)(space_p->dof(i + 1).coords(), v); //map to dom
1114 GeomElement* gelt = mdom->locate(pt);
1115 if(gelt == 0)
1116 {
1117 if(errorOnOutDom) locateError("in SutermVector constructor with mapping", *mdom, pt);
1118 *ite = 0.;
1119 }
1120 else
1121 {
1122 const Element* elt = gelt2elt[gelt];
1123 elt->interpolate(*sut.entries_p, pt, elt->dofNumbers, *ite);
1124 }
1125 }
1126 }
1127 if(st == _vector)
1128 {
1129 Vector<Vector<real_t> >::iterator ite = entries_p->rvEntries_p->begin();
1130 Vector<real_t> zero(nv, 0.);
1131 for(number_t i = 0; i < n; i++, ite++)
1132 {
1133 Point pt = space_p->dof(i + 1).coords();
1134 if(fmap != 0) pt = (*fmap)(space_p->dof(i + 1).coords(), v); //map to dom
1135 GeomElement* gelt = mdom->locate(pt);
1136 if(gelt == 0)
1137 {
1138 if(errorOnOutDom) locateError("in SutermVector constructor with mapping", *mdom, pt);
1139 *ite = zero;
1140 }
1141 else
1142 {
1143 const Element* elt = gelt2elt[gelt];
1144 elt->interpolate(*sut.entries_p, pt, elt->dofNumbers, *ite);
1145 }
1146 }
1147 }
1148 }
1149 if(vt == _complex)
1150 {
1151 if(st == _scalar)
1152 {
1153 Vector<complex_t>::iterator ite = entries_p->cEntries_p->begin();
1154 for(number_t i = 0; i < n; i++, ite++)
1155 {
1156 Point pt = space_p->dof(i + 1).coords();
1157 if(fmap != 0) pt = (*fmap)(space_p->dof(i + 1).coords(), v); //map to dom
1158 GeomElement* gelt = mdom->locate(pt);
1159 if(gelt == 0)
1160 {
1161 if(errorOnOutDom) locateError("in SutermVector constructor with mapping", *mdom, pt);
1162 *ite = 0.;
1163 }
1164 else
1165 {
1166 const Element* elt = gelt2elt[gelt];
1167 elt->interpolate(*sut.entries_p, pt, elt->dofNumbers, *ite);
1168 }
1169 }
1170 }
1171 if(st == _vector)
1172 {
1173 Vector<Vector<complex_t> >::iterator ite = entries_p->cvEntries_p->begin();
1174 Vector<complex_t> zero(nv, 0.);
1175 for(number_t i = 0; i < n; i++, ite++)
1176 {
1177 Point pt = space_p->dof(i + 1).coords();
1178 if(fmap != 0) pt = (*fmap)(space_p->dof(i + 1).coords(), v); //map to dom
1179 GeomElement* gelt = mdom->locate(pt);
1180 if(gelt == 0)
1181 {
1182 if(errorOnOutDom) locateError("in SutermVector constructor with mapping", *mdom, pt);
1183 *ite = zero;
1184 }
1185 else
1186 {
1187 const Element* elt = gelt2elt[gelt];
1188 elt->interpolate(*sut.entries_p, pt, elt->dofNumbers, *ite);
1189 }
1190 }
1191 }
1192 }
1193 computingInfo_.isComputed = true;
1194 }
1195
1196 /*! produce the mapped SuTermVector from current GeomDomains to GeomDomain dom
1197 current SuTermVector has to be already computed
1198 */
mapTo(const GeomDomain & dom,const Unknown & u,bool errOnOut) const1199 SuTermVector* SuTermVector::mapTo(const GeomDomain& dom, const Unknown& u, bool errOnOut) const
1200 {
1201 trace_p->push("SuTermVector::mapTo");
1202 if(!computed()) error("not_computed_term", "SuTermVector");
1203 SuTermVector* sut = 0;
1204 const GeomDomain* curdom = domain();
1205 if(curdom == 0) error("null_pointer", "domain");
1206 const Function* fmap = findMap(dom, *curdom); // find map between domains
1207 //if (fmap==0) error("domain_map_undefined",dom.name(),curdom->name());
1208 //const GeomDomain* udom = u.space()->domain();
1209 //if (udom!= &dom && !udom->include(dom)) error("domain_not_subdomain",dom.name(),udom->name());
1210 //create new SuTermVector
1211 sut = new SuTermVector(u, dom, *this, fmap, errOnOut, name_ + "mapto_" + dom.name());
1212 trace_p->pop();
1213 return sut;
1214 }
1215
1216 /*! extract unknown component term vector as a SuTermVector, create a SuTermVector
1217 this function must be called from TermVector class in order to encapsulate SuTermVector in a TermVector
1218 */
operator ()(const ComponentOfUnknown & cu) const1219 SuTermVector SuTermVector::operator()(const ComponentOfUnknown& cu) const
1220 {
1221 if(cu.parent() != u_p)
1222 {
1223 where("SuTermVector::operator()");
1224 error("term_wrong_unknown", name_, u_p->name(), cu.parent()->name());
1225 }
1226 if(cu.componentIndex() > nbOfComponents())
1227 {
1228 where("SuTermVector::operator()");
1229 error("term_wrong_unknown_component", name_, cu.componentIndex(), nbOfComponents());
1230 }
1231 if(nbOfComponents() == 1)
1232 {
1233 where("SuTermVector::operator()");
1234 error("unknown_not_scalar");
1235 }
1236 string_t na = name() + "_" + tostring(cu.componentIndex());
1237 SuTermVector su(na, &cu, space_p, valueType(), size(), 1, false); //create a scalar SuTermVector
1238 su.entries_p->extractComponent(*entries_p, cu.componentIndex());
1239 su.computed() = true;
1240 return su;
1241 }
1242
1243 /*! move SuTermVector unknown to an other one
1244 consist in changing the unknown u of SuTermVector by the unknown v (u and v must be defined on the same Space!)
1245 with an optionnal management of components of unknown, examples
1246 u a scalar unknown and v a scalar unknown : SuTermVector if not modified
1247 u a scalar unknown and v a 3 vector unknown, ci ={2} the SuTermVector is changed to a 3 column vector :
1248 new sutv=[ [0...0] [sutv] [0...0] ]
1249 u a 3-vector unknown and v a 3-vector unknown, ci ={2 3 1} the SuTermVector is changed columns are permuted :
1250 new sutv=[ [sutv2] [sutv3] [sutv1] ] v may be equal to u in that case
1251 u a 4-vector unknown and v a 2-vector unknown, ci ={2 4} the SuTermVector is changed :
1252 new sutv=[ [sutv2] [sutv4] ]
1253 u a 4-vector unknown and v a 3-vector unknown, ci ={2 0 4} the SuTermVector is changed :
1254 new sutv=[ [sutv2] [0...0] [sutv4] ]
1255 u is replaced by v,
1256 v may be equal to u but be cautious if the result is not of the dimension of v because many operations are not supported
1257 in doubt, create a new unknown of the consistent dimension
1258 */
1259
changeUnknown(const Unknown & v,const Vector<number_t> & ci)1260 void SuTermVector::changeUnknown(const Unknown& v, const Vector<number_t>& ci)
1261 {
1262 dimen_t du = u_p->nbOfComponents(), dv = v.nbOfComponents();
1263 if(ci.size() == 0 || (du == 1 && dv == 1))
1264 {
1265 if(u_p != &v) u_p = &v;
1266 return;
1267 }
1268 if(entries_p == 0)
1269 {
1270 where("SuTermVector::changeUnknown");
1271 error("null_pointer", "entries_p");
1272 }
1273 entries_p->moveColumns(ci);
1274 }
1275
1276 //destructor
~SuTermVector()1277 SuTermVector::~SuTermVector()
1278 {
1279 if(entries_p != 0) delete entries_p; //delete entries
1280 if(scalar_entries_p != entries_p && scalar_entries_p != 0) delete scalar_entries_p; //delete scalar entries
1281 }
1282
1283 // size of SuTermvector counted in scalar
size() const1284 number_t SuTermVector::size() const
1285 {
1286 if(entries_p != 0) return entries_p->size() * (u_p->nbOfComponents());
1287 if(scalar_entries_p != 0) return scalar_entries_p->size();
1288 return 0;
1289 }
1290
1291
1292 // size of Termvector counted in dofs
nbDofs() const1293 number_t SuTermVector::nbDofs() const
1294 {
1295 return space_p->nbDofs();
1296 }
1297
1298 //return n-th dof of unknown (n>=1)
dof(number_t n) const1299 const Dof& SuTermVector::dof(number_t n) const
1300 {
1301 return space_p->dof(n);
1302 }
1303
1304 // return geometric domain pointer attached to SuTermVector (may be 0)
domain() const1305 const GeomDomain* SuTermVector::domain() const
1306 {
1307 if(space_p == 0) return 0; //no space -> no domain
1308 return space_p->domain();
1309 }
1310
1311 // restriction of SuTermVector to a domain, return a pointer. May be null if dom does not intersect SuTermVector domain
onDomain(const GeomDomain & dom) const1312 SuTermVector* SuTermVector::onDomain(const GeomDomain& dom) const
1313 {
1314 SuTermVector* sutv = new SuTermVector(*this, dom);
1315 if(sutv->size() == 0)
1316 {
1317 delete sutv;
1318 return 0;
1319 }
1320 else return sutv;
1321 }
1322
1323 //deallocate memory used by a SuTermVector
clear()1324 void SuTermVector::clear()
1325 {
1326 if(entries_p != 0) delete entries_p;
1327 if(scalar_entries_p != entries_p && scalar_entries_p != 0) delete scalar_entries_p;
1328 cdofs_.clear();
1329 entries_p = 0;
1330 scalar_entries_p = 0;
1331 computed() = false;
1332 }
1333
1334 //! set of unknown spaces involved
unknownSpaces() const1335 std::set<const Space*> SuTermVector::unknownSpaces() const
1336 {
1337 std::set<const Space*>sps;
1338 if(u_p != 0) sps.insert(u_p->space());
1339 return sps;
1340 }
1341
1342 // return the actual pointer to entries (priority to scalar entry), return 0 is no allocated pointer
actual_entries() const1343 VectorEntry* SuTermVector::actual_entries() const
1344 {
1345 VectorEntry* ve = scalar_entries_p;
1346 if(ve != 0) return ve;
1347 return entries_p;
1348 }
1349
1350 //direct value managment (n>=1)
getValue(number_t n) const1351 Value SuTermVector::getValue(number_t n) const
1352 {
1353 if(entries_p == 0)
1354 {
1355 where("SuTermVector::getValue");
1356 error("null_pointer", "entries_p");
1357 }
1358 return entries_p->getValue(n);
1359 }
1360
setValue(number_t n,const Value & val)1361 void SuTermVector::setValue(number_t n, const Value& val)
1362 {
1363 if(entries_p == 0)
1364 {
1365 where("SuTermVector::setValue");
1366 error("null_pointer", "entries_p");
1367 }
1368 entries_p->setValue(n, val);
1369 }
1370
1371 /*! set dof values of SutermVector on a GeomDomainfrom from Value : u_i = v for all dof i on dom
1372 does not change other values
1373 dom has to be a subdomain of the domain of the currrent SuTermVector
1374 be cautious when Space is not a FE Lagrange space because does not imply that u=v on dom in the meaning of function*/
setValue(const Value & v,const GeomDomain & dom)1375 void SuTermVector::setValue(const Value& v, const GeomDomain& dom)
1376 {
1377 //check space type
1378 Space* sp = u_p->space();
1379
1380 //check value type
1381 StrucType st=strucType();
1382 ValueType vt=valueType();
1383 if(st!=v.strucType() || (vt==_real && v.valueType()!=_real))
1384 {
1385 where("SuTermVector::setValue(Value, Domain)");
1386 error("value_wrongtype", words("structure", st), "(" + words("value", vt) + ", " + words("value", v.valueType()) + ")",
1387 words("structure", v.strucType()), "(" + words("value", _real) + ", " + words("value", _real) + ")");
1388 }
1389
1390 std::vector<number_t> rks;
1391 bool samedom= (domain() == &dom);
1392 if(!samedom) //not same domain, get numberings
1393 {
1394 //get dof numbers of current SuTermVector, dof numbers of domain dom
1395 std::vector<number_t> curdofids = space_p->dofIds();
1396 std::vector<number_t> domdofids;
1397 Space* subsp=Space::findSubSpace(&dom,sp);
1398 if(subsp!=0) domdofids = subsp->dofIds(); //dofs of subspace related to dom
1399 else // built dof using dofsOn function
1400 {
1401 const_cast<GeomDomain&>(dom).updateParentOfSideElements();
1402 domdofids = sp->feSpace()->dofsOn(dom); //dofs located on dom
1403 }
1404 number_t nd=domdofids.size();
1405 if(nd==0)
1406 {
1407 where("SuTermVector::setValue(Value, Domain)");
1408 error("dof_not_found");
1409 }
1410 rks.resize(nd,0);
1411 ranks(curdofids,domdofids,rks); // costly find, to improve
1412 }
1413
1414 //fill value
1415 VectorEntry* ve=entries_p;
1416 if(ve==0) ve=scalar_entries_p;
1417 if(ve==0)
1418 {
1419 where("SuTermVector::setValue(Value, Domain)");
1420 error("term_no_entries");
1421 }
1422 std::vector<number_t>::iterator itn=rks.begin();
1423 switch(st)
1424 {
1425 case _scalar:
1426 if(vt==_real)
1427 {
1428 real_t r = v.asReal();
1429 Vector<real_t>::iterator it= ve->rEntries_p->begin();
1430 if(samedom)
1431 for(; it!=ve->rEntries_p->end(); ++it) *it = r;
1432 else
1433 for(; itn!=rks.end(); ++itn)
1434 if(*itn!=0) *(it + *itn-1) = r;
1435 }
1436 else
1437 {
1438 complex_t c = 0.;
1439 if(v.valueType()==_real) c=v.asReal();
1440 else c=v.asComplex();
1441 Vector<complex_t>::iterator it= ve->cEntries_p->begin();
1442 if(samedom)
1443 for(; it!=ve->cEntries_p->end(); ++it) *it = c;
1444 else
1445 for(; itn!=rks.end(); ++itn)
1446 if(*itn!=0) *(it + *itn-1) = c;
1447 }
1448 break;
1449 case _vector:
1450 if(vt==_real)
1451 {
1452 Vector<real_t> rs=v.asRealVector();
1453 Vector<Vector<real_t> >::iterator it= ve->rvEntries_p->begin();
1454 if(samedom)
1455 for(; it!=ve->rvEntries_p->end(); ++it) *it = rs;
1456 else
1457 for(; itn!=rks.end(); ++itn)
1458 if(*itn!=0) *(it + *itn-1) = rs;
1459 }
1460 else
1461 {
1462 Vector<complex_t> cs;
1463 if(v.valueType()==_real) cs=v.asRealVector();
1464 else cs=v.asComplexVector();
1465 Vector<Vector<complex_t> >::iterator it= ve->cvEntries_p->begin();
1466 if(samedom)
1467 for(; it!=ve->cvEntries_p->end(); ++it) *it=cs;
1468 else
1469 for(; itn!=rks.end(); ++itn)
1470 if(*itn!=0) *(it + *itn-1) = cs;
1471 }
1472 break;
1473 default:
1474 where("SuTermVector::setValue(Value, Domain)");
1475 error("scalar_or_vector");
1476 }
1477 }
1478
1479 /*! set dof values of GeomDomain from Function : u_i = f(M_i) for all dof i on dom, M_i point support of dof i
1480 does not change other values
1481 restricted to FE space
1482 dom has to be a subdomain of the domain of the currrent SuTermVector
1483 be cautious when Space is not a FE Lagrange space, because does not imply that u=f on dom in the meaning of function */
setValue(const Function & f,const GeomDomain & dom)1484 void SuTermVector::setValue(const Function& f, const GeomDomain& dom)
1485 {
1486 //check space type
1487 Space* sp = u_p->space();
1488 if(sp->typeOfSpace() != _feSpace)
1489 {
1490 where("SuTermVector::setValue(Function, Domain)");
1491 error("not_fe_space_type", sp->name());
1492 }
1493 //check value type
1494 StrucType st=strucType();
1495 ValueType vt=valueType();
1496 if(st!=f.strucType() || (vt==_real && f.valueType()!=_real))
1497 {
1498 where("SuTermVector::setValue(Function, Domain)");
1499 error("value_wrongtype", words("structure", st), "(" + words("value", vt) + ", " + words("value", f.valueType()) + ")",
1500 words("structure", f.strucType()), "(" + words("value", _real) + ", " + words("value", _real) + ")");
1501 }
1502
1503 std::vector<number_t> rks;
1504 bool samedom= (domain() == &dom);
1505 if(!samedom) //not same domain, get numberings
1506 {
1507 //get dof numbers of current SuTermVector, dof numbers of domain dom
1508 std::vector<number_t> curdofids = space_p->dofIds();
1509 std::vector<number_t> domdofids;
1510 Space* subsp=Space::findSubSpace(&dom,sp);
1511 if(subsp!=0) domdofids = subsp->dofIds(); //dofs of subspace related to dom
1512 else // built dof using dofsOn function
1513 {
1514 const_cast<GeomDomain&>(dom).updateParentOfSideElements();
1515 domdofids = sp->feSpace()->dofsOn(dom); //dofs located on dom
1516 }
1517 number_t nd=domdofids.size();
1518 if(nd==0)
1519 {
1520 where("SuTermVector::setValue(Function, Domain)");
1521 error("dof_not_found");
1522 }
1523 rks.resize(nd,0);
1524 ranks(curdofids,domdofids,rks); // costly find, to improve
1525 }
1526 else rks=trivialNumbering<number_t>(1,space_p->nbDofs());
1527
1528 //fill value
1529 VectorEntry* ve=entries_p;
1530 if(ve==0) ve=scalar_entries_p;
1531 if(ve==0)
1532 {
1533 where("SuTermVector::setValue(Function, Domain)");
1534 error("term_no_entries");
1535 }
1536 std::vector<number_t>::iterator itn=rks.begin();
1537 switch(st)
1538 {
1539 case _scalar:
1540 if(vt==_real)
1541 {
1542 Vector<real_t>::iterator it= ve->rEntries_p->begin();
1543 real_t r;
1544 for(; itn!=rks.end(); ++itn)
1545 if(*itn!=0) *(it + *itn-1) = f(sp->dof(*itn).coords(),r);
1546 }
1547 else
1548 {
1549 real_t r;
1550 complex_t c = 0.;
1551 Vector<complex_t>::iterator it= ve->cEntries_p->begin();
1552 for(; itn!=rks.end(); ++itn)
1553 if(*itn!=0)
1554 {
1555 if(f.valueType()==_real) *(it + *itn-1) = f(sp->dof(*itn).coords(),r);
1556 else *(it + *itn-1) = f(sp->dof(*itn).coords(),c);
1557 }
1558 }
1559 break;
1560 case _vector:
1561 if(vt==_real)
1562 {
1563 Vector<real_t> rs;
1564 Vector<Vector<real_t> >::iterator it= ve->rvEntries_p->begin();
1565 for(; itn!=rks.end(); ++itn)
1566 if(*itn!=0) *(it + *itn-1) = f(sp->dof(*itn).coords(),rs);
1567 }
1568 else
1569 {
1570 Vector<complex_t> cs;
1571 Vector<real_t> rs;
1572 Vector<Vector<complex_t> >::iterator it= ve->cvEntries_p->begin();
1573 for(; itn!=rks.end(); ++itn)
1574 if(*itn!=0)
1575 {
1576 if(f.valueType()==_real) *(it + *itn-1) = f(sp->dof(*itn).coords(),rs);
1577 else *(it + *itn-1) = f(sp->dof(*itn).coords(),cs);
1578 }
1579 }
1580 break;
1581 default:
1582 where("SuTermVector::setValue(Function, Domain)");
1583 error("scalar_or_vector");
1584 }
1585 }
1586
1587 /*! set dof values of GeomDomain from SuTermVector : u_i = v_i for all dof i on dom
1588 does not change other values
1589 dom has to be a subdomain of the domain of the currrent SuTermVector
1590 be cautious when Space is not a FE Lagrange space, because does not imply that u=v on dom in the meaning of function*/
setValue(const SuTermVector & sut,const GeomDomain & dom)1591 void SuTermVector::setValue(const SuTermVector& sut, const GeomDomain& dom)
1592 {
1593 //check value type
1594 StrucType st=strucType();
1595 ValueType vt=valueType();
1596 if(st!=sut.strucType() || (vt==_real && sut.valueType()!=_real))
1597 {
1598 where("SuTermVector::setValue(SuTermVector, Domain)");
1599 error("value_wrongtype", words("structure", st), "(" + words("value", vt) + ", " + words("value", sut.valueType()) + ")",
1600 words("structure", sut.strucType()), "(" + words("value", _real) + ", " + words("value", _real) + ")");
1601 }
1602
1603 //check space
1604 Space* sp = u_p->space();
1605 if(sut.u_p->space()!=sp)
1606 {
1607 where("SuTermVector::setValue(SuTermVector, Domain)");
1608 error("term_mismatch_spaces", sut.u_p->space()->name(), sp->name());
1609 }
1610
1611 //build numberings
1612 std::vector<number_t> curdofids = space_p->dofIds(); //dof ids of current SuTermVector
1613 std::vector<number_t> sutdofids = sut.space_p->dofIds(); //dof ids of given SuTermVector
1614 std::vector<number_t> domdofids; //dof ids on domain
1615 Space* subsp=Space::findSubSpace(&dom,sp);
1616 if(subsp!=0) domdofids = subsp->dofIds(); //dofs of subspace related to dom
1617 else // built dof using dofsOn function
1618 {
1619 const_cast<GeomDomain&>(dom).updateParentOfSideElements();
1620 domdofids = sp->feSpace()->dofsOn(dom); //dofs located on dom
1621 }
1622 std::vector<number_t> rks, rkc;
1623 ranks(sutdofids,domdofids,rks); // ranks of domain dofs in sut dofs
1624 if(sut.domain()==&dom) rkc=trivialNumbering(number_t(1),sut.nbDofs());
1625 else ranks(curdofids,domdofids,rkc); // ranks of domain dofs in current dofs
1626
1627 //fill value
1628 VectorEntry* vec=entries_p;
1629 const VectorEntry* ves=sut.entries();
1630 if(vec==0) vec=scalar_entries_p;
1631 if(vec==0)
1632 {
1633 where("SuTermVector::setValue(SuTermVector, Domain)");
1634 error("term_no_entries");
1635 }
1636 if(ves==0) ves=scalar_entries_p;
1637 if(ves==0)
1638 {
1639 where("SuTermVector::setValue(SuTermVector, Domain)");
1640 error("term_no_entries");
1641 }
1642 std::vector<number_t>::iterator itns=rks.begin(), itnc=rkc.begin();
1643 switch(st)
1644 {
1645 case _scalar:
1646 if(vt==_real)
1647 {
1648 Vector<real_t>::iterator itc= vec->rEntries_p->begin();
1649 Vector<real_t>::const_iterator its= ves->rEntries_p->begin();
1650 for(; itns!=rks.end(); ++itns, ++itnc)
1651 if(*itns!=0 && *itnc!=0) *(itc + *itnc-1) = *(its+*itns-1);
1652 }
1653 else
1654 {
1655 Vector<complex_t>::iterator itc= vec->cEntries_p->begin();
1656 if(sut.valueType()==_real)
1657 {
1658 Vector<real_t>::const_iterator its= ves->rEntries_p->begin();
1659 for(; itns!=rks.end(); ++itns, ++itnc)
1660 if(*itns!=0 && *itnc!=0) *(itc + *itnc-1) = *(its+*itns-1);
1661 }
1662 else
1663 {
1664 Vector<complex_t>::const_iterator its= ves->cEntries_p->begin();
1665 for(; itns!=rks.end(); ++itns, ++itnc)
1666 if(*itns!=0 && *itnc!=0) *(itc + *itnc-1) = *(its+*itns-1);
1667 }
1668 }
1669 break;
1670 case _vector:
1671 if(vt==_real)
1672 {
1673 Vector<Vector<real_t> >::iterator itc= vec->rvEntries_p->begin();
1674 Vector<Vector<real_t> >::const_iterator its= ves->rvEntries_p->begin();
1675 for(; itns!=rks.end(); ++itns, ++itnc)
1676 if(*itns!=0 && *itnc!=0) *(itc + *itnc-1) = *(its+*itns-1);
1677 }
1678 else
1679 {
1680 Vector<Vector<complex_t> >::iterator itc= vec->cvEntries_p->begin();
1681 if(sut.valueType()==_real)
1682 {
1683 Vector<Vector<real_t> >::const_iterator its= ves->rvEntries_p->begin();
1684 for(; itns!=rks.end(); ++itns, ++itnc)
1685 if(*itns!=0 && *itnc!=0) *(itc + *itnc-1) = *(its+*itns-1);
1686 }
1687 else
1688 {
1689 Vector<Vector<complex_t> >::const_iterator its= ves->cvEntries_p->begin();
1690 for(; itns!=rks.end(); ++itns, ++itnc)
1691 if(*itns!=0 && *itnc!=0) *(itc + *itnc-1) = *(its+*itns-1);
1692 }
1693 }
1694 break;
1695 default:
1696 where("SuTermVector::setValue(SuTermVector, Domain)");
1697 error("scalar_or_vector");
1698 }
1699 }
1700
1701 /*! set dof values of SutermVector from a given SuTermVector : u_i = v_i for all dof i of the given SutermVector
1702 does not change other values */
setValue(const SuTermVector & sut)1703 void SuTermVector::setValue(const SuTermVector& sut)
1704 {
1705 //check value type
1706 StrucType st=strucType();
1707 ValueType vt=valueType();
1708 if(st!=sut.strucType() || (vt==_real && sut.valueType()!=_real))
1709 {
1710 where("SuTermVector::setValue(SuTermVector)");
1711 error("value_wrongtype", words("structure", st), "(" + words("value", vt) + ", " + words("value", sut.valueType()) + ")",
1712 words("structure", sut.strucType()), "(" + words("value", _real) + ", " + words("value", _real) + ")");
1713 }
1714
1715 //check space
1716 Space* sp = u_p->space();
1717 if(sut.u_p->space()!=sp)
1718 {
1719 where("SuTermVector::setValue(SuTermVector)");
1720 error("term_mismatch_spaces", sut.u_p->space()->name(), sp->name());
1721 }
1722
1723 //build numberings
1724 std::vector<number_t> rks;
1725 if(sp==space_p) rks = sut.space_p->dofIds(); //dof ids of given SuTermVector
1726 else
1727 {
1728 std::vector<number_t> curdofids = space_p->dofIds(); //dof ids of current SuTermVector
1729 std::vector<number_t> sutdofids = sut.space_p->dofIds(); //dof ids of given SuTermVector
1730 ranks(curdofids,sutdofids,rks); // ranks of sut dofs in current dofs
1731 }
1732
1733 //fill value
1734 VectorEntry* vec=entries_p;
1735 const VectorEntry* ves=sut.entries();
1736 if(vec==0) vec=scalar_entries_p;
1737 if(vec==0)
1738 {
1739 where("SuTermVector::setValue(SuTermVector)");
1740 error("term_no_entries");
1741 }
1742 if(ves==0) ves=scalar_entries_p;
1743 if(ves==0)
1744 {
1745 where("SuTermVector::setValue(SuTermVector)");
1746 error("term_no_entries");
1747 }
1748 std::vector<number_t>::iterator itn=rks.begin();
1749 switch(st)
1750 {
1751 case _scalar:
1752 if(vt==_real)
1753 {
1754 Vector<real_t>::iterator itc= vec->rEntries_p->begin();
1755 Vector<real_t>::const_iterator its= ves->rEntries_p->begin();
1756 for(; itn!=rks.end(); ++itn, ++its)
1757 if(*itn!=0) *(itc + *itn-1) = *its;
1758 }
1759 else
1760 {
1761 Vector<complex_t>::iterator itc= vec->cEntries_p->begin();
1762 if(sut.valueType()==_real)
1763 {
1764 Vector<real_t>::const_iterator its= ves->rEntries_p->begin();
1765 for(; itn!=rks.end(); ++itn, ++its)
1766 if(*itn!=0) *(itc + *itn-1) = *its;
1767 }
1768 else
1769 {
1770 Vector<complex_t>::const_iterator its= ves->cEntries_p->begin();
1771 for(; itn!=rks.end(); ++itn, ++its)
1772 if(*itn!=0) *(itc + *itn-1) = *its;
1773 }
1774 }
1775 break;
1776 case _vector:
1777 if(vt==_real)
1778 {
1779 Vector<Vector<real_t> >::iterator itc= vec->rvEntries_p->begin();
1780 Vector<Vector<real_t> >::const_iterator its= ves->rvEntries_p->begin();
1781 for(; itn!=rks.end(); ++itn, ++its)
1782 if(*itn!=0) *(itc + *itn-1) = *its;
1783 }
1784 else
1785 {
1786 Vector<Vector<complex_t> >::iterator itc= vec->cvEntries_p->begin();
1787 if(sut.valueType()==_real)
1788 {
1789 Vector<Vector<real_t> >::const_iterator its= ves->rvEntries_p->begin();
1790 for(; itn!=rks.end(); ++itn, ++its)
1791 if(*itn!=0) *(itc + *itn-1) = *its;
1792 }
1793 else
1794 {
1795 Vector<Vector<complex_t> >::const_iterator its= ves->cvEntries_p->begin();
1796 for(; itn!=rks.end(); ++itn, ++its)
1797 if(*itn!=0) *(itc + *itn-1) = *its;
1798 }
1799 }
1800 break;
1801 default:
1802 where("SuTermVector::setValue(SuTermVector)");
1803 error("scalar_or_vector");
1804 }
1805 }
1806
1807
1808 // evaluate interpolated value at a point, use expansive interpolation method
evaluate(const Point & p) const1809 Value SuTermVector::evaluate(const Point& p) const
1810 {
1811 if(entries_p == 0)
1812 {
1813 where("SuTermVector::evaluate");
1814 error("null_pointer", "entries_p");
1815 }
1816 const FeSpace* fsp = space_p->feSpace();
1817 const FeSubSpace* ssp = space_p->feSubSpace();
1818 if(fsp == 0 && ssp == 0)
1819 {
1820 where("SuTermVector::evaluate");
1821 error("not_fe_space_type", space_p->name());
1822 }
1823 dimen_t dimf, dimu;
1824 if(fsp != 0) dimf = fsp->dimFun();
1825 else dimf = ssp->dimFun();
1826 if(dimf >1) dimf += space_p->dimPoint()-space_p->dimDomain(); //modify dimension because of mapping mD->nD
1827 dimu = u_p->nbOfComponents();
1828 dimen_t d = dimf * dimu;
1829
1830 if(entries_p->rEntries_p != 0) //real scalar input
1831 {
1832 if(d == 1) //real scalar output
1833 {
1834 real_t r;
1835 if(fsp != 0) fsp->interpolate(*entries_p->rEntries_p, p, r, _id);
1836 else ssp->interpolate(*entries_p->rEntries_p, p, r, _id);
1837 return Value(r);
1838 }
1839 else //real vector output
1840 {
1841 Vector<real_t> r(d);
1842 if(fsp != 0) fsp->interpolate(*entries_p->rEntries_p, p, r, _id);
1843 else ssp->interpolate(*entries_p->rEntries_p, p, r, _id);
1844 return Value(r);
1845 }
1846 }
1847
1848 if(entries_p->cEntries_p != 0) //complex scalar input
1849 {
1850 if(d == 1) //complex scalar output
1851 {
1852 complex_t r;
1853 if(fsp != 0) fsp->interpolate(*entries_p->cEntries_p, p, r, _id);
1854 else ssp->interpolate(*entries_p->cEntries_p, p, r, _id);
1855 return Value(r);
1856 }
1857 else //complex vector output
1858 {
1859 Vector<complex_t> r(d);
1860 if(fsp != 0) fsp->interpolate(*entries_p->cEntries_p, p, r, _id);
1861 else ssp->interpolate(*entries_p->cEntries_p, p, r, _id);
1862 return Value(r);
1863 }
1864 }
1865
1866 if(entries_p->rvEntries_p != 0) //real vector input
1867 {
1868 if(d == 1) //real scalar output
1869 {
1870 Vector<real_t> r(1);
1871 if(fsp != 0) fsp->interpolate(*entries_p->rvEntries_p, p, r, _id);
1872 else ssp->interpolate(*entries_p->rvEntries_p, p, r, _id);
1873 return Value(r[0]);
1874 }
1875 else //real vector output
1876 {
1877 Vector<real_t> r(d);
1878 if(fsp != 0) fsp->interpolate(*entries_p->rvEntries_p, p, r, _id);
1879 else ssp->interpolate(*entries_p->rvEntries_p, p, r, _id);
1880 return Value(Vector<real_t>(r));
1881 }
1882 }
1883
1884 if(entries_p->cvEntries_p != 0) //complex vector input
1885 {
1886 if(d == 1) //complex scalar output
1887 {
1888 Vector<complex_t> r(1);
1889 if(fsp != 0) fsp->interpolate(*entries_p->cvEntries_p, p, r, _id);
1890 else ssp->interpolate(*entries_p->cvEntries_p, p, r, _id);
1891 return Value(r[0]);
1892 }
1893 else //complex vector output
1894 {
1895 Vector<complex_t> r(d);
1896 if(fsp != 0) fsp->interpolate(*entries_p->cvEntries_p, p, r, _id);
1897 else ssp->interpolate(*entries_p->cvEntries_p, p, r, _id);
1898 return Value(Vector<complex_t>(r));
1899 }
1900 }
1901
1902 where("SuTermVector::evaluate");
1903 error("term_no_entries");
1904 return Value(0.);
1905 }
1906
1907
1908 /*!build the required subspaces and the largest subspace (possibly the whole space)
1909 this function :
1910 - travel along basic linear forms of the linear combination
1911 - identify the largest geometric domain
1912 - build the largest subspace (for SuTermVector dofs numbering)
1913 - create subspace related to each basic linear form if it does not exist
1914 - create dofs numbering between domain subspaces ands largest subspace
1915
1916 dofs numbering :
1917 whole space largest subspace domain subspace
1918 1 5 2
1919 2 3 1
1920 3 1
1921 4
1922 5
1923 */
buildSubspaces()1924 void SuTermVector::buildSubspaces()
1925 {
1926 //for safety
1927 if(sulf_p == 0) return ; //no linear form, nothing to do
1928 trace_p->push("SuTermVector::buildSubspaces");
1929
1930 //case of not a FeSpace
1931 Space* spu = sulf_p->unknown()->space(); //space of the unknown
1932 number_t nblf = sulf_p->size(); //number of basic linear forms in linear form
1933 std::vector<const GeomDomain*> doms(nblf, 0);
1934 space_p = spu;
1935 if(spu->typeOfSpace() != _feSpace)
1936 {
1937 spu->buildSubspaces(doms, subspaces); //build subspaces
1938 trace_p->pop();
1939 return;
1940 }
1941
1942 //only for FeSpace, make list of domains of each basic linear form
1943 number_t n = 0;
1944 for(it_vlfp it = sulf_p->begin(); it != sulf_p->end(); it++, n++) //travel the linear combination of forms
1945 {
1946 BasicLinearForm* blc = it->first;
1947 switch(blc->type())
1948 {
1949 case _intg :
1950 {
1951 if(blc->asIntgForm()->computationType()==_FEextComputation && blc->asIntgForm()->opu()->extensionRequired())
1952 doms[n] = &blc->asIntgForm()->domain()->meshDomain()->extendDomain(); //find or create extension of domain dom
1953 else doms[n] = blc->asIntgForm()->domain();
1954 break;
1955 }
1956 //case _bilinearAsLinear :
1957 //doms[n] = blc->asBilinearAsLinearForm()->domain(); //get the domain of linear form
1958 // break;
1959 case _doubleIntg : //to do later
1960 default :
1961 error("lform_not_handled", words("form type", blc->type())); //unknown basic linear form
1962 }
1963 }
1964
1965 space_p = spu->buildSubspaces(doms, subspaces); //build subspaces
1966
1967 trace_p->pop();
1968 }
1969
1970 /*! if vector unknown, create vector representation from scalar representation (have to exist)
1971 if scalar unknown, set entries_p = scalar_entries_p
1972 keepScalar : if false (default value), scalar entries are deleted
1973 */
toVector(bool keepScalar)1974 void SuTermVector::toVector(bool keepScalar)
1975 {
1976 if(scalar_entries_p == 0) return; // no scalar representation, nothing done
1977 trace_p->push("SuTermVector::toVector()");
1978 if(entries_p != 0 && scalar_entries_p != entries_p) delete entries_p; // delete old entries
1979 dimen_t nbc = u_p->nbOfComponents();
1980 if(nbc <= 1) //not a vector unknown
1981 {
1982 entries_p = scalar_entries_p;
1983 trace_p->pop();
1984 return;
1985 }
1986 //reallocate entries
1987 ValueType vt = scalar_entries_p->valueType_;
1988 std::vector<number_t> dofs = space_p->dofIds();
1989 entries_p = new VectorEntry(vt, nbc, dofs.size());
1990 std::map<number_t, number_t> dofindex;
1991 std::vector<number_t>::iterator itd = dofs.begin();
1992 number_t n = 1;
1993 for(; itd != dofs.end(); itd++, n++) dofindex[*itd] = n;
1994 std::vector<DofComponent>::iterator itcd = cdofs_.begin();
1995 std::map<number_t, number_t>::iterator itm;
1996 if(vt == _real) //real case
1997 {
1998 Vector<real_t>& sval = *scalar_entries_p->rEntries_p;
1999 Vector<Vector<real_t> >& val = *entries_p->rvEntries_p;
2000 Vector<real_t>::iterator itv = sval.begin();
2001 for(; itcd != cdofs_.end(); itcd++, itv++)
2002 {
2003 itm = dofindex.find(itcd->dofnum);
2004 if(itm == dofindex.end())
2005 error("dof_not_found");
2006 val(itm->second)(itcd->numc) = *itv;
2007 }
2008 }
2009 else //complex case
2010 {
2011 Vector<complex_t>& sval = *scalar_entries_p->cEntries_p;
2012 Vector<Vector<complex_t> >& val = *entries_p->cvEntries_p;
2013 Vector<complex_t>::iterator itv = sval.begin();
2014 for(; itcd != cdofs_.end(); itcd++, itv++)
2015 {
2016 itm = dofindex.find(itcd->dofnum);
2017 if(itm == dofindex.end())
2018 error("dof_not_found");
2019 val(itm->second)(itcd->numc) = *itv;
2020 }
2021 }
2022 if(!keepScalar)
2023 {
2024 delete scalar_entries_p;
2025 scalar_entries_p = 0;
2026 }
2027 trace_p->pop();
2028 }
2029
2030 /*! create scalar representation scalar_entries_p and cdofs_ numbering vectors
2031 - if unknown is a vector unknown a new VectorEntry is created using VectorEntry::toScalar() function
2032 and linked to the VectorEntry pointer scalar_entries_p. In that case, if keepVector is false the vector representation is destroyed
2033 - if unknowns is a scalar unknown, no new VectorEntry : scalar_entries_p = entries_p
2034 This function builds in any case, the cdofs_ numbering vector (vector of ComponentDof's)
2035 */
toScalar(bool keepVector)2036 void SuTermVector::toScalar(bool keepVector)
2037 {
2038 if(scalar_entries_p != 0) return; //already in scalar form
2039
2040 trace_p->push("SuTermVector::toScalar");
2041 //create or update scalar_entries_p
2042 dimen_t nbc = u_p->nbOfComponents();
2043 if(nbc == 1) scalar_entries_p = entries_p; //no creation, pointer copy
2044 else if(entries_p != 0) scalar_entries_p = entries_p->toScalar(); //create new scalar entries from vector entries
2045
2046 //create cdofs_u
2047 std::vector<number_t> dofs = space_p->dofIds();
2048 cdofs_.resize(dofs.size()*nbc);
2049 std::vector<number_t>::iterator itd = dofs.begin();
2050 std::vector<DofComponent>::iterator itdc = cdofs_.begin();
2051 for(; itd != dofs.end(); itd++)
2052 for(dimen_t d = 0; d < nbc; d++, itdc++) *itdc = DofComponent(u_p, *itd, d + 1);
2053
2054 if(!keepVector && entries_p != scalar_entries_p)
2055 {
2056 delete entries_p;
2057 entries_p = 0;
2058 }
2059 trace_p->pop();
2060 }
2061
2062 /*! when current SutermVector has a component unknown, return vector unknown representation
2063 if is not a component unknown SuTermVector, a copy of current SuTermVector is returned
2064 */
toVectorUnknown() const2065 SuTermVector SuTermVector::toVectorUnknown() const
2066 {
2067 trace_p->push("SuTermVector::toVectorUnknown");
2068 SuTermVector res(*this);
2069 if(!u_p->isComponent() || entries_p == 0)
2070 {
2071 trace_p->pop();
2072 return res;
2073 }
2074 res.entries_p->toVector(u_p->parent()->nbOfComponents(), u_p->componentIndex());
2075 res.u_p = u_p->parent();
2076 trace_p->pop();
2077 return res;
2078 }
2079
2080 // save SuTermVector to file
saveToFile(const string_t & fn,bool encode) const2081 void SuTermVector::saveToFile(const string_t& fn, bool encode) const
2082 {
2083 if(entries_p != 0) entries_p->saveToFile(fn, encode);
2084 if(scalar_entries_p != 0) scalar_entries_p->saveToFile(fn, encode);
2085 }
2086
2087 //return value type (_real,_complex)
valueType() const2088 ValueType SuTermVector::valueType() const
2089 {
2090 if(entries_p != 0) return entries_p->valueType_;
2091 if(scalar_entries_p != 0) return scalar_entries_p->valueType_;
2092 if(sulf_p != 0) return sulf_p->valueType();
2093 return _none;
2094 }
2095 //return structure type (_scalar,_vector)
strucType() const2096 StrucType SuTermVector::strucType() const
2097 {
2098 if(entries_p != 0) return entries_p->strucType_;
2099 if(scalar_entries_p != 0) return scalar_entries_p->strucType_;
2100 if(sulf_p != 0) return sulf_p->strucType();
2101 return _scalar;
2102 }
2103
2104 /* ----------------------------------------------------------------------------------------
2105 compute abs, real and imaginary part of SuTermVector
2106 note : current SuTermVector is modified
2107 ----------------------------------------------------------------------------------------*/
toAbs()2108 SuTermVector& SuTermVector::toAbs()
2109 {
2110 if(entries_p != 0) entries_p->toAbs();
2111 if(scalar_entries_p != 0) scalar_entries_p->toAbs();
2112 return *this;
2113 }
2114
toReal()2115 SuTermVector& SuTermVector::toReal()
2116 {
2117 if(entries_p != 0) entries_p->toReal();
2118 if(scalar_entries_p != 0) scalar_entries_p->toReal();
2119 return *this;
2120 }
2121
toImag()2122 SuTermVector& SuTermVector::toImag()
2123 {
2124 if(entries_p != 0) entries_p->toImag();
2125 if(scalar_entries_p != 0) scalar_entries_p->toImag();
2126 return *this;
2127 }
2128
toComplex()2129 SuTermVector& SuTermVector::toComplex()
2130 {
2131 if(entries_p != 0) entries_p->toComplex();
2132 if(scalar_entries_p != 0) scalar_entries_p->toComplex();
2133 return *this;
2134 }
2135
2136 // take the conjugate of entries, if no entries nothing is done
2137 // when conjugate is taken, the linear form is not updated to take it into account !
toConj()2138 SuTermVector& SuTermVector::toConj()
2139 {
2140 if(valueType()==_real) return *this; //nothing to do
2141 if(entries_p != 0) entries_p->toConj();
2142 if(scalar_entries_p != 0) scalar_entries_p->toConj();
2143 return *this;
2144
2145 }
2146 // round to zero all coefficients close to 0 (|.| < aszero)
roundToZero(real_t aszero)2147 SuTermVector& SuTermVector::roundToZero(real_t aszero)
2148 {
2149 if(entries_p != 0) entries_p->roundToZero(aszero);
2150 if(scalar_entries_p != 0) scalar_entries_p->roundToZero(aszero);
2151 return *this;
2152
2153 }
2154
2155 /* ----------------------------------------------------------------------------------------
2156 compute SuTermVector
2157 remember that it deal with a single unknown
2158 this routine first analyse the linear form to be computed,
2159 it collects computations by domain and type of computation
2160
2161 !!! For the moment, only FE computation is handled (not the BEM and spectral methods)
2162 ----------------------------------------------------------------------------------------*/
compute()2163 void SuTermVector::compute()
2164 {
2165 if(sulf_p == 0) return; //no linear form to compute
2166 if(sulf_p->size() == 0) return; //void SuTermVector !!!
2167 trace_p->push("SuTermVector::compute");
2168 //retry unknown
2169 const Unknown* up = sulf_p->unknown();
2170
2171 //analyse the combination of linear forms to be computed and split them by domain (and by type of computation)
2172 std::map<const GeomDomain*, std::vector<lfPair> > intgByDomain; //list of linear form by domain
2173 std::map<const GeomDomain*, std::vector<lfPair> >::iterator itm;
2174 std::list<lfPair> bilinearAslinear; //list of bilinear_as_linear forms
2175 std::list<lfPair>::iterator itl;
2176 ValueType vt = _real;
2177 StrucType st = sulf_p->begin()->first->strucType();
2178 dimPair dims = dimPair(0,0);
2179 for(it_vlfp it = sulf_p->begin(); it != sulf_p->end(); it++)
2180 {
2181 switch(it->first->type())
2182 {
2183 case _intg : //integral type
2184 {
2185 IntgLinearForm* ifl = it->first->asIntgForm(); //downcast
2186 const GeomDomain* dom = ifl->domain();
2187 itm = intgByDomain.find(dom);
2188 if(itm == intgByDomain.end())
2189 intgByDomain[dom] = std::vector<lfPair>(1, lfPair(*it));
2190 else
2191 intgByDomain[dom].push_back(lfPair(*it));
2192 //value and structure types
2193 if(it->first->valueType() == _complex || it->second.imag() != 0) vt = _complex;
2194 if(dims.first==0) dims=ifl->opu()->dimsRes();
2195 else if(dims!=ifl->opu()->dimsRes())
2196 error("operator_mismatch_size", dims.first, ifl->opu()->dimsRes().first);
2197 if(it->first->strucType() != st)
2198 error("term_mismatch_structures", words("structure", it->first->strucType()), words("structure", st));
2199 break;
2200 }
2201 case _bilinearAsLinear :
2202 {
2203 bilinearAslinear.push_back(lfPair(*it));
2204 if(it->first->valueType() == _complex) vt = _complex;
2205 if(it->first->strucType() != st)
2206 error("term_mismatch_structures", words("structure", it->first->strucType()), words("structure", st));
2207 break;
2208 }
2209 default :
2210 error("lform_not_handled", words("form type", it->first->type()));
2211
2212 }
2213 }
2214 std::vector<SuLinearForm> sulfs; //list of SuLinearForm, each of them is defined on a unique domain
2215 for(itm = intgByDomain.begin(); itm != intgByDomain.end(); itm++)
2216 {
2217 sulfs.push_back(SuLinearForm(itm->second));
2218 }
2219 intgByDomain.clear();
2220
2221 //create entries
2222 if(dims.second>1) error("scalar_or_vector");
2223 if(up->nbOfComponents()>1 && dims.first>1)
2224 error("term_inconsistent_nb_components");
2225 dimen_t du = std::max(up->nbOfComponents(),dims.first);
2226 if(du == 1)
2227 {
2228 st=_scalar;
2229 entries_p = new VectorEntry(sulf_p->valueType(), _scalar, space_p->dimSpace());
2230 }
2231 else
2232 {
2233 st=_vector;
2234 entries_p = new VectorEntry(sulf_p->valueType(), _vector, space_p->nbDofs(), du);
2235 }
2236
2237 //computation of SuLinearForms from intg
2238 std::vector<SuLinearForm>::iterator itsulf;
2239 UnknownType ut = up->type();
2240 //st = up->strucType();
2241 real_t r = 0;
2242 complex_t c = 0.;
2243 for(itsulf = sulfs.begin(); itsulf != sulfs.end(); itsulf++)
2244 {
2245 switch(ut)
2246 {
2247 case _feUnknown :
2248 switch(st)
2249 {
2250 case _scalar :
2251 if(vt == _real) computeFE(*itsulf, *(entries_p->rEntries_p), r);
2252 else computeFE(*itsulf, *(entries_p->cEntries_p), c);
2253 break;
2254 case _vector :
2255 if(vt == _real) computeFE(*itsulf, *(entries_p->rvEntries_p), r);
2256 else computeFE(*itsulf, *(entries_p->cvEntries_p), c);
2257 break;
2258 default :
2259 error("scalar_or_vector");
2260 }
2261 break;
2262 case _spUnknown :
2263 default :
2264 error("unknown_not_handled", words("unknown", ut));
2265 }
2266 }
2267
2268 // //computation of SuLinearForms from bilinear_as_linear form
2269 // for (itl=bilinearAslinear.begin(); itl!=bilinearAslinear.end(); ++itl)
2270 // switch(st)
2271 // {
2272 // case _scalar :
2273 // if (vt == _real) computeBilAsLin(*itl, *(entries_p->rEntries_p), r);
2274 // else computeBilAsLin(*itl, *(entries_p->cEntries_p), c);
2275 // break;
2276 // case _vector :
2277 // if (vt == _real) computeBilAsLin(*itl, *(entries_p->rvEntries_p), r);
2278 // else computeBilAsLin(*itl, *(entries_p->cvEntries_p), c);
2279 // break;
2280 // default :
2281 // error("scalar_or_vector");
2282 // }
2283
2284 computed() = true;
2285 trace_p->pop();
2286 }
2287
2288 /*! extend current vector to numbering of vector v (useful for algebraic computation on SuTermVector)
2289 update entries and not scalar entries if allocated
2290 */
extendTo(const SuTermVector & v)2291 void SuTermVector::extendTo(const SuTermVector& v)
2292 {
2293 if(&v == this) return; //same vector nothing to extend
2294 if(space_p == v.space_p) return; //same space nothing to extend
2295 if(u_p != v.u_p && u_p != v.u_p->dual_p())
2296 {
2297 where("SuTermVector::extendTo");
2298 error("term_inconsistent_unknowns");
2299 }
2300 if(entries_p == 0) return; //entries not allocated, do nothing
2301
2302 //extension may be required
2303 std::vector<number_t> dofrenumber = renumber(v.space_p, space_p);
2304 if(dofrenumber.size() == 0) return; //a trivial renumbering
2305 entries_p->extendEntries(dofrenumber, v.space_p->dimSpace());
2306 space_p = v.space_p; //update SuTermVector space
2307 }
2308
2309 /*! extend current vector to numbering of space sp
2310 update entries and not scalar entries
2311 */
extendTo(const Space & sp)2312 void SuTermVector::extendTo(const Space& sp)
2313 {
2314 if(space_p == &sp) return; //same space nothing to extend
2315 if(space_p->rootSpace() != sp.rootSpace())
2316 error("term_mismatch_spaces", space_p->rootSpace()->name(), sp.rootSpace()->name());
2317 if(entries_p == 0) return; //entries not allocated, do nothing
2318
2319 std::vector<number_t> dofrenumber = renumber(&sp, space_p);
2320 if(dofrenumber.size() == 0) return; //trivial renumbering
2321 entries_p->extendEntries(dofrenumber, sp.dimSpace());
2322 space_p = const_cast<Space*>(&sp); //update SuTermVector space
2323 }
2324
2325 /*! extend current vector to numbering given by DofComponent vector ndofs
2326 if useDual is true, use dual components dof (default = false)
2327 update scalar entries and not vector entries
2328 if scalar_entries = 0 move to scalar representation
2329 Note : differs from previous extendTo functions by the fact it works with component dof numbering instead of dof numbering
2330 */
extendScalarTo(const std::vector<DofComponent> & ndofs,bool useDual)2331 void SuTermVector::extendScalarTo(const std::vector<DofComponent>& ndofs, bool useDual)
2332 {
2333 VectorEntry* b = scalar_entries();
2334 if(b == 0)
2335 {
2336 toScalar();
2337 b = scalar_entries();
2338 }
2339 std::vector<number_t> renum;
2340 if(!useDual) renum = renumber(ndofs, cdofs());
2341 else renum = renumber(ndofs, dualDofComponents(cdofs()));
2342 if(renum.size() != 0)
2343 {
2344 b->extendEntries(renum, ndofs.size()); //extend vector to matrix column numbering
2345 cdofs() = ndofs; //update cdofs
2346 }
2347 }
2348
2349 /*! adjust scalar entries to cdofs numbering given
2350 same as extendScalarTo but different method, see general adjustScalarEntries function
2351 */
adjustScalarEntries(const std::vector<DofComponent> & ncdofs)2352 void SuTermVector::adjustScalarEntries(const std::vector<DofComponent>& ncdofs)
2353 {
2354 adjustScalarEntriesG(scalar_entries_p, cdofs_, ncdofs);
2355 }
2356
2357 //algebraic operations on SuTermVectors
operator +=(const SuTermVector & v)2358 SuTermVector& SuTermVector::operator+=(const SuTermVector& v) // operation U+=V
2359 {
2360 if(u_p != v.u_p && u_p != v.u_p->dual_p())
2361 {
2362 where("SutermVector::operator+=");
2363 error("term_inconsistent_unknowns"); //different unknowns, error
2364 }
2365 if(v.entries_p == 0 && v.scalar_entries_p == 0) return *this; //v has no entries, add 0 !
2366
2367 // first, we have to check if both vectors have the same entries structure
2368 // if no, we have to set v to the same structure, through a copy
2369 bool copyNeeded=false;
2370 bool vToScalar=false;
2371 bool vToVector=false;
2372 if(scalar_entries_p != 0 && scalar_entries_p != entries_p && v.scalar_entries_p == 0)
2373 {
2374 copyNeeded=vToScalar=true;
2375 }
2376 else if(scalar_entries_p == 0 && v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2377 {
2378 copyNeeded=vToVector=true;
2379 }
2380
2381 if(copyNeeded)
2382 {
2383 SuTermVector vcopy(v);
2384 if(vToScalar)
2385 {
2386 vcopy.toScalar();
2387 }
2388 if(vToVector)
2389 {
2390 vcopy.toVector();
2391 }
2392
2393 Space* spu = space_p, *spv = v.space_p;
2394 if(spu == spv) // same numbering => go to entries operation
2395 {
2396 if(vToVector)
2397 {
2398 if(entries_p == 0) entries_p = new VectorEntry(vcopy.valueType(), vcopy.strucType(), vcopy.nbDofs(), vcopy.nbOfComponents());
2399 *entries_p += *vcopy.entries_p;
2400 }
2401 if(vToScalar)
2402 {
2403 if(scalar_entries_p == 0) scalar_entries_p = new VectorEntry(vcopy.valueType(), vcopy.strucType(), vcopy.nbDofs()*vcopy.nbOfComponents(), 1);
2404 *scalar_entries_p += *vcopy.scalar_entries_p;
2405 }
2406 }
2407 else // not the same numbering => dynamic renumbering
2408 {
2409 Space* spuv = mergeSubspaces(spu,spv); // create union of subspaces, may be spu or spv or anything else
2410 space_p=spuv; // update subspace member
2411
2412 if(spu != spuv) // extend current entry if required
2413 {
2414 if(vToVector)
2415 {
2416 if(entries_p != 0 && vcopy.entries_p != 0)
2417 {
2418 std::vector<number_t> dofrenumber = renumber(spuv, spu);
2419 if(dofrenumber.size() != 0) entries_p->extendEntries(dofrenumber, spuv->dimSpace());
2420 }
2421 VectorEntry* ve = vcopy.entries_p;
2422
2423 if(spv != spuv)
2424 {
2425 if(entries_p != 0 && vcopy.entries_p != 0)
2426 {
2427 ve = new VectorEntry(*vcopy.entries_p); // copy of v entries
2428 std::vector<number_t> dofrenumber = renumber(spuv, spv);
2429 if(dofrenumber.size() != 0) ve->extendEntries(dofrenumber, spuv->dimSpace()); // do algebraic operation on entries
2430 }
2431 }
2432 if(entries_p != 0 && vcopy.entries_p != 0)
2433 {
2434 *entries_p += *ve; // do algebraic operation on entries
2435 }
2436 }
2437 if(vToScalar)
2438 {
2439 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
2440 {
2441 std::vector<number_t> dofrenumber;
2442 if(u_p == vcopy.u_p) dofrenumber=renumber(cdofs(), vcopy.cdofs());
2443 else dofrenumber=renumber(cdofs(), dualDofComponents(vcopy.cdofs()));
2444 if(dofrenumber.size() != 0) scalar_entries_p->extendEntries(dofrenumber, cdofs().size());
2445 }
2446 VectorEntry* vse = vcopy.scalar_entries_p;
2447
2448 if(spv != spuv)
2449 {
2450 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
2451 {
2452 vse=new VectorEntry(*vcopy.scalar_entries_p);
2453 std::vector<number_t> dofrenumber;
2454 if(u_p == vcopy.u_p) dofrenumber=renumber(vcopy.cdofs(), cdofs());
2455 else dofrenumber=renumber(vcopy.cdofs(), dualDofComponents(cdofs()));
2456 if(dofrenumber.size() != 0) vse->extendEntries(dofrenumber, vcopy.cdofs().size());
2457 }
2458 }
2459 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
2460 {
2461 *scalar_entries_p += *vse; // do algebraic operation on entries
2462 }
2463 }
2464 }
2465 }
2466 }
2467 else
2468 {
2469 Space* spu = space_p, *spv = v.space_p;
2470 if(spu == spv) // same numbering => go to entries operation
2471 {
2472 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2473 {
2474 if(scalar_entries_p == 0) scalar_entries_p = new VectorEntry(v.valueType(), v.strucType(), v.nbDofs()*v.nbOfComponents(), 1);
2475 if(scalar_entries_p != entries_p) *scalar_entries_p += *v.scalar_entries_p;
2476 }
2477 if(v.entries_p != 0)
2478 {
2479 if(entries_p == 0) entries_p = new VectorEntry(v.valueType(), v.strucType(), v.nbDofs(), v.nbOfComponents());
2480 *entries_p += *v.entries_p;
2481 }
2482 }
2483 else // not the same numbering => dynamic renumbering
2484 {
2485 Space* spuv = mergeSubspaces(spu, spv); // create union of subspaces, may be spu or spv or anything else
2486 space_p = spuv; // update subspace member
2487
2488 if(spu != spuv) //extend current entry if required
2489 {
2490 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2491 {
2492 std::vector<number_t> dofrenumber;
2493 if(u_p == v.u_p) dofrenumber=renumber(cdofs(), v.cdofs());
2494 else dofrenumber=renumber(cdofs(), dualDofComponents(v.cdofs()));
2495 if(dofrenumber.size() != 0) scalar_entries_p->extendEntries(dofrenumber, cdofs().size());
2496 }
2497 if(v.entries_p != 0)
2498 {
2499 std::vector<number_t> dofrenumber = renumber(spuv, spu);
2500 if(dofrenumber.size() != 0) entries_p->extendEntries(dofrenumber, spuv->dimSpace());
2501 }
2502 }
2503 VectorEntry* ve = v.entries_p;
2504 VectorEntry* vse = v.scalar_entries_p;
2505 if(spv != spuv) // extend v entry if required
2506 {
2507 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2508 {
2509 vse=new VectorEntry(*v.scalar_entries_p);
2510 std::vector<number_t> dofrenumber;
2511 if(u_p == v.u_p) dofrenumber=renumber(v.cdofs(), cdofs());
2512 else dofrenumber=renumber(v.cdofs(), dualDofComponents(cdofs()));
2513 if(dofrenumber.size() != 0) vse->extendEntries(dofrenumber, v.cdofs().size());
2514 }
2515 if(v.entries_p != 0)
2516 {
2517 ve = new VectorEntry(*v.entries_p); //copy of v entries
2518 std::vector<number_t> dofrenumber = renumber(spuv, spv);
2519 if(dofrenumber.size() != 0) ve->extendEntries(dofrenumber, spuv->dimSpace()); //do algebraic operation on entries
2520 }
2521 }
2522 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2523 {
2524 *scalar_entries_p += *vse;
2525 }
2526 if(v.entries_p != 0)
2527 {
2528 *entries_p += *ve; // do algebraic operation on entries
2529 }
2530 }
2531 }
2532
2533 return *this;
2534 }
2535
operator -=(const SuTermVector & v)2536 SuTermVector& SuTermVector::operator-=(const SuTermVector& v) // operation U-=V
2537 {
2538 if(u_p != v.u_p && u_p != v.u_p->dual_p())
2539 {
2540 where("SutermVector::operator-=");
2541 error("term_inconsistent_unknowns"); //different unknowns, error
2542 }
2543 if(v.entries_p == 0 && v.scalar_entries_p == 0) return *this; //v has no entries, add 0 !
2544
2545 // first, we have to check if both vectors have the same entries structure
2546 // if no, we have to set v to the same structure, through a copy
2547 bool copyNeeded=false;
2548 bool vToScalar=false;
2549 bool vToVector=false;
2550 if(scalar_entries_p != 0 && scalar_entries_p != entries_p && v.scalar_entries_p == 0)
2551 {
2552 copyNeeded=vToScalar=true;
2553 }
2554 else if(scalar_entries_p == 0 && v.scalar_entries_p !=0 && v.scalar_entries_p != v.entries_p)
2555 {
2556 copyNeeded=vToVector=true;
2557 }
2558
2559 if(copyNeeded)
2560 {
2561 SuTermVector vcopy(v);
2562 if(vToScalar)
2563 {
2564 vcopy.toScalar();
2565 }
2566 if(vToVector)
2567 {
2568 vcopy.toVector();
2569 }
2570
2571 Space* spu = space_p, *spv = v.space_p;
2572 if(spu == spv) // same numbering => go to entries operation
2573 {
2574 if(vToVector)
2575 {
2576 if(entries_p == 0) entries_p = new VectorEntry(vcopy.valueType(), vcopy.strucType(), vcopy.nbDofs(), vcopy.nbOfComponents());
2577 *entries_p -= *vcopy.entries_p;
2578 }
2579 if(vToScalar)
2580 {
2581 if(scalar_entries_p == 0) scalar_entries_p = new VectorEntry(vcopy.valueType(), vcopy.strucType(), vcopy.nbDofs()*vcopy.nbOfComponents(), 1);
2582 *scalar_entries_p -= *vcopy.scalar_entries_p;
2583 }
2584 }
2585 else // not the same numbering => dynamic renumbering
2586 {
2587 Space* spuv = mergeSubspaces(spu,spv); // create union of subspaces, may be spu or spv or anything else
2588 space_p=spuv; // update subspace member
2589
2590 if(spu != spuv) // extend current entry if required
2591 {
2592 if(vToVector)
2593 {
2594 if(entries_p != 0 && vcopy.entries_p != 0)
2595 {
2596 std::vector<number_t> dofrenumber = renumber(spuv, spu);
2597 if(dofrenumber.size() != 0) entries_p->extendEntries(dofrenumber, spuv->dimSpace());
2598 }
2599 VectorEntry* ve = vcopy.entries_p;
2600
2601 if(spv != spuv)
2602 {
2603 if(entries_p != 0 && vcopy.entries_p != 0)
2604 {
2605 ve = new VectorEntry(*vcopy.entries_p); // copy of v entries
2606 std::vector<number_t> dofrenumber = renumber(spuv, spv);
2607 if(dofrenumber.size() != 0) ve->extendEntries(dofrenumber, spuv->dimSpace()); // do algebraic operation on entries
2608 }
2609 }
2610 if(entries_p != 0 && vcopy.entries_p != 0)
2611 {
2612 *entries_p -= *ve; // do algebraic operation on entries
2613 }
2614 }
2615 if(vToScalar)
2616 {
2617 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
2618 {
2619 std::vector<number_t> dofrenumber;
2620 if(u_p == vcopy.u_p) dofrenumber=renumber(cdofs(), vcopy.cdofs());
2621 else dofrenumber=renumber(cdofs(), dualDofComponents(vcopy.cdofs()));
2622 if(dofrenumber.size() != 0) scalar_entries_p->extendEntries(dofrenumber, cdofs().size());
2623 }
2624 VectorEntry* vse = vcopy.scalar_entries_p;
2625
2626 if(spv != spuv)
2627 {
2628 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
2629 {
2630 vse=new VectorEntry(*vcopy.scalar_entries_p);
2631 std::vector<number_t> dofrenumber;
2632 if(u_p == vcopy.u_p) dofrenumber=renumber(vcopy.cdofs(), cdofs());
2633 else dofrenumber=renumber(vcopy.cdofs(), dualDofComponents(cdofs()));
2634 if(dofrenumber.size() != 0) vse->extendEntries(dofrenumber, vcopy.cdofs().size());
2635 }
2636 }
2637 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
2638 {
2639 *scalar_entries_p -= *vse; // do algebraic operation on entries
2640 }
2641 }
2642 }
2643 }
2644 }
2645 else
2646 {
2647 Space* spu = space_p, *spv = v.space_p;
2648 if(spu == spv) // same numbering => go to entries operation
2649 {
2650 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2651 {
2652 if(scalar_entries_p == 0) scalar_entries_p = new VectorEntry(v.valueType(), v.strucType(), v.nbDofs()*v.nbOfComponents(), 1);
2653 if(scalar_entries_p != entries_p) *scalar_entries_p -= *v.scalar_entries_p;
2654 }
2655 if(v.entries_p != 0)
2656 {
2657 if(entries_p == 0) entries_p = new VectorEntry(v.valueType(), v.strucType(), v.nbDofs(), v.nbOfComponents());
2658 *entries_p -= *v.entries_p;
2659 }
2660 }
2661 else // not the same numbering => dynamic renumbering
2662 {
2663 Space* spuv = mergeSubspaces(spu, spv); // create union of subspaces, may be spu or spv or anything else
2664 space_p = spuv; // update subspace member
2665
2666 if(spu != spuv) //extend current entry if required
2667 {
2668 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2669 {
2670 std::vector<number_t> dofrenumber;
2671 if(u_p == v.u_p) dofrenumber=renumber(cdofs(), v.cdofs());
2672 else dofrenumber=renumber(cdofs(), dualDofComponents(v.cdofs()));
2673 if(dofrenumber.size() != 0) scalar_entries_p->extendEntries(dofrenumber, cdofs().size());
2674 }
2675 if(v.entries_p != 0)
2676 {
2677 std::vector<number_t> dofrenumber = renumber(spuv, spu);
2678 if(dofrenumber.size() != 0) entries_p->extendEntries(dofrenumber, spuv->dimSpace());
2679 }
2680 }
2681 VectorEntry* ve = v.entries_p;
2682 VectorEntry* vse = v.scalar_entries_p;
2683 if(spv != spuv) // extend v entry if required
2684 {
2685 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2686 {
2687 vse=new VectorEntry(*v.scalar_entries_p);
2688 std::vector<number_t> dofrenumber;
2689 if(u_p == v.u_p) dofrenumber=renumber(v.cdofs(), cdofs());
2690 else dofrenumber=renumber(v.cdofs(), dualDofComponents(cdofs()));
2691 if(dofrenumber.size() != 0) vse->extendEntries(dofrenumber, v.cdofs().size());
2692 }
2693 if(v.entries_p != 0)
2694 {
2695 ve = new VectorEntry(*v.entries_p); //copy of v entries
2696 std::vector<number_t> dofrenumber = renumber(spuv, spv);
2697 if(dofrenumber.size() != 0) ve->extendEntries(dofrenumber, spuv->dimSpace()); //do algebraic operation on entries
2698 }
2699 }
2700 if(v.scalar_entries_p != 0 && v.scalar_entries_p != v.entries_p)
2701 {
2702 *scalar_entries_p -= *vse;
2703 }
2704 if(v.entries_p != 0)
2705 {
2706 *entries_p -= *ve; // do algebraic operation on entries
2707 }
2708 }
2709 }
2710
2711 return *this;
2712 }
2713
2714 // merging a SuTermVector with current one BUT preserving the current value when common dofs
2715 // like a += but without summing values of common dofs
2716 // process works as following :
2717 // - detect common dofs
2718 // - if there are some
2719 // - copy of SuTermVector to merge with
2720 // - replace by 0 the value related to a common dofs
2721 // - use += operator
merge(const SuTermVector & v)2722 SuTermVector& SuTermVector::merge(const SuTermVector& v)
2723 {
2724 trace_p->push("SuTermVector::merge(SuTermVector)");
2725 if(u_p != v.u_p && u_p != v.u_p->dual_p())
2726 {
2727 where("SutermVector::merge");
2728 error("term_inconsistent_unknowns"); //different unknowns, error
2729 }
2730 Space* spu = space_p, *spv = v.space_p;
2731 if(spu == spv) //same numbering, merge do nothing
2732 {
2733 trace_p->pop();
2734 return *this;
2735 }
2736 //find common dofs
2737 std::vector<number_t> dofrenumber = renumber(spu, spv);
2738 bool noCommonDofs = true;
2739 std::vector<number_t>::iterator itn = dofrenumber.begin();
2740 while(itn != dofrenumber.end() && noCommonDofs)
2741 {
2742 if(*itn != 0) noCommonDofs = false;
2743 else ++itn;
2744 }
2745 SuTermVector* vc = const_cast<SuTermVector*>(&v);
2746 if(!noCommonDofs) //have common dofs, copy v and set 0 values on common dofs
2747 {
2748 vc = new SuTermVector(v);
2749 StrucType st = vc->strucType();
2750 ValueType vt = vc->valueType();
2751 VectorEntry* entries = vc->entries();
2752 complex_t z0(0., 0.);
2753 switch(st)
2754 {
2755 case _scalar :
2756 if(vt == _real)
2757 {
2758 number_t i = 1;
2759 for(itn = dofrenumber.begin(); itn != dofrenumber.end(); ++itn, ++i)
2760 if(*itn != 0) entries->setValue(i, 0.);
2761 }
2762 else
2763 {
2764 number_t i = 1;
2765 for(itn = dofrenumber.begin(); itn != dofrenumber.end(); ++itn, ++i)
2766 if(*itn != 0) entries->setValue(i, z0);
2767 }
2768 break;
2769 case _vector :
2770 if(vt == _real)
2771 {
2772 number_t i = 1;
2773 Vector<real_t> rv0(vc->nbOfComponents(), 0.);
2774 for(itn = dofrenumber.begin(); itn != dofrenumber.end(); ++itn, ++i)
2775 if(*itn != 0) entries->setValue(i, rv0);
2776 }
2777 else
2778 {
2779 number_t i = 1;
2780 Vector<complex_t> rc0(vc->nbOfComponents(), z0);
2781 for(itn = dofrenumber.begin(); itn != dofrenumber.end(); ++itn, ++i)
2782 if(*itn != 0) entries->setValue(i, rc0);
2783 }
2784 break;
2785 default :
2786 error("scalar_or_vector");
2787 }
2788 }
2789 //add to current
2790 (*this) += *vc;
2791
2792 if(vc != &v) delete vc;
2793 trace_p->pop();
2794 return *this;
2795 }
2796
2797 /*! compute SuTermVector from a linear combination of SuTermVector's
2798 the current SuTermVector is assumed to be void, this function fills every things
2799 if it is not the case, every thing is clear
2800 */
compute(const LcTerm<SuTermVector> & lc)2801 void SuTermVector::compute(const LcTerm<SuTermVector>& lc)
2802 {
2803 trace_p->push("SuTermVector::compute(LcTerm)");
2804 clear();
2805 if(lc.size() == 0) error("is_void", "LcTerm");
2806
2807 termType_ = _sutermVector;
2808 if(lc.size() == 1) //copy and multiplication
2809 {
2810 const SuTermVector* sut = dynamic_cast<const SuTermVector*>(lc.begin()->first);
2811 if(sut == 0) error("null_pointer", "SuTermVector");
2812 complex_t a = lc.begin()->second;
2813 sulf_p = sut->sulf_p;
2814 u_p = sut->u_p;
2815 space_p = sut->space_p;
2816 subspaces = sut->subspaces;
2817 entries_p = new VectorEntry(*sut->entries_p);
2818 if(a != complex_t(1., 0.)) *entries_p *= a;
2819 computed() = true;
2820 trace_p->pop();
2821 return;
2822 }
2823
2824 //clear current linear form properties
2825 subspaces.clear();
2826 if(sulf_p == 0) delete sulf_p;
2827 sulf_p = 0;
2828
2829 // create largest space and subspace numberings related to this largest space
2830 std::vector<Space*> spaces(lc.size(), 0);
2831 std::vector<Space*>::iterator its = spaces.begin();
2832 const SuTermVector* stv = dynamic_cast<const SuTermVector*>(lc.begin()->first);
2833 if(stv == 0) error("null_pointer", "SuTermVector");
2834 ValueType vt = stv->valueType();
2835 StrucType st = stv->strucType();
2836 u_p = stv->u_p;
2837 for(LcTerm<SuTermVector>::const_iterator itt = lc.begin(); itt != lc.end(); itt++, its++)
2838 {
2839 const SuTermVector* stv = dynamic_cast<const SuTermVector*>(itt->first);
2840 if(stv == 0) error("null_pointer", "SuTermVector");
2841 *its = stv->space_p; // list of (sub)spaces
2842 if(stv->valueType() == _complex) vt = _complex;
2843 if(stv->strucType() != st)
2844 error("term_mismatch_structures", words("structure", stv->strucType()), words("structure", st));
2845 }
2846 if(lc.coefType() == _complex) vt = _complex;
2847 space_p = mergeSubspaces(spaces, true);
2848
2849 //allocate entries of current SuTermVector
2850 entries_p = new VectorEntry(vt, st, space_p->dimSpace(), u_p->nbOfComponents());
2851
2852 //do linear combination
2853 its = spaces.begin();
2854 for(LcTerm<SuTermVector>::const_iterator itt = lc.begin(); itt != lc.end(); itt++, its++)
2855 {
2856 const SuTermVector* stv = dynamic_cast<const SuTermVector*>(itt->first);
2857 if(!stv->computed()) error("not_computed_term", stv->name());
2858 Space* sp = *its;
2859 //if (sp->typeOfSpace() == _subSpace)
2860 if(sp->typeOfSpace() == _subSpace && sp != space_p)
2861 {
2862 if(vt == _real) entries_p->add(*stv->entries_p, sp->subSpace()->dofNumbers(), itt->second.real());
2863 else entries_p->add(*stv->entries_p, sp->subSpace()->dofNumbers(), itt->second);
2864 }
2865 else //subspace is the largest space (same numbering)
2866 {
2867 if(vt == _real) entries_p->add(*stv->entries_p, itt->second.real());
2868 else entries_p->add(*stv->entries_p, itt->second);
2869 }
2870 }
2871 //may be it is best to delete new subspaces created here (to be done later)
2872 computed() = true;
2873 trace_p->pop();
2874 }
2875
2876 /*! interpolate current sutermvector on u space and domain dom
2877 sutr(i) = sum_j sutv_j w_j(Mi) Mi nodes of Lagrange u-space, Mi in dom
2878 wj shape functions related to sutv
2879 return a new SuTermMatrix allocated here
2880 quite expansive !!!
2881 */
interpolate(const Unknown & u,const GeomDomain & dom)2882 SuTermVector* SuTermVector::interpolate(const Unknown& u, const GeomDomain& dom)
2883 {
2884 trace_p->push("SuTermVector::interpolate(Unknown, GeomDomain)");
2885 if(u.space() == space_p) return onDomain(dom); //same space, apply restriction to domain dom
2886 if(!u.space()->isFE()) error("not_fe_space_type", u.space()->name());
2887 if(u.space()->interpolation()->type != _Lagrange) error("lagrange_fe_space_only", u.space()->name());
2888
2889 //get subspace
2890 Space* spu = u.space();
2891 Space* subsp = Space::findSubSpace(&dom, spu); //find subspace (linked to domain dom) of spu
2892 if(subsp == 0) subsp = new Space(dom, *spu, spu->name() + "_" + dom.name()); //create if not exist
2893
2894 //create suTermVector
2895 std::vector<number_t> dofs = subsp->dofIds();
2896 number_t nd = dofs.size();
2897 string_t na = name_ + "_interpolated_" + u.space()->name() + "_" + dom.name();
2898 SuTermVector* sutv = new SuTermVector(na, &u, subsp, valueType(), nd, u.nbOfComponents());
2899
2900 //travel dofs and interpolate at node, store value
2901 std::vector<number_t>::iterator itd = dofs.begin();
2902 number_t k = 1;
2903 for(; itd != dofs.end(); ++itd, ++k)
2904 {
2905 Point p = subsp->rootSpace()->feSpace()->dofs[*itd - 1].coords();
2906 Value v = evaluate(p);
2907 sutv->entries_p->setValue(k, v);
2908 }
2909 sutv->computed() = true;
2910 trace_p->pop();
2911 return sutv;
2912
2913 }
2914
2915 //! print SuTermVector
print(std::ostream & out) const2916 void SuTermVector::print(std::ostream& out) const
2917 {
2918 print(out, false, true);
2919 }
2920
2921 //if raw=true only x y z v is print
print(std::ostream & out,bool raw,bool header) const2922 void SuTermVector::print(std::ostream& out, bool raw, bool header) const
2923 {
2924 if(theVerboseLevel == 0) return;
2925 if(header && !raw) out << " SuTermVector " << name() << ", " << " unknown " << u_p->name() << ", "
2926 << words("value", valueType()) << " " << words("structure", strucType())
2927 << ", ";
2928 if(sulf_p != 0) out << (*sulf_p) << "\n";
2929 if(!computed())
2930 {
2931 out << words("not computed") << "\n";
2932 return;
2933 }
2934 if(entries_p == 0 && scalar_entries_p == 0)
2935 {
2936 out << " unallocated SuTermVector block" << eol;
2937 return;
2938 }
2939 if(theVerboseLevel < 2) return;
2940 if(!raw)
2941 {
2942 if(nbOfComponents() > 1) out << " (size=" << nbOfComponents() << "),";
2943 out << " " << size() << " " << words("values");
2944 if(theVerboseLevel < 2)
2945 {
2946 out << eol;
2947 return;
2948 }
2949
2950 //first and last values
2951 blanks(eol, 3);
2952 number_t s = size();
2953 number_t n = std::min(number_t(theVerboseLevel), s);
2954
2955 if(entries_p != 0) //display dofid and coordinates when dof is a ponctual fedof
2956 {
2957 number_t dims = space_p->nbDofs();
2958 number_t wd = std::floor(std::log10(dims))+1;
2959 if(2 * n >= dims) //print all value
2960 {
2961 out << ", all values" << eol;
2962 std::vector<string_t> com(dims, "");
2963 number_t w=0;
2964 for(number_t i = 0; i < dims; i++)
2965 { com[i] = space_p->dof(i + 1).dofData(wd); w=std::max(w,com[i].size());}
2966 for(number_t i = 0; i <dims; i++)
2967 {
2968 number_t s = w-com[i].size();
2969 if(s>0) com[i]+= string_t(s,' ');
2970 com[i]+=" -> ";
2971 }
2972 entries_p->printFirst(out, dims, com);
2973 }
2974 else
2975 {
2976 out << ", first and last " << tostring(n) << " values" << eol;
2977 std::vector<string_t> comd(n, ""), comf(n, "");
2978 number_t w=0;
2979 for(number_t i = 0; i < n; i++)
2980 {
2981 comd[i] = space_p->dof(i + 1).dofData(wd); w=std::max(w,comd[i].size());
2982 comf[i] = space_p->dof(dims - n + i + 1).dofData(wd); w=std::max(w,comf[i].size());
2983 }
2984 for(number_t i = 0; i <n; i++)
2985 {
2986 number_t s = w-comd[i].size();
2987 if(s>0) comd[i]+= string_t(s,' ');
2988 comd[i]+=" -> ";
2989 s = w-comf[i].size();
2990 if(s>0) comf[i]+= string_t(s,' ');
2991 comf[i]+=" -> ";
2992 }
2993 entries_p->printFirst(out, n, comd);
2994 out << "..." << eol;
2995 entries_p->printLast(out, n, comf);
2996 }
2997 }
2998 if(scalar_entries_p != 0)
2999 {
3000 out << " scalar entries : " << tostring(scalar_entries_p->size()) << " "
3001 << words("value", valueType()) << " values" << eol;
3002 out << words("firste") << " " << words("row") << " cdofs : ";
3003 number_t nbd = cdofs_.size();
3004 number_t m = std::min(number_t(theVerboseLevel), nbd);
3005 std::vector<DofComponent>::const_iterator itd = cdofs_.begin();
3006 for(number_t i = 0; i < m; i++, itd++) out << *itd << " ";
3007 if(m < nbd) out << "...";
3008 out << eol;
3009 if(scalar_entries_p != entries_p) out << (*scalar_entries_p);
3010 }
3011 blanks(eol, -3);
3012 out << eol;
3013 }
3014 else //raw format
3015 {
3016 if(entries_p != 0)
3017 {
3018 number_t dims = space_p->nbDofs();
3019 std::vector<string_t> com(dims, "");
3020 for(number_t i = 0; i < dims; i++)
3021 {
3022 Point pi = space_p->dof(i + 1).coords();
3023 for(number_t j = 0; j < pi.size(); j++) com[i] += tostring(pi[j]) + " ";
3024 }
3025 entries_p->printFirst(out, dims, com);
3026 }
3027 if(scalar_entries_p != 0 && scalar_entries_p != entries_p)
3028 {
3029 number_t dims = nbOfComponents() * space_p->nbDofs();
3030 std::vector<string_t> com(dims, "");
3031 scalar_entries_p->printFirst(out, dims, com);
3032 }
3033 }
3034 }
3035
innerProduct(const SuTermVector & tv1,const SuTermVector & tv2)3036 complex_t innerProduct(const SuTermVector& tv1, const SuTermVector& tv2)
3037 {
3038 trace_p->push("innerProduct(SuTermVector,SuTermVector)");
3039 if(&tv1 == &tv2) //same SuTermVectors
3040 {
3041 if(tv1.scalar_entries() != 0)
3042 {
3043 trace_p->pop();
3044 return innerProduct(*tv1.scalar_entries(), *tv1.scalar_entries());
3045 }
3046 else
3047 {
3048 trace_p->pop();
3049 return innerProduct(*tv1.entries(), *tv1.entries());
3050 }
3051 }
3052 //check consistancy of unknowns
3053 complex_t res = 0.;
3054 if(tv1.up() != tv2.up() && tv1.up() != tv2.up()->dual_p()) error("term_inconsistent_unknowns");
3055 number_t n1 = tv1.spacep()->dimSpace(), n2 = tv2.spacep()->dimSpace();
3056 if(n1 > n2) res = innerProduct(tv2, tv1);
3057 else
3058 {
3059 bool copyNeeded2=false;
3060 bool toScalar2=false;
3061 bool toVector2=false;
3062 if(tv1.scalar_entries() != 0 && tv1.scalar_entries() != tv1.entries() && tv2.scalar_entries() == 0)
3063 {
3064 copyNeeded2=toScalar2=true;
3065 }
3066 else if(tv1.scalar_entries() == 0 && tv2.scalar_entries() !=0 && tv2.scalar_entries() != tv2.entries())
3067 {
3068 copyNeeded2=toVector2=true;
3069 }
3070
3071 if(copyNeeded2)
3072 {
3073 SuTermVector tv2copy(tv2);
3074 if(toScalar2) tv2copy.toScalar();
3075 if(toVector2) tv2copy.toVector();
3076 if(tv1.scalar_entries() != 0 && tv1.scalar_entries() != tv1.entries() &&
3077 tv2copy.scalar_entries() != 0 && tv2copy.scalar_entries() != tv2copy.entries())
3078 {
3079 if(tv1.spacep() == tv2copy.spacep()) res = innerProduct(*tv1.scalar_entries(), *tv2copy.scalar_entries());
3080 else //align vector
3081 {
3082 bool useDual = (tv1.up() == tv2.up()->dual_p());
3083 tv2copy.extendScalarTo(tv1.cdofs(), useDual); //align tv2copy on tv1
3084 res = innerProduct(*tv1.scalar_entries(), *tv2copy.scalar_entries());
3085 }
3086 }
3087 else
3088 {
3089 if(tv1.entries() == 0) error("null_pointer", "tv1.entries_p");
3090 if(tv2copy.entries() == 0) error("null_pointer", "tv2.entries_p");
3091 if(tv1.spacep() == tv2copy.spacep()) res = innerProduct(*tv1.entries(), *tv2copy.entries());
3092 else //align vector
3093 {
3094 tv2copy.extendTo(tv1); //align tv2copy on tv1
3095 res = innerProduct(*tv1.entries(), *tv2copy.entries());
3096 }
3097 }
3098 }
3099 else
3100 {
3101 if(tv1.scalar_entries() != 0 && tv1.scalar_entries() != tv1.entries() &&
3102 tv2.scalar_entries() != 0 && tv2.scalar_entries() != tv2.entries())
3103 {
3104 if(tv1.spacep() == tv2.spacep()) res = innerProduct(*tv1.scalar_entries(), *tv2.scalar_entries());
3105 else //align vector
3106 {
3107 SuTermVector tw2(tv2); //copy tv2
3108 bool useDual = (tv1.up() == tv2.up()->dual_p());
3109 tw2.extendScalarTo(tv1.cdofs(), useDual); //align tw2 on tv1
3110 res = innerProduct(*tv1.scalar_entries(), *tw2.scalar_entries());
3111 }
3112 }
3113 else
3114 {
3115 if(tv1.entries() == 0) error("null_pointer", "tv1.entries_p");
3116 if(tv2.entries() == 0) error("null_pointer", "tv2.entries_p");
3117 if(tv1.spacep() == tv2.spacep()) res = innerProduct(*tv1.entries(), *tv2.entries());
3118 else //align vector
3119 {
3120 SuTermVector tw2(tv2); //copy tv2
3121 tw2.extendTo(tv1); //align tw2 on tv1
3122 res = innerProduct(*tv1.entries(), *tw2.entries());
3123 }
3124 }
3125 }
3126 }
3127 trace_p->pop();
3128 return res;
3129 }
3130
hermitianProduct(const SuTermVector & tv1,const SuTermVector & tv2)3131 complex_t hermitianProduct(const SuTermVector& tv1, const SuTermVector& tv2)
3132 {
3133 trace_p->push("hermitianProduct(SuTermVector,SuTermVector)");
3134 complex_t res = 0;
3135 if(&tv1 == &tv2) //same SuTermVectors
3136 {
3137 if(tv1.scalar_entries() != 0)
3138 {
3139 trace_p->pop();
3140 return hermitianProduct(*tv1.scalar_entries(), *tv1.scalar_entries());
3141 }
3142 else
3143 {
3144 trace_p->pop();
3145 return hermitianProduct(*tv1.entries(), *tv1.entries());
3146 }
3147 }
3148 //check consistancy of unknowns
3149 if(tv1.up() != tv2.up() && tv1.up() != tv2.up()->dual_p()) error("term_inconsistent_unknowns");
3150 number_t n1 = tv1.spacep()->dimSpace(), n2 = tv2.spacep()->dimSpace();
3151 if(n1 > n2) res = std::conj(hermitianProduct(tv2, tv1));
3152 else
3153 {
3154 bool copyNeeded2=false;
3155 bool toScalar2=false;
3156 bool toVector2=false;
3157 if(tv1.scalar_entries() != 0 && tv1.scalar_entries() != tv1.entries() && tv2.scalar_entries() == 0)
3158 {
3159 copyNeeded2=toScalar2=true;
3160 }
3161 else if(tv1.scalar_entries() == 0 && tv2.scalar_entries() != 0 && tv2.scalar_entries() != tv2.entries())
3162 {
3163 copyNeeded2=toVector2=true;
3164 }
3165
3166 if(copyNeeded2)
3167 {
3168 SuTermVector tv2copy(tv2);
3169 if(toScalar2) tv2copy.toScalar();
3170 if(toVector2) tv2copy.toVector();
3171 if(tv1.scalar_entries() != 0 && tv1.scalar_entries() != tv1.entries() &&
3172 tv2copy.scalar_entries() != 0 && tv2copy.scalar_entries() != tv2copy.entries())
3173 {
3174 if(tv1.spacep() == tv2copy.spacep()) res = hermitianProduct(*tv1.scalar_entries(), *tv2copy.scalar_entries());
3175 else //align vector
3176 {
3177 bool useDual = (tv1.up() == tv2.up()->dual_p());
3178 tv2copy.extendScalarTo(tv1.cdofs(), useDual); //align tv2copy on tv1
3179 res = hermitianProduct(*tv1.scalar_entries(), *tv2copy.scalar_entries());
3180 }
3181 }
3182 else
3183 {
3184 if(tv1.entries() == 0) error("null_pointer", "tv1.entries_p");
3185 if(tv2copy.entries() == 0) error("null_pointer", "tv2.entries_p");
3186 if(tv1.spacep() == tv2copy.spacep()) res = hermitianProduct(*tv1.entries(), *tv2copy.entries());
3187 else //align vector
3188 {
3189 tv2copy.extendTo(tv1); //align tv2copy on tv1
3190 res = hermitianProduct(*tv1.entries(), *tv2copy.entries());
3191 }
3192 }
3193 }
3194 else
3195 {
3196 if(tv1.scalar_entries() != 0 && tv1.scalar_entries() != tv1.entries() &&
3197 tv2.scalar_entries() != 0 && tv2.scalar_entries() != tv2.entries())
3198 {
3199 if(tv1.spacep() == tv2.spacep()) res = hermitianProduct(*tv1.scalar_entries(), *tv2.scalar_entries());
3200 else //align vector
3201 {
3202 SuTermVector tw2(tv2); //copy tv2
3203 bool useDual = (tv1.up() == tv2.up()->dual_p());
3204 tw2.extendScalarTo(tv1.cdofs(), useDual); //align tw2 on tv1
3205 res = hermitianProduct(*tv1.scalar_entries(), *tw2.scalar_entries());
3206 }
3207 }
3208 else
3209 {
3210 if(tv1.entries() == 0) error("null_pointer", "tv1.entries_p");
3211 if(tv2.entries() == 0) error("null_pointer", "tv2.entries_p");
3212 if(tv1.spacep() == tv2.spacep()) res = hermitianProduct(*tv1.entries(), *tv2.entries());
3213 else //align vector
3214 {
3215 SuTermVector tw2(tv2); //copy tv2
3216 tw2.extendTo(tv1); //align tw2 on tv1
3217 res = hermitianProduct(*tv1.entries(), *tw2.entries());
3218 }
3219 }
3220 }
3221 }
3222 trace_p->pop();
3223 return res;
3224 }
3225
3226 // vector norms
norm1(const SuTermVector & tv)3227 real_t norm1(const SuTermVector& tv)
3228 {
3229 if(tv.scalar_entries() != 0) return norm1(*tv.scalar_entries());
3230 if(tv.entries() != 0) return norm1(*tv.entries());
3231 return 0.;
3232 }
3233
norminfty(const SuTermVector & tv)3234 real_t norminfty(const SuTermVector& tv)
3235 {
3236 if(tv.scalar_entries() != 0) return norminfty(*tv.scalar_entries());
3237 if(tv.entries() != 0) return norminfty(*tv.entries());
3238 return 0.;
3239 }
3240
3241 // return the value (in complex) of component being the largest one in absolute value
3242 // travel all SCALAR components of SuTermVector using scalar entries if exists
maxValAbs() const3243 complex_t SuTermVector::maxValAbs() const
3244 {
3245 if(scalar_entries_p != 0) return scalar_entries_p->maxValAbs();
3246 if(entries_p != 0) return entries_p->maxValAbs();
3247 return complex_t(0.);
3248 }
3249
3250 //=================================================================================
3251 // SuTermVectors member functions
3252 //=================================================================================
3253
3254 // move all SuTermVector's to real
toReal()3255 SuTermVectors& SuTermVectors::toReal()
3256 {
3257 std::vector<SuTermVector>::iterator itv = begin();
3258 for(; itv != end(); itv++) itv->toReal();
3259 return *this;
3260 }
3261
toImag()3262 SuTermVectors& SuTermVectors::toImag()
3263 {
3264 std::vector<SuTermVector>::iterator itv = begin();
3265 for(; itv != end(); itv++) itv->toImag();
3266 return *this;
3267 }
3268
print(std::ostream & os) const3269 void SuTermVectors::print(std::ostream& os) const
3270 {
3271 os << "list of SuTermVector's (" << size() << ")" << eol;
3272 if(theVerboseLevel < 2) return;
3273 std::vector<SuTermVector>::const_iterator itv = begin();
3274 for(; itv != end(); itv++) itv->print(os);
3275 }
3276
operator <<(std::ostream & os,const SuTermVectors & tvs)3277 std::ostream& operator<<(std::ostream& os, const SuTermVectors& tvs)
3278 {
3279 tvs.print(os);
3280 return os;
3281 }
3282
3283 /*! adjust the scalar entries to the cdofs numbering newcdofs
3284 when cdofs is included in newcdofs, new zeros are introduced (extension)
3285 when newcdofs is included in cdofs , coefficients are removed (restriction)
3286 else it is in a same time a restriction (removed cdofs) and an extension (omitted cdof)
3287 in any case, the coefficient may be permuted and cdofs = newcdofs at the end
3288
3289 used by SuTermVector and TermVector
3290 */
adjustScalarEntriesG(VectorEntry * & scalar_entries_p,std::vector<DofComponent> & cdofs,const std::vector<DofComponent> & newcdofs)3291 void adjustScalarEntriesG(VectorEntry*& scalar_entries_p, std::vector<DofComponent>& cdofs, const std::vector<DofComponent>& newcdofs)
3292 {
3293 trace_p->push("adjustScalarEntriesG(VectorEntry*, vector<DofComponent>&, vector<DofComponent>&)");
3294 std::map<DofComponent, number_t> mcdofs;
3295 std::vector<DofComponent>::iterator itd = cdofs.begin();
3296 std::vector<DofComponent>::const_iterator itn = newcdofs.begin();
3297 number_t k = 0;
3298 bool sameNum = true;
3299 for(; itd != cdofs.end(); itd++, k++)
3300 {
3301 mcdofs[*itd] = k;
3302 if(sameNum && itn != newcdofs.end())
3303 {
3304 if(*itd != *itn && *itd != itn->dual()) sameNum = false; //allows dual unknown (permissive)
3305 itn++;
3306 }
3307 }
3308 if(sameNum && cdofs.size() == newcdofs.size())
3309 {
3310 trace_p->pop(); //nothing done
3311 return;
3312 }
3313
3314 //create new vector
3315 ValueType vt = _real;
3316 if(scalar_entries_p != 0) vt = scalar_entries_p->valueType_;
3317 VectorEntry* ve = new VectorEntry(vt, _scalar, newcdofs.size());
3318 std::map<DofComponent, number_t>::iterator itmd;
3319 if(vt == _real) //real case
3320 {
3321 Vector<real_t>::iterator itve = ve->beginr(), itv = scalar_entries_p->beginr();
3322 for(itn = newcdofs.begin(); itn != newcdofs.end(); itn++, itve++)
3323 {
3324 itmd = mcdofs.find(*itn);
3325 if(itmd == mcdofs.end()) itmd = mcdofs.find(itn->dual());
3326 if(itmd != mcdofs.end()) *itve = *(itv + itmd->second);
3327 }
3328 }
3329 else //complex case
3330 {
3331 Vector<complex_t>::iterator itve = ve->beginc(), itv = scalar_entries_p->beginc();
3332 for(itn = newcdofs.begin(); itn != newcdofs.end(); itn++, itve++)
3333 {
3334 itmd = mcdofs.find(*itn);
3335 if(itmd == mcdofs.end()) itmd = mcdofs.find(itn->dual()); //find with dual (permissive)
3336 if(itmd != mcdofs.end()) *itve = *(itv + itmd->second);
3337 }
3338 }
3339 //update current vector
3340 if(scalar_entries_p != 0) delete scalar_entries_p;
3341 scalar_entries_p = ve;
3342 cdofs = newcdofs;
3343 trace_p->pop();
3344 }
3345
3346 } //end of namespace xlifepp
3347