Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
FE_def.hpp
1#ifndef FE_DEF_hpp
2#define FE_DEF_hpp
3
4#include <string>
5#include "feddlib/core/core_config.h"
6#ifdef FEDD_HAVE_ACEGENINTERFACE
7#include <aceinterface.hpp>
8#endif
9
18
19
20int MMAInitialisationCode[]={
21 0,0
22};
23
24
25using Teuchos::reduceAll;
26using Teuchos::REDUCE_SUM;
27using Teuchos::outArg;
28
29namespace FEDD {
30DataElement::DataElement():
31ht_(1,0.),
32hp_(1,0.)
33{
34
35}
36
37DataElement::DataElement(int size):
38ht_(size,0.),
39hp_(size,0.)
40{
41
42}
43
44std::vector<double> DataElement::getHp()
45{
46 return hp_;
47}
48
49std::vector<double> DataElement::getHt()
50{
51 return ht_;
52}
53
54void DataElement::setHp( double* ht )
55{
56 for (int i=0; i<hp_.size(); i++)
57 hp_[i] = ht[i];
58}
59
63template <class SC, class LO, class GO, class NO>
64FE<SC,LO,GO,NO>::FE(bool saveAssembly):FE_ElementAssembly<SC, LO, GO, NO>(saveAssembly),
65ed_(0),
66es_()
67{
68}
69
70
71template <class SC, class LO, class GO, class NO>
72void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
73 vec3D_dbl_Type& dPhiOut,
74 SmallMatrix<SC>& Binv){
75 UN dim = Binv.size();
76 for (UN w=0; w<dPhiIn->size(); w++){
77 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
78 for (UN d1=0; d1<dim; d1++) {
79 for (UN d2=0; d2<dim; d2++) {
80 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
81 }
82 }
83 }
84 }
85}
86
87
88template <class SC, class LO, class GO, class NO>
89void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
90 vec3D_dbl_Type& dPhiOut,
91 const SmallMatrix<SC>& Binv){
92 UN dim = Binv.size();
93 for (UN w=0; w<dPhiIn->size(); w++){
94 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
95 for (UN d1=0; d1<dim; d1++) {
96 for (UN d2=0; d2<dim; d2++) {
97 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
98 }
99 }
100 }
101 }
102}
103
104
105template <class SC, class LO, class GO, class NO>
106void FE<SC,LO,GO,NO>::assemblyIdentity(MatrixPtr_Type &A){
107 Teuchos::Array<SC> value(1, Teuchos::ScalarTraits<SC>::one() );
108 Teuchos::Array<GO> index(1);
109 MapConstPtr_Type map = A->getMap();
110 for (int i=0; i<A->getNodeNumRows(); i++) {
111 index[0] = map->getGlobalElement( i );
112 A->insertGlobalValues( index[0], index(), value() );
113 }
114 A->fillComplete();
115}
116
117
118template <class SC, class LO, class GO, class NO>
119void FE<SC,LO,GO,NO>::assemblySurfaceRobinBC(int dim,
120 std::string FETypeP,
121 std::string FETypeV,
122 MultiVectorPtr_Type u,
123 MatrixPtr_Type A,
124 std::vector<SC>& funcParameter,
125 RhsFunc_Type func,
126 ParameterListPtr_Type parameters){
127
128 ElementsPtr_Type elements = this->domainVec_.at(1)->getElementsC();
129 ElementsPtr_Type elementsV = this->domainVec_.at(0)->getElementsC();
130
131 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(1)->getPointsRepeated();
132
133 MapConstPtr_Type map = this->domainVec_.at(1)->getMapRepeated();
134
135 vec2D_dbl_ptr_Type phi,phiV;
136 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
137
138
139 UN extraDeg = Helper::determineDegree( dim-1, FETypeV, Helper::Deriv0);
140 UN deg = Helper::determineDegree( dim-1, FETypeP, Helper::Deriv0)*2 + extraDeg;
141
142
143 Helper::getPhi(phi, weights, dim-1, FETypeP, deg);
144 Helper::getPhi(phiV, weights, dim-1, FETypeV, deg);
145
146 SC detB;
147 SC absDetB;
148 SmallMatrix<SC> B(dim);
149
150
151 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
152 vec_dbl_Type uLocN( weights->size() , -1. );
153
154 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
155
156
157 SC elScaling;
158 vec_dbl_Type b(dim);
159
160 std::vector<double> valueFunc(dim);
161 // The second last entry is a placeholder for the surface element flag. It will be set below
162 SC* paramsFunc = &(funcParameter[0]);
163 for (UN T=0; T<elements->numberElements(); T++) {
164 FiniteElement fe = elementsV->getElement( T );
165 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
166 for (int surface=0; surface<fe.numSubElements(); surface++) {
167 FiniteElement feSub = subEl->getElement( surface );
168 if(subEl->getDimension() == dim-1){
169 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
170
171 vec_int_Type nodeList = feSub.getVectorNodeListNonConst();
172 vec_int_Type nodeListP = elements->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
173
174 vec_dbl_Type v_E(dim,1.);
175 double norm_v_E=1.;
176 vec_dbl_Type x(dim,0.); //dummy
177 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
178
179 func( &x[0], &valueFunc[0], paramsFunc);
180 if(valueFunc[0] > 0.){
181 Helper::computeSurfaceNormal(dim, pointsRep,nodeListP,v_E,norm_v_E);
182
183 Helper::buildTransformationSurface( nodeListP, pointsRep, B, b, FETypeP);
184
185 elScaling = B.computeScaling( );
186 for (int w=0; w<phiV->size(); w++){ //quads points
187 for (int d=0; d<dim; d++) {
188 uLoc[d][w] = 0.;
189 for (int i=0; i < phiV->at(0).size(); i++) {
190 LO index = dim * nodeList[i] + d;
191 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
192 }
193 }
194 }
195 for (int w=0; w<phiV->size(); w++){ //quads points
196 uLocN[w] = 0.;
197 for (int d=0; d<dim; d++) {
198 uLocN[w] += uLoc[d][w] *v_E[d] / norm_v_E;
199 }
200 }
201 for (UN i=0; i < phi->at(0).size(); i++) {
202 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
203 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
204 for (UN j=0; j < value.size(); j++) {
205 for (UN w=0; w<phi->size(); w++) {
206 value[j] += weights->at(w) * uLocN[w]* (*phi)[w][j] * (*phi)[w][i] ;
207 }
208 value[j] *= elScaling;
209 indices[j] = GO ( map->getGlobalElement( nodeListP[j] ) );
210 }
211
212 GO row = GO ( map->getGlobalElement( nodeListP[i] ) );
213 A->insertGlobalValues( row, indices(), value() );
214 }
215
216 }
217 }
218 }
219 }
220 A->fillComplete();
221}
222
223// Assembling the nonlinear reaction part of Reaction-Diffusion equation
224// Gerneral function in case of nonlinear reaction function
225// template <class SC, class LO, class GO, class NO>
226// void FE<SC,LO,GO,NO>::assemblyReactionTerm(int dim,
227// std::string FEType,
228// MatrixPtr_Type &A,
229// MultiVectorPtr_Type u,
230// bool callFillComplete,
231// std::vector<SC>& funcParameter,
232// RhsFunc_Type reactionFunc){
233
234// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
235// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
236
237// UN FEloc = this->checkFE(dim,FEType);
238
239// ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
240
241// vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
242
243// MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
244
245// vec2D_dbl_ptr_Type phi;
246// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
247
248// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
249
250// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
251// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
252// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
253// extraDeg;
254
255// Helper::getPhi(phi, weights, dim, FEType, deg);
256
257// // We have a scalar value of concentration in each point
258// vec_dbl_Type uLoc( weights->size() , -1. );
259// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
260
261// std::vector<double> valueFunc(1);
262
263// SC* paras = &(funcParameter[0]);
264
265// SC detB;
266// SC absDetB;
267// SmallMatrix<SC> B(dim);
268// SmallMatrix<SC> Binv(dim);
269
270// for (UN T=0; T<elements->numberElements(); T++) {
271// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
272// detB = B.computeInverse(Binv);
273// absDetB = std::fabs(detB);
274
275// // Building u
276// for (int w=0; w<phi->size(); w++){ //quadpoints
277// uLoc[w] = 0.;
278// for (int i=0; i < phi->at(0).size(); i++) { // points of element
279// LO index = elements->getElement(T).getNode(i);
280// uLoc[w] += uArray[index] * phi->at(w).at(i);
281// }
282// }
283
284// for (UN i=0; i < phi->at(0).size(); i++) {
285// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
286// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
287// for (UN j=0; j < value.size(); j++) {
288// for (UN w=0; w<phi->size(); w++) {
289// value[j] += weights->at(w) * uLoc[w] * (*phi)[w][i] ;
290// }
291// reactionFunc(&value[j], &valueFunc[0] ,paras);
292
293// value[j] *= valueFunc[0] * absDetB;
294// if (this->setZeros_ && std::fabs(value[j]) < this->myeps_) {
295// value[j] = 0.;
296// }
297// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
298
299// }
300// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
301
302
303// A->insertGlobalValues( row, indices(), value() );
304
305// }
306// }
307
308// if (callFillComplete)
309// A->fillComplete();
310// }
311
312
313// // Assembling the nonlinear reaction part of Reaction-Diffusion equation
314// template <class SC, class LO, class GO, class NO>
315// void FE<SC,LO,GO,NO>::assemblyLinearReactionTerm(int dim,
316// std::string FEType,
317// MatrixPtr_Type &A,
318// bool callFillComplete,
319// std::vector<SC>& funcParameter,
320// RhsFunc_Type reactionFunc){
321
322// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
323// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
324
325// UN FEloc = this->checkFE(dim,FEType);
326
327// ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
328
329// vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
330
331// MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
332
333// vec2D_dbl_ptr_Type phi;
334// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
335
336// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
337// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
338// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
339// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
340// extraDeg;
341
342// Helper::getPhi(phi, weights, dim, FEType, deg);
343
344// std::vector<double> valueFunc(1);
345
346// SC* paras = &(funcParameter[0]);
347
348// SC detB;
349// SC absDetB;
350// SmallMatrix<SC> B(dim);
351// SmallMatrix<SC> Binv(dim);
352
353// for (UN T=0; T<elements->numberElements(); T++) {
354// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
355// detB = B.computeInverse(Binv);
356// absDetB = std::fabs(detB);
357
358// for (UN i=0; i < phi->at(0).size(); i++) {
359// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
360// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
361// for (UN j=0; j < value.size(); j++) {
362// for (UN w=0; w<phi->size(); w++) {
363// value[j] += weights->at(w) * (*phi)[w][j] * (*phi)[w][i] ;
364// }
365// reactionFunc(&value[j], &valueFunc[0] ,paras);
366
367// value[j] *= valueFunc[0] * absDetB;
368// if (this->setZeros_ && std::fabs(value[j]) < this->myeps_) {
369// value[j] = 0.;
370// }
371// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
372
373// }
374// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
375
376// A->insertGlobalValues( row, indices(), value() );
378// }
379// }
380// if (callFillComplete)
381// A->fillComplete();
382
383// A->print();
385// }
386
387// Assembling the nonlinear reaction part of Reaction-Diffusion equation
388// template <class SC, class LO, class GO, class NO>
389// void FE<SC,LO,GO,NO>::assemblyDReactionTerm(int dim,
390// std::string FEType,
391// MatrixPtr_Type &A,
392// MultiVectorPtr_Type u,
393// bool callFillComplete,
394// std::vector<SC>& funcParameter,
395// RhsFunc_Type reactionFunc){
396
397// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
398// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
399
400// UN FEloc = this->checkFE(dim,FEType);
402// ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
403
404// vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
405
406// MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
407
408// vec2D_dbl_ptr_Type phi;
409// vec3D_dbl_ptr_Type dPhi;
410// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
411
412// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
413// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
414// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
415// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
416// extraDeg;
417
418// Helper::getPhi(phi, weights, dim, FEType, deg);
419
420// Helper::getDPhi(dPhi, weights, dim, FEType, deg);
421
422// // We have a scalar value of concentration in each point
423// vec2D_dbl_Type duLoc( weights->size() ,vec_dbl_Type(dim ,-1. ));
424// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
425
426// std::vector<double> valueFunc(1);
427
428// SC* paras = &(funcParameter[0]);
429
430// SC detB;
431// SC absDetB;
432// SmallMatrix<SC> B(dim);
433// SmallMatrix<SC> Binv(dim);
434
435// for (UN T=0; T<elements->numberElements(); T++) {
436
437
438// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
439// detB = B.computeInverse(Binv);
440// absDetB = std::fabs(detB);
441
442// vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
443// applyBTinv( dPhi, dPhiTrans, Binv );
444
445// for (int w=0; w<dPhiTrans.size(); w++){ //quads points
446// for (int i=0; i < dPhiTrans[0].size(); i++) {
447// LO index = elements->getElement(T).getNode(i) ;
448// for (int d2=0; d2<dim; d2++)
449// duLoc[w][d2] += uArray[index] * dPhiTrans[w][i][d2];
450// }
451
452// }
453
454
455// for (UN i=0; i < phi->at(0).size(); i++) {
456// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
457// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
458// for (UN j=0; j < value.size(); j++) {
459// for (UN d2=0; d2<dim; d2++){
460// for (UN w=0; w<phi->size(); w++) {
461// value[j] += weights->at(w) * duLoc[w][d2] * (*phi)[w][i] ;
462// }
463// }
464// reactionFunc(&value[j], &valueFunc[0] ,paras);
465
466// value[j] *= valueFunc[0] * absDetB;
467// if (this->setZeros_ && std::fabs(value[j]) < this->myeps_) {
468// value[j] = 0.;
469// }
470// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
471
472// }
473// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
474// A->insertGlobalValues( row, indices(), value() );
475// }
476// }
477
478// if (callFillComplete)
479// A->fillComplete();
480// }
481
482
483
484
485template <class SC, class LO, class GO, class NO>
486void FE<SC,LO,GO,NO>::assemblyLaplaceDiffusion(int dim,
487 std::string FEType,
488 int degree,
489 MatrixPtr_Type &A,
490 vec2D_dbl_Type diffusionTensor,
491 bool callFillComplete,
492 int FELocExternal){
493 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
494 UN FEloc;
495 if (FELocExternal<0)
496 FEloc = this->checkFE(dim,FEType);
497 else
498 FEloc = FELocExternal;
499
500 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
501
502 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
503
504 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
505
506 vec3D_dbl_ptr_Type dPhi;
507 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
508
509 // inner( grad(u) , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
510 // The diffusion tensor is constant and, thus, does not require a higher-order quadrature rule.
511 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);//+1;
512 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
513
514 SC detB;
515 SC absDetB;
516 SmallMatrix<SC> B(dim);
517 SmallMatrix<SC> Binv(dim);
518 GO glob_i, glob_j;
519 vec_dbl_Type v_i(dim);
520 vec_dbl_Type v_j(dim);
521
522
523 SmallMatrix<SC> diffusionT(dim);
524 // Linear Diffusion Tensor
525 if(diffusionTensor.size()==0 || diffusionTensor.size() < dim ){
526 vec2D_dbl_Type diffusionTensor(3,vec_dbl_Type(3,0));
527 for(int i=0; i< dim; i++){
528 diffusionTensor[i][i]=1.;
529 }
530 }
531
532 for(int i=0; i< dim; i++){
533 for(int j=0; j<dim; j++){
534 diffusionT[i][j]=diffusionTensor[i][j];
535 }
536 }
537 //Teuchos::ArrayRCP< SC > linearDiff = diffusionTensor->getDataNonConst( 0 );
538 //std::cout << "Assembly Info " << "num Elements " << elements->numberElements() << " num Nodes " << pointsRep->size() << std::endl;
539 for (UN T=0; T<elements->numberElements(); T++) {
540
541 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
542 detB = B.computeInverse(Binv);
543 absDetB = std::fabs(detB);
544
545 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
546 applyBTinv( dPhi, dPhiTrans, Binv );
547
548 vec3D_dbl_Type dPhiTransDiff( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
549 applyDiff( dPhiTrans, dPhiTransDiff, diffusionT );
550
551 for (UN i=0; i < dPhiTrans[0].size(); i++) {
552 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
553 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
554
555 for (UN j=0; j < value.size(); j++) {
556 for (UN w=0; w<dPhiTrans.size(); w++) {
557 for (UN d=0; d<dim; d++){
558 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTransDiff[w][j][d];
559 }
560 }
561 value[j] *= absDetB;
562 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
563 if (this->setZeros_ && std::fabs(value[j]) < this->myeps_) {
564 value[j] = 0.;
565 }
566 }
567 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
568
569 A->insertGlobalValues( row, indices(), value() );
570 }
571
572
573 }
574 if (callFillComplete)
575 A->fillComplete();
576
577}
578
579template <class SC, class LO, class GO, class NO>
580void FE<SC,LO,GO,NO>::applyDiff( vec3D_dbl_Type& dPhiIn,
581 vec3D_dbl_Type& dPhiOut,
582 SmallMatrix<SC>& diffT){
583 UN dim = diffT.size();
584 for (UN w=0; w<dPhiIn.size(); w++){
585 for (UN i=0; i < dPhiIn[w].size(); i++) {
586 for (UN d1=0; d1<dim; d1++) {
587 for (UN d2=0; d2<dim; d2++) {
588 dPhiOut[w][i][d1] += dPhiIn[w][i][d2]* diffT[d2][d1];
589 }
590 }
591 }
592 }
593}
594
595// template <class SC, class LO, class GO, class NO>
596// void FE<SC,LO,GO,NO>::assemblyAceGenTPM( MatrixPtr_Type &A00,
597// MatrixPtr_Type &A01,
598// MatrixPtr_Type &A10,
599// MatrixPtr_Type &A11,
600// MultiVectorPtr_Type &F0,
601// MultiVectorPtr_Type &F1,
602// MapPtr_Type &mapRepeated1,
603// MapPtr_Type &mapRepeated2,
604// ParameterListPtr_Type parameterList,
605// MultiVectorPtr_Type u_repeatedNewton,
606// MultiVectorPtr_Type p_repeatedNewton,
607// MultiVectorPtr_Type u_repeatedTime,
608// MultiVectorPtr_Type p_repeatedTime,
609// bool update,
610// bool updateHistory)
611// {
612
613
614// std::string tpmType = parameterList->sublist("Parameter").get("TPM Type","Biot");
615
616// int dim = this->domainVec_[0]->getDimension();
617// int idata = 1; //= we should init this
618// int ic = -1; int ng = -1;
619
620// //ed.hp:history previous (timestep); previous solution (velocity and acceleration)
621// //ed.ht:? same length as hp
622// ElementsPtr_Type elements1 = this->domainVec_[0]->getElementsC();
623// ElementsPtr_Type elements2 = this->domainVec_[1]->getElementsC();
624
625// int sizeED = 24; /* 2D case for P2 elements:
626// 12 velocities, 12 accelerations (2 dof per P2 node)
627// */
628// if (dim==3)
629// sizeED = 60;/* 3D case for P2 elements:
630// 30 velocities, 30 accelerations (3 dof per P2 node)
631// */
632// if (ed_.size()==0){
633// for (UN T=0; T<elements1->numberElements(); T++)
634// ed_.push_back( Teuchos::rcp(new DataElement( sizeED )) );
635// }
636
637// std::vector<ElementSpec> es_vec( parameterList->sublist("Parameter").get("Number of materials",1) , ElementSpec());
638// vec2D_dbl_Type dataVec( parameterList->sublist("Parameter").get("Number of materials",1), vec_dbl_Type(6,0.) );
639
640// for (int i=0; i<dataVec.size(); i++) {
641// if (tpmType == "Biot") {
642// if (dim==2) {
643// dataVec[i][0] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
644// dataVec[i][1] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
645// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
646// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
647// dataVec[i][4] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
648// dataVec[i][5] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
649// }
650// else if (dim==3) {
651// dataVec[i].resize(12);
652// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),2.e5);
653// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
654// dataVec[i][2] = 0.; //body force x
655// dataVec[i][3] = 0.; //body force y
656// dataVec[i][4] = parameterList->sublist("Parameter").get("body force z"+std::to_string(i+1),0.);; //body force z
657// dataVec[i][5] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.67);
658// dataVec[i][6] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),0.01);
659// dataVec[i][7] = 2000.; //effective density solid
660// dataVec[i][8] = 1000.; //effective density fluid?
661// dataVec[i][9] = 9.81; // gravity
662// dataVec[i][10] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
663// dataVec[i][11] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
664// }
665// }
666
667
668// else if (tpmType == "Biot-StVK") {
669// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
670// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
671// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
672// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
673// dataVec[i][4] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
674// dataVec[i][5] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
675// }
676// }
677
678// for (int i=0; i<es_vec.size(); i++){
679// if(tpmType == "Biot"){
680// if (dim==2)
681// this->SMTSetElSpecBiot(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
682// else if(dim==3)
683// this->SMTSetElSpecBiot3D(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
684// }
685// else if(tpmType == "Biot-StVK")
686// this->SMTSetElSpecBiotStVK(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
687// }
688// LO elementSizePhase = elements1->nodesPerElement();
689// LO sizePhase = dim * elementSizePhase;
690// LO sizePressure = elements2->nodesPerElement();
691// GO sizePhaseGlobal = A00->getMap()->getMaxAllGlobalIndex()+1;
692// int workingVectorSize;
693// if(tpmType == "Biot"){
694// if (dim==2)
695// workingVectorSize = 5523;
696// else if(dim==3)
697// workingVectorSize = 1817;
698// }
699// else if(tpmType == "Biot-StVK")
700// workingVectorSize = 5223;
701
702// double* v = new double [workingVectorSize];
703
704// // nd sind Nodalwerte, Anzahl an structs in nd sollte den Knoten entsprechen, bei P2-P1 in 2D also 9
705// // In X stehen die Koordinaten, X[0] ist x-Koordinate, X[1] ist y-Koordinate, etc.
706// // nd->X[0]
707// // at ist die Loesung im letzten Newtonschritt.
708// // nd[0]->at[0];
709// // ap ist die Loesung im letzten Zeitschritt.
710// // nd[0]->ap[0]
711// // rdata ist die Zeitschrittweite, RD_TimeIncrement wird in sms.h definiert, entsprechend wird auch die Laenge von rdata dort definiert. Standard 400, aber auch nicht gesetzt. Wert muss selber initialisiert werden; eventuell kuerzer moeglich.
712
713// std::vector<double> rdata(RD_TimeIncrement+1, 0.);
714
715// rdata[RD_TimeIncrement] = parameterList->sublist("Timestepping Parameter").get("dt",0.01);
716
717// NodeSpec *ns=NULL;//dummy not need in SKR
718
719// NodeData** nd = new NodeData*[ elementSizePhase + sizePressure ];
720
721// for (int i=0; i<elementSizePhase + sizePressure; i++){
722// nd[i] = new NodeData();
723// }
724
725// int numNodes = elementSizePhase + sizePressure;
726
727// vec2D_dbl_Type xFull( numNodes, vec_dbl_Type(dim,0.) );
728// vec2D_dbl_Type atFull( numNodes, vec_dbl_Type(dim,0.) );
729// vec2D_dbl_Type apFull( numNodes, vec_dbl_Type(dim,0.) );
730
731// for (int i=0; i<elementSizePhase + sizePressure; i++) {
732// nd[i]->X = &(xFull[i][0]);
733// nd[i]->at = &(atFull[i][0]);
734// nd[i]->ap = &(apFull[i][0]);
735// }
736
737// GO offsetMap1 = dim * mapRepeated1->getMaxAllGlobalIndex()+1;
738// vec2D_dbl_ptr_Type pointsRepU = this->domainVec_.at(0)->getPointsRepeated();
739// vec2D_dbl_ptr_Type pointsRepP = this->domainVec_.at(1)->getPointsRepeated();
740
741// Teuchos::ArrayRCP< const SC > uArrayNewton = u_repeatedNewton->getData(0);
742// Teuchos::ArrayRCP< const SC > pArrayNewton = p_repeatedNewton->getData(0);
743// Teuchos::ArrayRCP< const SC > uArrayTime = u_repeatedTime->getData(0);
744// Teuchos::ArrayRCP< const SC > pArrayTime = p_repeatedTime->getData(0);
745
746// double** mat = new double*[sizePhase+sizePressure];
747// for (int i=0; i<sizePhase+sizePressure; i++){
748// mat[i] = new double[sizePhase+sizePressure];
749// }
750
751// Teuchos::ArrayRCP<SC> fValues0 = F0->getDataNonConst(0);
752// Teuchos::ArrayRCP<SC> fValues1 = F1->getDataNonConst(0);
753
754// // Element loop
755
756// ElementData ed = ElementData();
757// for (UN T=0; T<elements1->numberElements(); T++) {
758
759// std::vector<double> tmpHp = ed_[T]->getHp(); // Dies sind die alten Daten
760// std::vector<double> tmpHt = ed_[T]->getHt(); // Dies sind die neuen Daten nachdem das Element aufgerufen wurde, wir hier eigentlich nicht als Variable in ed_ benoetigt.
761// ed.hp = &tmpHp[0];
762// ed.ht = &tmpHt[0];
763
764// int materialFlag = elements1->getElement(T).getFlag();
765// TEUCHOS_TEST_FOR_EXCEPTION( materialFlag>es_vec.size()-1, std::runtime_error, "There are not enought material parameters initialized." ) ;
766// int counter=0;
767// //Newtonloesung at und Zeitschrittloesung ap
768// for (int j=0; j<elementSizePhase; j++) {
769// for (int d=0; d<dim; d++) {
770// LO index = dim * elements1->getElement(T).getNode(j)+d;//dim * elements1->at(T).at( j ) + d;
771// atFull[j][d] = uArrayNewton[index];
772// apFull[j][d] = uArrayTime[index];
773// }
774// }
775// for (int j=0; j<sizePressure; j++) {
776// LO index = elements2->getElement(T).getNode(j);//elements2->at(T).at( j );
777// atFull[elementSizePhase+j][0] = pArrayNewton[index];
778// apFull[elementSizePhase+j][0] = pArrayTime[index];
779// }
780
781// //Nodes
782// for (int j=0; j<elementSizePhase; j++ ) {
783// LO index = elements1->getElement(T).getNode(j);
784// for (int d=0; d<dim; d++) {
785// xFull[j][d] = (*pointsRepU)[index][d];
786// }
787// }
788// for (int j=0; j<sizePressure; j++ ) {
789// LO index = elements2->getElement(T).getNode(j);
790// for (int d=0; d<dim; d++) {
791// xFull[elementSizePhase+j][d] = (*pointsRepP)[index][d];
792// }
793// }
794// vec_dbl_Type p( sizePhase+sizePressure , 0. );
795
796// for (int i=0; i<sizePhase+sizePressure; i++){
797// for (int j=0; j<sizePhase+sizePressure; j++)
798// mat[i][j] = 0.;
799// }
800// // element assembly
801// if(tpmType == "Biot"){
802// if(dim==2)
803// this->SKR_Biot( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
804// else if (dim==3)
805// this->SKR_Biot3D( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
806// }
807// else if(tpmType == "Biot-StVK")
808// this->SKR_Biot_StVK( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
809
810// if (updateHistory)
811// ed_[T]->setHp( ed.ht );
812
813// if (update) {
814
815// // A00 & A01
816// for (UN i=0; i < sizePhase; i++) {
817// Teuchos::Array<SC> value00( sizePhase, 0. );
818// Teuchos::Array<GO> indices00( sizePhase, 0 );
819// for (UN j=0; j < value00.size(); j++) {
820
821// value00[j] = mat[i][j];
822
823// LO tmpJ = j/dim;
824// LO index = elements1->getElement(T).getNode(tmpJ);
825// if (j%dim==0)
826// indices00[j] = dim * mapRepeated1->getGlobalElement( index );
827// else if (j%dim==1)
828// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
829// else if (j%dim==2)
830// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
831// }
832
833// Teuchos::Array<SC> value01( sizePressure, 0. );
834// Teuchos::Array<GO> indices01( sizePressure, 0 );
835
836// for (UN j=0; j < value01.size(); j++) {
837// value01[j] = mat[i][sizePhase+j];
838// LO index = elements2->getElement(T).getNode(j);
839// indices01[j] = mapRepeated2->getGlobalElement( index );
840// }
841
842// GO row;
843// LO tmpI = i/dim;
844// LO index = elements1->getElement(T).getNode(tmpI);
845// if (i%dim==0)
846// row = dim * mapRepeated1->getGlobalElement( index );
847// else if (i%dim==1)
848// row = dim * mapRepeated1->getGlobalElement( index ) + 1;
849// else if (i%dim==2)
850// row = dim * mapRepeated1->getGlobalElement( index ) + 2;
851
852// A00->insertGlobalValues( row, indices00(), value00() );
853// A01->insertGlobalValues( row, indices01(), value01() );
854
855// if (i%dim==0)
856// fValues0[ dim*index ] += p[ i ];
857// else if (i%dim==1)
858// fValues0[ dim*index+1 ] += p[ i ];
859// else if (i%dim==2)
860// fValues0[ dim*index+2 ] += p[ i ];
861// }
862// // A10 & A11
863// for (UN i=0; i < sizePressure; i++) {
864// Teuchos::Array<SC> value10( sizePhase , 0. );
865// Teuchos::Array<GO> indices10( sizePhase , 0 );
866// for (UN j=0; j < value10.size(); j++) {
867// value10[j] = mat[sizePhase+i][j];
868
869// LO tmpJ = j/dim;
870// LO index = elements1->getElement(T).getNode(tmpJ);
871// if (j%dim==0)
872// indices10[j] = dim * mapRepeated1->getGlobalElement( index );
873// else if (j%dim==1)
874// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
875// else if (j%dim==2)
876// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
877// }
878
879// Teuchos::Array<SC> value11( sizePressure, 0. );
880// Teuchos::Array<GO> indices11( sizePressure, 0 );
881// for (UN j=0; j < value11.size(); j++) {
882// value11[j] = mat[sizePhase+i][sizePhase+j];
883
884// LO index = elements2->getElement(T).getNode(j);
885// indices11[j] = mapRepeated2->getGlobalElement( index );
886// }
887
888
889// LO index2 = elements2->getElement(T).getNode(i);
890// GO row = mapRepeated2->getGlobalElement( index2 );
891// A10->insertGlobalValues( row, indices10(), value10() );
892// A11->insertGlobalValues( row, indices11(), value11() );
893
894// fValues1[ index2 ] += p[ sizePhase + i ];
895// }
896// }
897// }
898
899// for (int i=0; i<sizePhase+sizePressure; i++)
900// delete [] mat[i];
901// delete [] mat;
902
903// delete [] v;
904
905// for (int i=0; i<elementSizePhase+sizePressure; i++)
906// delete nd[i];
907
908// delete [] nd;
909
910
911// A00->fillComplete( A00->getMap("row"), A00->getMap("row") );
912// A01->fillComplete( A10->getMap("row"), A00->getMap("row") );
913// A10->fillComplete( A00->getMap("row"), A10->getMap("row") );
914// A11->fillComplete( A10->getMap("row"), A10->getMap("row") );
915
916// }
917
918template <class SC, class LO, class GO, class NO>
919void FE<SC,LO,GO,NO>::assemblyMass(int dim,
920 std::string FEType,
921 std::string fieldType,
922 MatrixPtr_Type &A,
923 bool callFillComplete){
924
925 TEUCHOS_TEST_FOR_EXCEPTION( FEType == "P0", std::logic_error, "Not implemented for P0" );
926 UN FEloc = this->checkFE(dim,FEType);
927 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
928
929 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
930
931 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
932
933 vec2D_dbl_ptr_Type phi;
934 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
935
936 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
937 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
938
939 Helper::getPhi( phi, weights, dim, FEType, deg );
940
941 SC detB;
942 SC absDetB;
943 SmallMatrix<SC> B(dim);
944 GO glob_i, glob_j;
945 vec_dbl_Type v_i(dim);
946 vec_dbl_Type v_j(dim);
947
948 for (UN T=0; T<elements->numberElements(); T++) {
949
950 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
951 detB = B.computeDet( );
952 absDetB = std::fabs(detB);
953
954 for (UN i=0; i < phi->at(0).size(); i++) {
955 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
956 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
957 for (UN j=0; j < value.size(); j++) {
958 for (UN w=0; w<phi->size(); w++) {
959 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
960
961 }
962 value[j] *= absDetB;
963 if (!fieldType.compare("Scalar")) {
964 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
965 }
966
967 }
968 if (!fieldType.compare("Scalar")) {
969 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
970 A->insertGlobalValues( row, indices(), value() );
971 }
972 else if (!fieldType.compare("Vector")) {
973 for (UN d=0; d<dim; d++) {
974 for (int j=0; j<indices.size(); j++) {
975 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
976 }
977 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
978 A->insertGlobalValues( row, indices(), value() );
979 }
980 }
981 else
982 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
983 }
984
985 }
986
987 if (callFillComplete)
988 A->fillComplete();
989}
990
991
992// Ueberladung der Assemblierung der Massematrix fuer FSI, da
993// this->checkFE sonst auch fuer das Strukturproblem FEloc = 1 liefert (= Fluid)
994// und somit die welche domain und Map in der Assemblierung genutzt wird.
995template <class SC, class LO, class GO, class NO>
996void FE<SC,LO,GO,NO>::assemblyMass(int dim,
997 std::string FEType,
998 std::string fieldType,
999 MatrixPtr_Type &A,
1000 int FEloc, // 0 = Fluid, 2 = Struktur
1001 bool callFillComplete){
1002
1003 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1004
1005 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
1006
1007 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1008
1009 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1010
1011 vec2D_dbl_ptr_Type phi;
1012 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1013
1014 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
1015 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
1016
1017 Helper::getPhi( phi, weights, dim, FEType, deg );
1018
1019 SC detB;
1020 SC absDetB;
1021 SmallMatrix<SC> B(dim);
1022 GO glob_i, glob_j;
1023 vec_dbl_Type v_i(dim);
1024 vec_dbl_Type v_j(dim);
1025
1026 for (UN T=0; T<elements->numberElements(); T++) {
1027
1028 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
1029 detB = B.computeDet( );
1030 absDetB = std::fabs(detB);
1031
1032 for (UN i=0; i < phi->at(0).size(); i++) {
1033 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1034 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1035 for (UN j=0; j < value.size(); j++) {
1036 for (UN w=0; w<phi->size(); w++) {
1037 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
1038 }
1039 value[j] *= absDetB;
1040 if (!fieldType.compare("Scalar")) {
1041 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
1042 }
1043
1044 }
1045 if (!fieldType.compare("Scalar")) {
1046 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
1047 A->insertGlobalValues( row, indices(), value() );
1048 }
1049 else if (!fieldType.compare("Vector")) {
1050 for (UN d=0; d<dim; d++) {
1051 for (int j=0; j<indices.size(); j++) {
1052 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
1053 }
1054 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
1055 A->insertGlobalValues( row, indices(), value() );
1056 }
1057 }
1058 else
1059 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
1060 }
1061
1062
1063 }
1064 if (callFillComplete)
1065 A->fillComplete();
1066}
1067
1068
1069template <class SC, class LO, class GO, class NO>
1070void FE<SC,LO,GO,NO>::assemblyLaplace(int dim,
1071 std::string FEType,
1072 int degree,
1073 MatrixPtr_Type &A,
1074 bool callFillComplete,
1075 int FELocExternal){
1076 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1077 UN FEloc;
1078 if (FELocExternal<0)
1079 FEloc = this->checkFE(dim,FEType);
1080 else
1081 FEloc = FELocExternal;
1082
1083 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
1084
1085 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1086
1087 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1088
1089 vec3D_dbl_ptr_Type dPhi;
1090 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1091
1092 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
1093 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1094
1095 SC detB;
1096 SC absDetB;
1097 SmallMatrix<SC> B(dim);
1098 SmallMatrix<SC> Binv(dim);
1099 GO glob_i, glob_j;
1100 vec_dbl_Type v_i(dim);
1101 vec_dbl_Type v_j(dim);
1102
1103 for (UN T=0; T<elements->numberElements(); T++) {
1104
1105 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1106 detB = B.computeInverse(Binv);
1107 absDetB = std::fabs(detB);
1108
1109 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1110 applyBTinv( dPhi, dPhiTrans, Binv );
1111 for (UN i=0; i < dPhiTrans[0].size(); i++) {
1112 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
1113 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
1114 for (UN j=0; j < value.size(); j++) {
1115 for (UN w=0; w<dPhiTrans.size(); w++) {
1116 for (UN d=0; d<dim; d++){
1117 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
1118 }
1119 }
1120 value[j] *= absDetB;
1121 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
1122 }
1123 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
1124
1125 A->insertGlobalValues( row, indices(), value() );
1126 }
1127
1128
1129 }
1130 if (callFillComplete)
1131 A->fillComplete();
1132
1133}
1134
1135template <class SC, class LO, class GO, class NO>
1136void FE<SC,LO,GO,NO>::assemblyLaplaceVecField(int dim,
1137 std::string FEType,
1138 int degree,
1139 MatrixPtr_Type &A,
1140 bool callFillComplete){
1141
1142 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P1-disc" || FEType == "P0",std::logic_error, "Not implemented for P0 or P1-disc");
1143 UN FEloc = this->checkFE(dim,FEType);
1144
1145 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
1146
1147 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1148
1149 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1150
1151 vec3D_dbl_ptr_Type dPhi;
1152 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1153
1154 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
1155
1156 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1157
1158 SC detB;
1159 SC absDetB;
1160 SmallMatrix<SC> B(dim);
1161 SmallMatrix<SC> Binv(dim);
1162 GO glob_i, glob_j;
1163 vec_dbl_Type v_i(dim);
1164 vec_dbl_Type v_j(dim);
1165
1166
1167 for (UN T=0; T<elements->numberElements(); T++) {
1168
1169 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1170 detB = B.computeInverse(Binv);
1171 absDetB = std::fabs(detB);
1172
1173 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1174 applyBTinv( dPhi, dPhiTrans, Binv );
1175
1176 for (UN i=0; i < dPhiTrans[0].size(); i++) {
1177 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
1178 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
1179 for (UN j=0; j < value.size(); j++) {
1180 for (UN w=0; w<dPhiTrans.size(); w++) {
1181 for (UN d=0; d<dim; d++)
1182 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
1183 }
1184 value[j] *= absDetB;
1185 if (this->setZeros_ && std::fabs(value[j]) < this->myeps_) {
1186 value[j] = 0.;
1187 }
1188 }
1189 for (UN d=0; d<dim; d++) {
1190 for (UN j=0; j < indices.size(); j++)
1191 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
1192
1193 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
1194 A->insertGlobalValues( row, indices(), value() );
1195 }
1196 }
1197 }
1198 if (callFillComplete)
1199 A->fillComplete();
1200}
1201//this assembly used blas matrix-matrix multiplications. It determines the local stiffness matrix at once, but has some overhead due to zero off-diagonal blocks which are computed.
1202template <class SC, class LO, class GO, class NO>
1203void FE<SC,LO,GO,NO>::assemblyLaplaceVecFieldV2(int dim,
1204 std::string FEType,
1205 int degree,
1206 MatrixPtr_Type &A,
1207 bool callFillComplete){
1208
1209 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1210 UN FEloc = this->checkFE(dim,FEType);
1211
1212 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
1213
1214 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1215
1216 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1217
1218 vec3D_dbl_ptr_Type dPhi;
1219 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1220
1221 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
1222
1223 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1224
1225 Teuchos::BLAS<int, SC> teuchosBLAS;
1226
1227 int nmbQuadPoints = dPhi->size();
1228 int nmbScalarDPhi = dPhi->at(0).size();
1229 int nmbAllDPhi = nmbScalarDPhi * dim;
1230 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
1231 int sizeLocStiff = dim*dim;
1232 Teuchos::Array<SmallMatrix<double> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<double>(dim) );
1233 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
1234
1235
1236 SC detB;
1237 SC absDetB;
1238 SmallMatrix<SC> B(dim);
1239 SmallMatrix<SC> Binv(dim);
1240 GO glob_i, glob_j;
1241 vec_dbl_Type v_i(dim);
1242 vec_dbl_Type v_j(dim);
1243
1244 for (UN T=0; T<elements->numberElements(); T++) {
1245
1246 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
1247 detB = B.computeInverse(Binv);
1248 absDetB = std::fabs(detB);
1249
1250 Teuchos::Array<SmallMatrix<double> > allDPhiMatTrans( dPhiMat.size(), SmallMatrix<double>() );
1251
1252 for (int i=0; i<allDPhiMatTrans.size(); i++) {
1253 SmallMatrix<double> res = dPhiMat[i] * Binv;
1254 allDPhiMatTrans[i] = res;
1255 }
1256
1257 SmallMatrix<double> locStiffMat( nmbAllDPhi, 0. );
1258
1259 for (int p=0; p<nmbQuadPoints; p++){
1260
1261 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
1262
1263 int offset = p * nmbAllDPhi;
1264 int offsetInArray = 0;
1265 for (int i=0; i<nmbAllDPhi; i++) {
1266 fillMatrixArray( allDPhiMatTrans[ offset + i ], allDPhiBlas, "rows",offsetInArray );
1267 offsetInArray += sizeLocStiff;
1268 }
1269
1270 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
1271
1272 teuchosBLAS.GEMM (Teuchos::TRANS, Teuchos::NO_TRANS, nmbAllDPhi, nmbAllDPhi, sizeLocStiff, 1., allDPhiBlas, sizeLocStiff/*lda of A not trans(A)! Otherwise result is wrong*/, allDPhiBlas, sizeLocStiff, 0., locStiffMatBlas, nmbAllDPhi);
1273
1274 for (int i=0; i<nmbAllDPhi; i++) {
1275 for (int j=0; j<nmbAllDPhi; j++) {
1276 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
1277 }
1278 }
1279
1280 delete [] allDPhiBlas;
1281 delete [] locStiffMatBlas;
1282
1283 }
1284
1285 for (UN i=0; i < nmbScalarDPhi; i++) {
1286 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
1287 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
1288 for (UN d=0; d<dim; d++) {
1289 for (UN j=0; j < nmbScalarDPhi; j++){
1290 value[ j * dim + d ] = absDetB * locStiffMat[dim * i + d][j];
1291 indices[ j * dim + d ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
1292 }
1293 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
1294 A->insertGlobalValues( row, indices(), value() );
1295 }
1296 }
1297 }
1298 if (callFillComplete)
1299 A->fillComplete();
1300}
1301
1302
1303
1304template <class SC, class LO, class GO, class NO>
1305void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAndStressAceFEM(int dim,
1306 std::string FEType,
1307 MatrixPtr_Type &A,
1308 MultiVectorPtr_Type &f,
1309 MultiVectorPtr_Type u,
1310 ParameterListPtr_Type pList,
1311 double C,
1312 bool callFillComplete){
1313 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::runtime_error, "Not implemented for P0");
1314 UN FEloc = this->checkFE(dim,FEType);
1315
1316
1317 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
1318 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1319
1320 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1321 vec3D_dbl_ptr_Type dPhi;
1322 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1323
1324 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
1325
1326 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1327
1328 SC detB;
1329 SC absDetB;
1330 SmallMatrix<SC> B(dim);
1331 SmallMatrix<SC> Binv(dim);
1332
1333 Teuchos::BLAS<int,SC> teuchosBLAS;
1334
1335 int nmbQuadPoints = dPhi->size();
1336 int nmbScalarDPhi = dPhi->at(0).size();
1337 int nmbAllDPhi = nmbScalarDPhi * dim;
1338 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
1339 int sizeLocStiff = dim*dim;
1340 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
1341
1342 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
1343
1344 std::string material_model = pList->sublist("Parameter").get("Material model","Neo-Hooke");
1345
1346 double poissonRatio = pList->sublist("Parameter").get("Poisson Ratio",0.4);
1347 double mue = pList->sublist("Parameter").get("Mu",2.0e+6);
1348 double mue1 = pList->sublist("Parameter").get("Mu1",2.0e+6);
1349 double mue2 = pList->sublist("Parameter").get("Mu2",2.0e+6);
1350 // Berechne daraus nun E (Youngsches Modul) und die erste Lamé-Konstante \lambda
1351 double E = pList->sublist("Parameter").get("E",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
1352 double E1 = pList->sublist("Parameter").get("E1",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
1353 double E2 = pList->sublist("Parameter").get("E2",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
1354
1355 if (material_model=="Saint Venant-Kirchhoff") {
1356 E = mue*2.*(1. + poissonRatio);
1357 E1 = mue1*2.*(1. + poissonRatio);
1358 E2 = mue2*2.*(1. + poissonRatio);
1359 }
1360
1361 // For StVK (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
1362 double lambda = (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
1363 double lambda1 = (poissonRatio*E1)/((1 + poissonRatio)*(1 - 2*poissonRatio));
1364 double lambda2 = (poissonRatio*E2)/((1 + poissonRatio)*(1 - 2*poissonRatio));
1365
1366 if (dim == 2){
1367 double* v;
1368 if(!material_model.compare("Saint Venant-Kirchhoff"))
1369 v = new double[154];
1370 else
1371 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Saint Venant-Kirchhoff in 2D.");
1372
1373 double** Pmat = new double*[2];
1374 for (int i=0; i<2; i++)
1375 Pmat[i] = new double[2];
1376
1377 double** F = new double*[2];
1378 for (int i=0; i<2; i++)
1379 F[i] = new double[2];
1380
1381 double**** Amat = new double***[2];
1382 for (int i=0; i<2; i++){
1383 Amat[i] = new double**[2];
1384 for (int j=0; j<2; j++) {
1385 Amat[i][j] = new double*[2];
1386 for (int k=0; k<2; k++)
1387 Amat[i][j][k] = new double[2];
1388 }
1389 }
1390
1391 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1392
1393 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
1394
1395 Teuchos::Array<int> indices(2);
1396 for (int T=0; T<elements->numberElements(); T++) {
1397
1398 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
1399 detB = B.computeInverse(Binv);
1400 absDetB = std::fabs(detB);
1401
1402 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
1403
1404 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
1405 SmallMatrix<SC> res = dPhiMat[i] * Binv;
1406 all_dPhiMat_Binv[i] = res;
1407 }
1408
1409 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
1410 std::vector<SC> locStresses( nmbAllDPhi, 0. );
1411 int elementFlag = 0;
1412 for (int p=0; p<nmbQuadPoints; p++){
1413
1414 SmallMatrix<SC> Fmat( dim, 0. );
1415 SmallMatrix<SC> tmpForScaling( dim, 0. );
1416 Fmat[0][0] = 1.; Fmat[1][1] = 1.;
1417
1418 for (int i=0; i<nmbScalarDPhi; i++) {
1419 indices.at(0) = dim * elements->getElement(T).getNode(i);
1420 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
1421
1422 for (int j=0; j<dim; j++) {
1423 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
1424 SC v = uArray[indices.at(j)];
1425 tmpForScaling.scale( v );
1426 Fmat += tmpForScaling;
1427 }
1428 }
1429
1430 for (int i=0; i<Fmat.size(); i++) {
1431 for (int j=0; j<Fmat.size(); j++) {
1432 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
1433 }
1434 }
1435
1436 elementFlag = elements->getElement(T).getFlag();
1437 if (elementFlag == 1){
1438 lambda = lambda1;
1439 mue = mue1;
1440 E = E1;
1441 }
1442 else if (elementFlag == 2){
1443 lambda = lambda2;
1444 mue = mue2;
1445 E = E2;
1446 }
1447
1448 if ( !material_model.compare("Saint Venant-Kirchhoff") )
1449 stvk2d(v, &lambda, &mue, F, Pmat, Amat);
1450
1451 SmallMatrix<SC> Aloc(dim*dim);
1452 for (int i=0; i<2; i++) {
1453 for (int j=0; j<2; j++) {
1454 for (int k=0; k<2; k++) {
1455 for (int l=0; l<2; l++) {
1456 Aloc[ 2 * i + j ][ 2 * k + l ] = Amat[i][j][k][l];
1457 }
1458 }
1459 }
1460 }
1461
1462 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
1463 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
1464
1465 //jacobian
1466 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
1467 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
1468 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
1469
1470 int offset = p * nmbAllDPhi;
1471 int offsetInArray = 0;
1472 for (int i=0; i<nmbAllDPhi; i++) {
1473 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
1474 offsetInArray += sizeLocStiff;
1475 }
1476
1477 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
1478
1479
1480 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
1481
1482 teuchosBLAS.GEMM (Teuchos::TRANS, Teuchos::NO_TRANS, nmbAllDPhi, nmbAllDPhi, sizeLocStiff, 1., allDPhiBlas, sizeLocStiff/*lda of A not trans(A)! Otherwise result is wrong*/, resTmp, sizeLocStiff, 0., locStiffMatBlas, nmbAllDPhi);
1483
1484 for (int i=0; i<nmbAllDPhi; i++) {
1485 for (int j=0; j<nmbAllDPhi; j++)
1486 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
1487 }
1488
1489 delete [] resTmp;
1490 delete [] locStiffMatBlas;
1491
1492
1493 //stress
1494 double* fArray = new double[ sizeLocStiff ];
1495 for (int i=0; i<dim; i++) {
1496 for (int j=0; j<dim; j++) {
1497 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
1498 }
1499 }
1500
1501 double* res = new double[ nmbAllDPhi ];
1502 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
1503 for (int i=0; i<locStresses.size(); i++) {
1504 locStresses[i] += weights->at(p) * res[i];
1505 }
1506
1507 delete [] res;
1508 delete [] aceFEMFunc;
1509 delete [] allDPhiBlas;
1510 delete [] fArray;
1511 }
1512
1513 for (int i=0; i<nmbScalarDPhi; i++) {
1514 for (int d1=0; d1<dim; d1++) {
1515
1516 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
1517 SC v = absDetB * locStresses[ dim * i + d1 ];
1518 fValues[rowLO] += v;
1519
1520 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
1521 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
1522 LO counter = 0;
1523 for (UN j=0; j < nmbScalarDPhi; j++){
1524 for (UN d2=0; d2<dim; d2++) {
1525 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
1526 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
1527 counter++;
1528 }
1529 }
1530 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
1531 A->insertGlobalValues( row, indices(), value() );
1532 }
1533 }
1534 }
1535
1536 delete [] v;
1537 for (int i=0; i<2; i++)
1538 delete [] Pmat[i];
1539 delete [] Pmat;
1540 for (int i=0; i<2; i++)
1541 delete [] F[i];
1542 delete [] F;
1543
1544 for (int i=0; i<2; i++){
1545 for (int j=0; j<2; j++) {
1546 for (int k=0; k<2; k++)
1547 delete [] Amat[i][j][k];
1548 delete [] Amat[i][j];
1549 }
1550 delete [] Amat[i];
1551 }
1552 delete [] Amat;
1553
1554
1555 }
1556 else if (dim == 3) {
1557 double* v;
1558 if (!material_model.compare("Neo-Hooke"))
1559 v = new double[466];
1560 else if(!material_model.compare("Mooney-Rivlin"))
1561 v = new double[476];
1562 else if(!material_model.compare("Saint Venant-Kirchhoff"))
1563 v = new double[279];
1564 else{
1565 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke, Mooney-Rivlin and Saint Venant-Kirchhoff.");
1566 }
1567
1568 double** Pmat = new double*[3];
1569 for (int i=0; i<3; i++)
1570 Pmat[i] = new double[3];
1571
1572 double** F = new double*[3];
1573 for (int i=0; i<3; i++)
1574 F[i] = new double[3];
1575
1576 double**** Amat = new double***[3];
1577 for (int i=0; i<3; i++){
1578 Amat[i] = new double**[3];
1579 for (int j=0; j<3; j++) {
1580 Amat[i][j] = new double*[3];
1581 for (int k=0; k<3; k++)
1582 Amat[i][j][k] = new double[3];
1583 }
1584 }
1585
1586 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1587
1588 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
1589
1590 Teuchos::Array<int> indices(3);
1591 for (int T=0; T<elements->numberElements(); T++) {
1592
1593 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
1594 detB = B.computeInverse(Binv);
1595 absDetB = std::fabs(detB);
1596
1597 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
1598
1599 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
1600 SmallMatrix<SC> res = dPhiMat[i] * Binv;
1601 all_dPhiMat_Binv[i] = res;
1602 }
1603
1604 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
1605 std::vector<SC> locStresses( nmbAllDPhi, 0. );
1606 int elementFlag = 0;
1607 for (int p=0; p<nmbQuadPoints; p++){
1608
1609 SmallMatrix<SC> Fmat( dim, 0. );
1610 SmallMatrix<SC> tmpForScaling( dim, 0. );
1611 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
1612
1613 for (int i=0; i<nmbScalarDPhi; i++) {
1614 indices.at(0) = dim * elements->getElement(T).getNode(i);
1615 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
1616 indices.at(2) = dim * elements->getElement(T).getNode(i) + 2;
1617
1618 for (int j=0; j<dim; j++) {
1619 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
1620 SC v = uArray[indices.at(j)];
1621 tmpForScaling.scale( v );
1622 Fmat += tmpForScaling;
1623 }
1624 }
1625
1626 for (int i=0; i<Fmat.size(); i++) {
1627 for (int j=0; j<Fmat.size(); j++) {
1628 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
1629 }
1630 }
1631
1632 elementFlag = elements->getElement(T).getFlag();
1633 if (elementFlag == 1){
1634 lambda = lambda1;
1635 mue = mue1;
1636 E = E1;
1637 }
1638 else if (elementFlag == 2){
1639 lambda = lambda2;
1640 mue = mue2;
1641 E = E2;
1642 }
1643
1644 if ( !material_model.compare("Neo-Hooke") )
1645 nh3d(v, &E, &poissonRatio, F, Pmat, Amat);
1646 else if ( !material_model.compare("Mooney-Rivlin") )
1647 mr3d(v, &E, &poissonRatio, &C, F, Pmat, Amat);
1648 else if ( !material_model.compare("Saint Venant-Kirchhoff") )
1649 stvk3d(v, &lambda, &mue, F, Pmat, Amat);
1650
1651 SmallMatrix<SC> Aloc(dim*dim);
1652 for (int i=0; i<3; i++) {
1653 for (int j=0; j<3; j++) {
1654 for (int k=0; k<3; k++) {
1655 for (int l=0; l<3; l++) {
1656 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
1657 }
1658 }
1659 }
1660 }
1661
1662 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
1663 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
1664
1665 //jacobian
1666 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
1667 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
1668 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
1669
1670 int offset = p * nmbAllDPhi;
1671 int offsetInArray = 0;
1672 for (int i=0; i<nmbAllDPhi; i++) {
1673 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
1674 offsetInArray += sizeLocStiff;
1675 }
1676
1677 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
1678
1679
1680 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
1681
1682 teuchosBLAS.GEMM (Teuchos::TRANS, Teuchos::NO_TRANS, nmbAllDPhi, nmbAllDPhi, sizeLocStiff, 1., allDPhiBlas, sizeLocStiff/*lda of A not trans(A)! Otherwise result is wrong*/, resTmp, sizeLocStiff, 0., locStiffMatBlas, nmbAllDPhi);
1683
1684 for (int i=0; i<nmbAllDPhi; i++) {
1685 for (int j=0; j<nmbAllDPhi; j++)
1686 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
1687 }
1688
1689 delete [] resTmp;
1690 delete [] locStiffMatBlas;
1691
1692
1693 //stress
1694 double* fArray = new double[ sizeLocStiff ];
1695 for (int i=0; i<dim; i++) {
1696 for (int j=0; j<dim; j++) {
1697 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
1698 }
1699 }
1700
1701 double* res = new double[ nmbAllDPhi ];
1702 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
1703 for (int i=0; i<locStresses.size(); i++) {
1704 locStresses[i] += weights->at(p) * res[i];
1705 }
1706
1707 delete [] res;
1708 delete [] aceFEMFunc;
1709 delete [] allDPhiBlas;
1710 delete [] fArray;
1711 }
1712
1713 for (int i=0; i<nmbScalarDPhi; i++) {
1714 for (int d1=0; d1<dim; d1++) {
1715
1716 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
1717 SC v = absDetB * locStresses[ dim * i + d1 ];
1718 fValues[rowLO] += v;
1719
1720 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
1721 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
1722 LO counter = 0;
1723 for (UN j=0; j < nmbScalarDPhi; j++){
1724 for (UN d2=0; d2<dim; d2++) {
1725 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
1726 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
1727
1728 counter++;
1729 }
1730 }
1731 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
1732 A->insertGlobalValues( row, indices(), value() );
1733 }
1734 }
1735 }
1736
1737 delete [] v;
1738 for (int i=0; i<3; i++)
1739 delete [] Pmat[i];
1740 delete [] Pmat;
1741 for (int i=0; i<3; i++)
1742 delete [] F[i];
1743 delete [] F;
1744
1745 for (int i=0; i<3; i++){
1746 for (int j=0; j<3; j++) {
1747 for (int k=0; k<3; k++)
1748 delete [] Amat[i][j][k];
1749 delete [] Amat[i][j];
1750 }
1751 delete [] Amat[i];
1752 }
1753 delete [] Amat;
1754
1755 }
1756 if (callFillComplete)
1757 A->fillComplete();
1758
1759}
1760
1761
1762template <class SC, class LO, class GO, class NO>
1763void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAceFEM(int dim,
1764 std::string FEType,
1765 MatrixPtr_Type &A,
1766 MultiVectorPtr_Type u,
1767 std::string material_model,
1768 double E,
1769 double nu,
1770 double C,
1771 bool callFillComplete){
1772 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1773 UN FEloc = this->checkFE(dim,FEType);
1774
1775 vec2D_int_ptr_Type elements = this->domainVec_.at(FEloc)->getElements();
1776
1777 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1778
1779 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1780 vec3D_dbl_ptr_Type dPhi;
1781 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1782
1783 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
1784
1785 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1786
1787 SC detB;
1788 SC absDetB;
1789 SmallMatrix<SC> B(dim);
1790 SmallMatrix<SC> Binv(dim);
1791
1792 Teuchos::BLAS<int, SC> teuchosBLAS;
1793
1794 int nmbQuadPoints = dPhi->size();
1795 int nmbScalarDPhi = dPhi->at(0).size();
1796 int nmbAllDPhi = nmbScalarDPhi * dim;
1797 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
1798 int sizeLocStiff = dim*dim;
1799 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
1800
1801 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
1802
1803 if (dim == 2){
1804 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
1805 }
1806 else if (dim == 3) {
1807
1808 double* v;
1809 if (!material_model.compare("Neo-Hooke"))
1810 v = new double[466];
1811 else if(!material_model.compare("Mooney-Rivlin"))
1812 v = new double[476];
1813 else{
1814 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
1815 }
1816
1817
1818 double** Pmat = new double*[3];
1819 for (int i=0; i<3; i++)
1820 Pmat[i] = new double[3];
1821
1822 double** F = new double*[3];
1823 for (int i=0; i<3; i++)
1824 F[i] = new double[3];
1825
1826 double**** Amat = new double***[3];
1827 for (int i=0; i<3; i++){
1828 Amat[i] = new double**[3];
1829 for (int j=0; j<3; j++) {
1830 Amat[i][j] = new double*[3];
1831 for (int k=0; k<3; k++)
1832 Amat[i][j][k] = new double[3];
1833 }
1834 }
1835
1836 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1837
1838 Teuchos::Array<int> indices(3);
1839 for (int T=0; T<elements->size(); T++) {
1840
1841 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
1842 detB = B.computeInverse(Binv);
1843 absDetB = std::fabs(detB);
1844
1845 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
1846
1847 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
1848 SmallMatrix<SC> res = dPhiMat[i] * Binv;
1849 all_dPhiMat_Binv[i] = res;
1850 }
1851
1852 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
1853
1854 for (int p=0; p<nmbQuadPoints; p++){
1855
1856 SmallMatrix<SC> Fmat( dim, 0. );
1857 SmallMatrix<SC> tmpForScaling( dim, 0. );
1858 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
1859
1860 for (int i=0; i<nmbScalarDPhi; i++) {
1861 indices.at(0) = dim * elements->at(T).at(i);
1862 indices.at(1) = dim * elements->at(T).at(i) + 1;
1863 indices.at(2) = dim * elements->at(T).at(i) + 2;
1864
1865 for (int j=0; j<dim; j++) {
1866 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
1867 SC v = uArray[indices.at(j)];
1868 tmpForScaling.scale( v );
1869 Fmat += tmpForScaling;
1870 }
1871 }
1872
1873 for (int i=0; i<Fmat.size(); i++) {
1874 for (int j=0; j<Fmat.size(); j++) {
1875 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
1876 }
1877 }
1878 if ( !material_model.compare("Neo-Hooke") )
1879 nh3d(v, &E, &nu, F, Pmat, Amat);
1880 else if ( !material_model.compare("Mooney-Rivlin") )
1881 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
1882
1883 SmallMatrix<SC> Aloc(dim*dim);
1884 for (int i=0; i<3; i++) {
1885 for (int j=0; j<3; j++) {
1886 for (int k=0; k<3; k++) {
1887 for (int l=0; l<3; l++) {
1888 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
1889 }
1890 }
1891 }
1892 }
1893
1894 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
1895 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
1896 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
1897 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
1898 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
1899
1900 int offset = p * nmbAllDPhi;
1901 int offsetInArray = 0;
1902 for (int i=0; i<nmbAllDPhi; i++) {
1903 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
1904 offsetInArray += sizeLocStiff;
1905 }
1906
1907 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
1908
1909 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
1910
1911 teuchosBLAS.GEMM (Teuchos::TRANS, Teuchos::NO_TRANS, nmbAllDPhi, nmbAllDPhi, sizeLocStiff, 1., allDPhiBlas, sizeLocStiff/*lda of A not trans(A)! Otherwise result is wrong*/, resTmp, sizeLocStiff, 0., locStiffMatBlas, nmbAllDPhi);
1912
1913 for (int i=0; i<nmbAllDPhi; i++) {
1914 for (int j=0; j<nmbAllDPhi; j++)
1915 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
1916 }
1917
1918 delete [] aceFEMFunc;
1919 delete [] allDPhiBlas;
1920 delete [] resTmp;
1921 delete [] locStiffMatBlas;
1922
1923 }
1924 for (int i=0; i<nmbScalarDPhi; i++) {
1925 for (int d1=0; d1<dim; d1++) {
1926 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
1927 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
1928 LO counter = 0;
1929 for (UN j=0; j < nmbScalarDPhi; j++){
1930 for (UN d2=0; d2<dim; d2++) {
1931 indices[counter] = GO ( dim * map->getGlobalElement( elements->at(T).at(j) ) + d2 );
1932 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
1933 counter++;
1934 }
1935 }
1936 GO row = GO ( dim * map->getGlobalElement( elements->at(T).at(i) ) + d1 );
1937 A->insertGlobalValues( row, indices(), value() );
1938 }
1939 }
1940 }
1941
1942 delete [] v;
1943 for (int i=0; i<3; i++)
1944 delete [] Pmat[i];
1945 delete [] Pmat;
1946 for (int i=0; i<3; i++)
1947 delete [] F[i];
1948 delete [] F;
1949
1950 for (int i=0; i<3; i++){
1951 for (int j=0; j<3; j++) {
1952 for (int k=0; k<3; k++)
1953 delete [] Amat[i][j][k];
1954 delete [] Amat[i][j];
1955 }
1956 delete [] Amat[i];
1957 }
1958 delete [] Amat;
1959
1960 }
1961 if (callFillComplete)
1962 A->fillComplete();
1963
1964}
1965
1966template <class SC, class LO, class GO, class NO>
1967void FE<SC,LO,GO,NO>::assemblyElasticityStressesAceFEM(int dim,
1968 std::string FEType,
1969 MultiVectorPtr_Type &f,
1970 MultiVectorPtr_Type u,
1971 std::string material_model,
1972 double E,
1973 double nu,
1974 double C,
1975 bool callFillComplete){
1976 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1977 UN FEloc = this->checkFE(dim,FEType);
1978
1979 vec2D_int_ptr_Type elements = this->domainVec_.at(FEloc)->getElements();
1980
1981 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
1982
1983 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
1984
1985 vec3D_dbl_ptr_Type dPhi;
1986 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1987
1988 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
1989
1990 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1991
1992 SC detB;
1993 SC absDetB;
1994 SmallMatrix<SC> B(dim);
1995 SmallMatrix<SC> Binv(dim);
1996
1997 Teuchos::BLAS<int, SC> teuchosBLAS;
1998
1999 int nmbQuadPoints = dPhi->size();
2000 int nmbScalarDPhi = dPhi->at(0).size();
2001 int nmbAllDPhi = nmbScalarDPhi * dim;
2002 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2003 int sizeLocStiff = dim*dim;
2004 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
2005
2006 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2007
2008 if (dim == 2){
2009 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
2010 }
2011 else if (dim == 3) {
2012
2013 double* v;
2014 if (!material_model.compare("Neo-Hooke"))
2015 v = new double[466];
2016 else if(!material_model.compare("Mooney-Rivlin"))
2017 v = new double[476];
2018 else{
2019 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
2020 }
2021
2022
2023 double** Pmat = new double*[3];
2024 for (int i=0; i<3; i++)
2025 Pmat[i] = new double[3];
2026
2027 double** F = new double*[3];
2028 for (int i=0; i<3; i++)
2029 F[i] = new double[3];
2030
2031 double**** Amat = new double***[3];
2032 for (int i=0; i<3; i++){
2033 Amat[i] = new double**[3];
2034 for (int j=0; j<3; j++) {
2035 Amat[i][j] = new double*[3];
2036 for (int k=0; k<3; k++)
2037 Amat[i][j][k] = new double[3];
2038 }
2039 }
2040
2041 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2042
2043 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
2044
2045 Teuchos::Array<int> indices(3);
2046 for (int T=0; T<elements->size(); T++) {
2047
2048 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
2049 detB = B.computeInverse(Binv);
2050 absDetB = std::fabs(detB);
2051
2052 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
2053
2054 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
2055 SmallMatrix<SC> res = dPhiMat[i] * Binv;
2056 all_dPhiMat_Binv[i] = res;
2057 }
2058 std::vector<double> locStresses( nmbAllDPhi, 0. );
2059
2060 for (int p=0; p<nmbQuadPoints; p++){
2061
2062 SmallMatrix<SC> Fmat( dim, 0. );
2063 SmallMatrix<SC> tmpForScaling( dim, 0. );
2064 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
2065
2066 for (int i=0; i<nmbScalarDPhi; i++) {
2067 indices.at(0) = dim * elements->at(T).at(i);
2068 indices.at(1) = dim * elements->at(T).at(i) + 1;
2069 indices.at(2) = dim * elements->at(T).at(i) + 2;
2070
2071 for (int j=0; j<dim; j++) {
2072 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
2073 SC v = uArray[indices.at(j)];
2074 tmpForScaling.scale( v );
2075 Fmat += tmpForScaling;
2076 }
2077 }
2078
2079 for (int i=0; i<Fmat.size(); i++) {
2080 for (int j=0; j<Fmat.size(); j++) {
2081 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
2082 }
2083 }
2084 if ( !material_model.compare("Neo-Hooke") )
2085 nh3d(v, &E, &nu, F, Pmat, Amat);
2086 else if ( !material_model.compare("Mooney-Rivlin") )
2087 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
2088
2089 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
2090 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
2091
2092 int offset = p * nmbAllDPhi;
2093 int offsetInArray = 0;
2094 for (int i=0; i<nmbAllDPhi; i++) {
2095 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
2096 offsetInArray += sizeLocStiff;
2097 }
2098
2099
2100 double* fArray = new double[ sizeLocStiff ];
2101 for (int i=0; i<dim; i++) {
2102 for (int j=0; j<dim; j++) {
2103 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
2104 }
2105 }
2106
2107 double* res = new double[ nmbAllDPhi ];
2108 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
2109 for (int i=0; i<locStresses.size(); i++) {
2110 locStresses[i] += weights->at(p) * res[i];
2111 }
2112
2113 delete [] aceFEMFunc;
2114 delete [] allDPhiBlas;
2115 delete [] fArray;
2116 }
2117
2118
2119
2120 for (int i=0; i<nmbScalarDPhi; i++) {
2121 for (int d1=0; d1<dim; d1++) {
2122 LO row = dim * elements->at(T).at(i) + d1;
2123 SC v = absDetB * locStresses[ dim * i + d1 ];
2124 fValues[row] = v;
2125 }
2126 }
2127 }
2128
2129
2130 delete [] v;
2131 for (int i=0; i<3; i++)
2132 delete [] Pmat[i];
2133 delete [] Pmat;
2134 for (int i=0; i<3; i++)
2135 delete [] F[i];
2136 delete [] F;
2137
2138 for (int i=0; i<3; i++){
2139 for (int j=0; j<3; j++) {
2140 for (int k=0; k<3; k++)
2141 delete [] Amat[i][j][k];
2142 delete [] Amat[i][j];
2143 }
2144 delete [] Amat[i];
2145 }
2146 delete [] Amat;
2147
2148 }
2149}
2150
2152template <class SC, class LO, class GO, class NO>
2154 std::string FEType,
2155 MatrixPtr_Type &A,
2156 MultiVectorPtr_Type u,
2157 bool callFillComplete){
2158
2159 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
2160 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2161
2162 UN FEloc = this->checkFE(dim,FEType);
2163
2164 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
2165
2166 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
2167
2168 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
2169
2170 vec3D_dbl_ptr_Type dPhi;
2171 vec2D_dbl_ptr_Type phi;
2172 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2173
2174 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
2175
2176 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1 ) +
2177 Helper::determineDegree( dim, FEType, Helper::Deriv0) +
2178 extraDeg;
2179
2180 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2181 Helper::getPhi(phi, weights, dim, FEType, deg);
2182 SC detB;
2183 SC absDetB;
2184 SmallMatrix<SC> B(dim);
2185 SmallMatrix<SC> Binv(dim);
2186 GO glob_i, glob_j;
2187 vec_dbl_Type v_i(dim);
2188 vec_dbl_Type v_j(dim);
2189
2190 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
2191 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2192
2193 for (UN T=0; T<elements->numberElements(); T++) {
2194
2195 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2196 detB = B.computeInverse(Binv);
2197 absDetB = std::fabs(detB);
2198
2199 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2200 applyBTinv( dPhi, dPhiTrans, Binv );
2201
2202 for (int w=0; w<phi->size(); w++){ //quads points
2203 for (int d=0; d<dim; d++) {
2204 uLoc[d][w] = 0.;
2205 for (int i=0; i < phi->at(0).size(); i++) {
2206 LO index = dim * elements->getElement(T).getNode(i) + d;
2207 uLoc[d][w] += uArray[index] * phi->at(w).at(i);
2208 }
2209 }
2210 }
2211
2212 for (UN i=0; i < phi->at(0).size(); i++) {
2213 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2214 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2215 for (UN j=0; j < value.size(); j++) {
2216 for (UN w=0; w<dPhiTrans.size(); w++) {
2217 for (UN d=0; d<dim; d++){
2218 value[j] += weights->at(w) * uLoc[d][w] * (*phi)[w][i] * dPhiTrans[w][j][d];
2219 }
2220
2221 }
2222 value[j] *= absDetB;
2223 if (this->setZeros_ && std::fabs(value[j]) < this->myeps_) {
2224 value[j] = 0.;
2225 }
2226
2227 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) );
2228 GO glob_j = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) );
2229 }
2230 for (UN d=0; d<dim; d++) {
2231 for (UN j=0; j < indices.size(); j++)
2232 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2233
2234 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2235 A->insertGlobalValues( row, indices(), value() );
2236 }
2237 }
2238 }
2239
2240
2241 if (callFillComplete)
2242 A->fillComplete();
2243}
2244
2246template <class SC, class LO, class GO, class NO>
2248 std::string FEType,
2249 MatrixPtr_Type &A,
2250 MultiVectorPtr_Type u,
2251 bool callFillComplete){
2252
2253 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
2254 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2255 UN FEloc = this->checkFE(dim,FEType);
2256
2257 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
2258
2259 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
2260
2261 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
2262
2263 vec3D_dbl_ptr_Type dPhi;
2264 vec2D_dbl_ptr_Type phi;
2265 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2266
2267 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); //Elementwise assembly of u
2268
2269 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
2270
2271 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2272 Helper::getPhi(phi, weights, dim, FEType, deg);
2273
2274 SC detB;
2275 SC absDetB;
2276 SmallMatrix<SC> B(dim);
2277 SmallMatrix<SC> Binv(dim);
2278 GO glob_i, glob_j;
2279 vec_dbl_Type v_i(dim);
2280 vec_dbl_Type v_j(dim);
2281
2282 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2283
2284 for (UN T=0; T<elements->numberElements(); T++) {
2285
2286 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2287 detB = B.computeInverse(Binv);
2288 absDetB = std::fabs(detB);
2289
2290 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2291 applyBTinv( dPhi, dPhiTrans, Binv );
2292
2293 std::vector<SmallMatrix<SC> > duLoc( weights->size(), SmallMatrix<SC>(dim) ); //for all quad points p_i each matrix is [u_x * grad Phi(p_i), u_y * grad Phi(p_i), u_z * grad Phi(p_i) (if 3D) ], duLoc[w] = [[phixx;phixy],[phiyx;phiyy]] (2D)
2294
2295 for (int w=0; w<dPhiTrans.size(); w++){ //quads points
2296 for (int d1=0; d1<dim; d1++) {
2297 for (int i=0; i < dPhiTrans[0].size(); i++) {
2298 LO index = dim * elements->getElement(T).getNode(i) + d1;
2299 for (int d2=0; d2<dim; d2++)
2300 duLoc[w][d2][d1] += uArray[index] * dPhiTrans[w][i][d2];
2301 }
2302 }
2303 }
2304
2305 for (UN i=0; i < phi->at(0).size(); i++) {
2306 for (UN d1=0; d1<dim; d1++) {
2307 Teuchos::Array<SC> value( dim*phi->at(0).size(), 0. ); //These are value (W_ix,W_iy,W_iz)
2308 Teuchos::Array<GO> indices( dim*phi->at(0).size(), 0 );
2309 for (UN j=0; j < phi->at(0).size(); j++) {
2310 for (UN d2=0; d2<dim; d2++){
2311 for (UN w=0; w<phi->size(); w++) {
2312 value[ dim * j + d2 ] += weights->at(w) * duLoc[w][d2][d1] * (*phi)[w][i] * (*phi)[w][j];
2313 }
2314 value[ dim * j + d2 ] *= absDetB;
2315
2316 if (this->setZeros_ && std::fabs(value[ dim * j + d2 ]) < this->myeps_) {
2317 value[ dim * j + d2 ] = 0.;
2318 }
2319 }
2320 }
2321 for (UN j=0; j < phi->at(0).size(); j++){
2322 for (UN d2=0; d2<dim; d2++){
2323 indices[ dim * j + d2 ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
2324 }
2325 }
2326
2327 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
2328 A->insertGlobalValues( row, indices(), value() );
2329 }
2330 }
2331 }
2332 if (callFillComplete)
2333 A->fillComplete();
2334}
2335
2337template <class SC, class LO, class GO, class NO>
2339 std::string FEType,
2340 std::string FETypeV,
2341 MatrixPtr_Type &A,
2342 MultiVectorPtr_Type u,
2343 bool callFillComplete){
2344
2345 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
2346 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2347
2348 UN FEloc = this->checkFE(dim,FEType);
2349
2350 ElementsPtr_Type elements = this->domainVec_.at(1)->getElementsC();
2351 ElementsPtr_Type elementsVel = this->domainVec_.at(0)->getElementsC();
2352
2353 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(1)->getPointsRepeated();
2354
2355 MapConstPtr_Type map = this->domainVec_.at(1)->getMapRepeated();
2356
2357 vec3D_dbl_ptr_Type dPhi;
2358 vec2D_dbl_ptr_Type phi,phiV;
2359 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2360
2361 UN degV = Helper::determineDegree( dim, FETypeV, Helper::Deriv0); //Elementwise assembly of u
2362 UN degP = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of p
2363 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) + degV + degP;
2364
2365 Helper::getDPhi(dPhi, weights, dim, FEType, deg); // Dphi for \nabla p
2366 Helper::getPhi(phi, weights, dim, FEType, deg); // phi for u
2367 Helper::getPhi(phiV, weights, dim, FETypeV, deg); // phi for p
2368
2369 SC detB;
2370 SC absDetB;
2371 SmallMatrix<SC> B(dim);
2372 SmallMatrix<SC> Binv(dim);
2373 GO glob_i, glob_j;
2374 vec_dbl_Type v_i(dim);
2375 vec_dbl_Type v_j(dim);
2376
2377 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
2378 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2379
2380 for (UN T=0; T<elements->numberElements(); T++) {
2381
2382 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2383 detB = B.computeInverse(Binv);
2384 absDetB = std::fabs(detB);
2385
2386 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2387 applyBTinv( dPhi, dPhiTrans, Binv );
2388
2389 for (int w=0; w<phiV->size(); w++){ //quads points
2390 for (int d=0; d<dim; d++) {
2391 uLoc[d][w] = 0.;
2392 for (int i=0; i < phiV->at(0).size(); i++) {
2393 LO index = dim * elementsVel->getElement(T).getNode(i) + d;
2394 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
2395 }
2396 }
2397 }
2398
2399 for (UN i=0; i < phi->at(0).size(); i++) {
2400 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2401 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2402 for (UN j=0; j < value.size(); j++) {
2403 for (UN w=0; w<dPhiTrans.size(); w++) {
2404 for (UN d=0; d<dim; d++){
2405 value[j] += weights->at(w) * uLoc[d][w]* dPhiTrans[w][j][d] * (*phi)[w][i] ;
2406 }
2407 }
2408 value[j] *= absDetB;
2409 indices[j] = GO ( map->getGlobalElement( elements->getElement(T).getNode(j) ) );
2410 }
2411
2412 GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
2413 A->insertGlobalValues( row, indices(), value() );
2414
2415 }
2416 }
2417
2418
2419 if (callFillComplete)
2420 A->fillComplete();
2421}
2422
2424template <class SC, class LO, class GO, class NO>
2426 std::string FEType1,
2427 std::string FEType2,
2428 int degree,
2429 MatrixPtr_Type &Bmat,
2430 MatrixPtr_Type &BTmat,
2431 MapConstPtr_Type map1,
2432 MapConstPtr_Type map2,
2433 bool callFillComplete) {
2434
2435
2436 UN FEloc1 = this->checkFE(dim,FEType1);
2437 UN FEloc2 = this->checkFE(dim,FEType2);
2438
2439 ElementsPtr_Type elements1 = this->domainVec_.at(FEloc1)->getElementsC();
2440 ElementsPtr_Type elements2 = this->domainVec_.at(FEloc2)->getElementsC();
2441
2442 vec2D_dbl_ptr_Type pointsRep1 = this->domainVec_.at(FEloc1)->getPointsRepeated();
2443
2444 MapConstPtr_Type mapping1 = this->domainVec_.at(FEloc1)->getMapRepeated();
2445 MapConstPtr_Type mapping2;
2446
2447 if (FEType2 == "P0")
2448 mapping2 = this->domainVec_.at(FEloc2)->getElementMap();
2449 else
2450 mapping2 = this->domainVec_.at(FEloc2)->getMapRepeated();
2451
2452 vec3D_dbl_ptr_Type dPhi;
2453 vec2D_dbl_ptr_Type phi;
2454 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2455
2456 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
2458
2459 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
2460
2461 // if (FEType2=="P1-disc-global")
2462 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
2463 if (FEType2=="P1-disc" && FEType1=="Q2" )
2464 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
2465 else
2466 Helper::getPhi(phi, weights, dim, FEType2, deg);
2467
2468 SC detB;
2469 SC absDetB;
2470 SmallMatrix<SC> B(dim);
2471 SmallMatrix<SC> Binv(dim);
2472 GO glob_i, glob_j;
2473 vec_dbl_Type v_i(dim);
2474 vec_dbl_Type v_j(dim);
2475
2476 for (UN T=0; T<elements1->numberElements(); T++) {
2477
2478 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
2479 detB = B.computeInverse(Binv);
2480 absDetB = std::fabs(detB);
2481
2482 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2483 applyBTinv( dPhi, dPhiTrans, Binv );
2484
2485 for (UN i=0; i < phi->at(0).size(); i++) {
2486 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( dPhiTrans[0].size(), 0. ) );
2487 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2488
2489 for (UN j=0; j < valueVec[0].size(); j++) {
2490 for (UN w=0; w<dPhiTrans.size(); w++) {
2491 for (UN d=0; d<dim; d++)
2492 valueVec[d][j] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
2493 }
2494 for (UN d=0; d<dim; d++){
2495 valueVec[d][j] *= absDetB;
2496 if (this->setZeros_ && std::fabs(valueVec[d][j]) < this->myeps_) {
2497 valueVec[d][j] = 0.;
2498 }
2499 }
2500 }
2501 for (UN d=0; d<dim; d++) {
2502 for (UN j=0; j < indices.size(); j++)
2503 indices[j] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
2504
2505 GO row;
2506 if (FEType2=="P0")
2507 row = GO ( mapping2->getGlobalElement( T ) );
2508 else
2509 row = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
2510 Bmat->insertGlobalValues( row, indices(), valueVec[d]() );
2511 }
2512 }
2513
2514 // We compute value twice, maybe we should change this
2515 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2516
2517 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( phi->at(0).size(), 0. ) );
2518 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2519 for (UN j=0; j < valueVec[0].size(); j++) {
2520 for (UN w=0; w<dPhiTrans.size(); w++) {
2521 for (UN d=0; d<dim; d++)
2522 valueVec[d][j] += weights->at(w) * phi->at(w)[j] * dPhiTrans[w][i][d];
2523 }
2524 for (UN d=0; d<dim; d++){
2525 valueVec[d][j] *= absDetB;
2526 if (this->setZeros_ && std::fabs(valueVec[d][j]) < this->myeps_) {
2527 valueVec[d][j] = 0.;
2528 }
2529 }
2530 }
2531
2532 for (UN j=0; j < indices.size(); j++){
2533 if (FEType2=="P0")
2534 indices[j] = GO ( mapping2->getGlobalElement( T ) );
2535 else
2536 indices[j] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(j) ) );
2537 }
2538 for (UN d=0; d<dim; d++) {
2539 GO row = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(i) ) + d );
2540 BTmat->insertGlobalValues( row, indices(), valueVec[d]() );
2541 }
2542
2543 }
2544
2545 }
2546 if (callFillComplete) {
2547 Bmat->fillComplete( map1, map2 );
2548 BTmat->fillComplete( map2, map1 );
2549 }
2550
2551}
2552
2554template <class SC, class LO, class GO, class NO>
2556 std::string FEType1,
2557 std::string FEType2,
2558 int degree,
2559 MatrixPtr_Type &Bmat,
2560 MatrixPtr_Type &BTmat,
2561 MapConstPtr_Type map1,
2562 MapConstPtr_Type map2,
2563 bool callFillComplete) {
2564
2565
2566 UN FEloc1 = this->checkFE(dim,FEType1);
2567 UN FEloc2 = this->checkFE(dim,FEType2);
2568
2569 ElementsPtr_Type elements1 = this->domainVec_.at(FEloc1)->getElementsC();
2570 ElementsPtr_Type elements2 = this->domainVec_.at(FEloc2)->getElementsC();
2571
2572 vec2D_dbl_ptr_Type pointsRep1 = this->domainVec_.at(FEloc1)->getPointsRepeated();
2573
2574 MapConstPtr_Type mapping1 = this->domainVec_.at(FEloc1)->getMapRepeated();
2575 MapConstPtr_Type mapping2;
2576
2577 if (FEType2 == "P0")
2578 mapping2 = this->domainVec_.at(FEloc2)->getElementMap();
2579 else
2580 mapping2 = this->domainVec_.at(FEloc2)->getMapRepeated();
2581
2582 vec3D_dbl_ptr_Type dPhi;
2583 vec2D_dbl_ptr_Type phi;
2584 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2585
2586 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
2588
2589 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
2590
2591 // if (FEType2=="P1-disc-global")
2592 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
2593 if (FEType2=="P1-disc" && FEType1=="Q2" )
2594 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
2595 else
2596 Helper::getPhi(phi, weights, dim, FEType2, deg);
2597
2598 SC detB;
2599 SC absDetB;
2600 SmallMatrix<SC> B(dim);
2601 SmallMatrix<SC> Binv(dim);
2602 GO glob_i, glob_j;
2603 vec_dbl_Type v_i(dim);
2604 vec_dbl_Type v_j(dim);
2605
2606 Teuchos::Array<GO> colIndex( 1, 0 );
2607 Teuchos::Array<GO> rowIndex( 1, 0 );
2608 Teuchos::Array<SC> value(1, 0.);
2609
2610 for (UN T=0; T<elements1->numberElements(); T++) {
2611
2612 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
2613 detB = B.computeInverse(Binv);
2614 absDetB = std::fabs(detB);
2615
2616 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2617 applyBTinv( dPhi, dPhiTrans, Binv );
2618
2619 for (UN i=0; i < phi->at(0).size(); i++) {
2620 if (FEType2=="P0")
2621 rowIndex[0] = GO ( mapping2->getGlobalElement( T ) );
2622 else
2623 rowIndex[0] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
2624
2625 for (UN j=0; j < dPhiTrans[0].size(); j++) {
2626 for (UN d=0; d<dim; d++){
2627 value[0] = 0.;
2628 for (UN w=0; w<dPhiTrans.size(); w++)
2629 value[0] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
2630 value[0] *= absDetB;
2631 colIndex[0] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
2632 Bmat->insertGlobalValues( rowIndex[0], colIndex(), value() );
2633 BTmat->insertGlobalValues( colIndex[0], rowIndex(), value() );
2634
2635 }
2636 }
2637 }
2638
2639 }
2640 if (callFillComplete) {
2641 Bmat->fillComplete( map1, map2 );
2642 BTmat->fillComplete( map2, map1 );
2643 }
2644
2645}
2646
2648template <class SC, class LO, class GO, class NO>
2650 std::string FEType,
2651 MatrixPtr_Type &A,
2652 bool callFillComplete){
2653
2654 TEUCHOS_TEST_FOR_EXCEPTION(FEType != "P1" && FEType != "Q1",std::logic_error, "Only implemented for P1, Q1.");
2655 UN FEloc = this->checkFE(dim,FEType);
2656
2657 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
2658
2659 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
2660
2661 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
2662
2663 vec2D_dbl_ptr_Type phi;
2664
2665 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2666
2667 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2668
2669 Helper::getPhi( phi, weights, dim, FEType, deg );
2670
2671 SC detB;
2672 SC absDetB;
2673 SmallMatrix<SC> B(dim);
2674 GO glob_i, glob_j;
2675 vec_dbl_Type v_i(dim);
2676 vec_dbl_Type v_j(dim);
2677
2678 SC refElementSize;
2679 SC refElementScale;
2680 if(FEType=="P1"){
2681 if (dim==2) {
2682 refElementSize = 0.5;
2683 refElementScale = 1./9.;
2684 }
2685 else if(dim==3){
2686 refElementSize = 1./6.;
2687 refElementScale = 1./16.;
2688 }
2689 }
2690 else if(FEType=="Q1"){
2691 if(dim==3){
2692 refElementScale=1./64;
2693 refElementSize=8.;
2694 }
2695 else{
2696 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Q1 Only implemented for 3D.");
2697 }
2698 }
2699
2700 for (UN T=0; T<elements->numberElements(); T++) {
2701
2702 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2703 detB = B.computeDet( );
2704 absDetB = std::fabs(detB);
2705
2706 for (UN i=0; i < phi->at(0).size(); i++) {
2707 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2708 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2709 for (UN j=0; j < value.size(); j++) {
2710 for (UN w=0; w<phi->size(); w++) {
2711 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2712 }
2713 value[j] *= absDetB;
2714 value[j] -= refElementSize * absDetB * refElementScale;
2715
2716 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2717 }
2718
2719 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2720 A->insertGlobalValues( row, indices(), value() );
2721 }
2722
2723 }
2724
2725 if (callFillComplete)
2726 A->fillComplete();
2727}
2728
2729
2730
2731template <class SC, class LO, class GO, class NO>
2733 std::string FEType,
2734 MatrixPtr_Type &A,
2735 CoeffFuncDbl_Type func,
2736 double* parameters,
2737 bool callFillComplete)
2738{
2739 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2740 int FEloc = this->checkFE(dim,FEType);
2741
2742 DomainConstPtr_Type domain = this->domainVec_.at(FEloc);
2743 ElementsPtr_Type elements = domain->getElementsC();
2744 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
2745 MapConstPtr_Type map = domain->getMapRepeated();
2746
2747 vec3D_dbl_ptr_Type dPhi;
2748 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
2749 vec2D_dbl_ptr_Type quadPts;
2750
2751 // double val, value1_j, value2_j , value1_i, value2_i;
2752
2753 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
2754
2755 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
2756 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi, FEType);
2757
2758 // SC = double, GO = long, UN = int
2759 SC detB;
2760 SC absDetB;
2761 SmallMatrix<SC> B(dim);
2762 SmallMatrix<SC> Binv(dim);
2763 GO glob_i, glob_j;
2764
2765
2766 vec_dbl_ptr_Type dist = domain->getDistancesToInterface();
2767 if (dim == 2)
2768 {
2769 double val, value1_j, value2_j , value1_i, value2_i;
2770 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
2771
2772 double distance1, distance2, distance3;
2773 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
2774 for (int T = 0; T < elements->numberElements(); T++)
2775 {
2776 p1 = pointsRep->at(elements->getElement(T).getNode(0));
2777 p2 = pointsRep->at(elements->getElement(T).getNode(1));
2778 p3 = pointsRep->at(elements->getElement(T).getNode(2));
2779
2780 distance1 = dist->at(elements->getElement(T).getNode(0));
2781 distance2 = dist->at(elements->getElement(T).getNode(1));
2782 distance3 = dist->at(elements->getElement(T).getNode(2));
2783
2784 distance_mean.at(0) = (distance1 + distance2 + distance3)/3.0; // Mittelwert
2785 double funcvalue = func(&distance_mean.at(0),parameters);
2786
2787 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2788 detB = B.computeInverse(Binv);
2789 absDetB = std::fabs(detB);
2790
2791 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
2792 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2793 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
2794
2795 for (int i = 0; i < dPhi->at(0).size(); i++)
2796 {
2797 Teuchos::Array<SC> value( 1, 0. );
2798 Teuchos::Array<GO> indices( 1, 0 );
2799
2800 for (int j = 0; j < dPhi->at(0).size(); j++)
2801 {
2802 val = 0.0;
2803 for (int k = 0; k < dPhi->size(); k++)
2804 {
2805
2806 value1_j = dPhiTrans.at(k).at(j).at(0);
2807 value2_j = dPhiTrans.at(k).at(j).at(1);
2808
2809 value1_i = dPhiTrans.at(k).at(i).at(0);
2810 value2_i = dPhiTrans.at(k).at(i).at(1);
2811
2812 val = val + funcvalue * weightsDPhi->at(k) * ( value1_j*value1_i + value2_j*value2_i );
2813 }
2814 val = absDetB * val;
2815 value[0] = val;
2816
2817 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
2818 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
2819 indices[0] = glob_j;
2820
2821
2822 A->insertGlobalValues(glob_i, indices(), value());
2823 glob_j++;
2824 indices[0] = glob_j;
2825 A->insertGlobalValues(glob_i+1, indices(), value());
2826 }
2827 }
2828 }
2829 if (callFillComplete)
2830 {
2831 A->fillComplete();
2832 }
2833 }
2834 else if(dim == 3)
2835 {
2836 double val, value1_j, value2_j ,value3_j, value1_i, value2_i ,value3_i;
2837
2838 long long glob_i, glob_j;
2839 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
2840
2841 double distance1, distance2, distance3, distance4;
2842 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
2843 for (int T = 0; T < elements->numberElements(); T++)
2844 {
2845 p1 = pointsRep->at(elements->getElement(T).getNode(0));
2846 p2 = pointsRep->at(elements->getElement(T).getNode(1));
2847 p3 = pointsRep->at(elements->getElement(T).getNode(2));
2848 p4 = pointsRep->at(elements->getElement(T).getNode(3));
2849
2850 distance1 = dist->at(elements->getElement(T).getNode(0));
2851 distance2 = dist->at(elements->getElement(T).getNode(1));
2852 distance3 = dist->at(elements->getElement(T).getNode(2));
2853 distance4 = dist->at(elements->getElement(T).getNode(3));
2854
2855 distance_mean.at(0) = (distance1 + distance2 + distance3 + distance4)/4.0; //Mittelwert
2856 double funcvalue = func(&distance_mean.at(0),parameters);
2857
2858 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2859 detB = B.computeInverse(Binv);
2860 absDetB = std::fabs(detB);
2861
2862 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
2863 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2864 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
2865
2866 for (int i = 0; i < dPhi->at(0).size(); i++)
2867 {
2868 Teuchos::Array<SC> value( 1, 0. );
2869 Teuchos::Array<GO> indices( 1, 0 );
2870
2871 for (int j = 0; j < dPhi->at(0).size(); j++)
2872 {
2873 val = 0.0;
2874 for (int k = 0; k < dPhi->size(); k++)
2875 {
2876 value1_j = dPhiTrans.at(k).at(j).at(0);
2877 value2_j = dPhiTrans.at(k).at(j).at(1);
2878 value3_j = dPhiTrans.at(k).at(j).at(2);
2879
2880 value1_i = dPhiTrans.at(k).at(i).at(0);
2881 value2_i = dPhiTrans.at(k).at(i).at(1);
2882 value3_i = dPhiTrans.at(k).at(i).at(2);
2883
2884 val = val + funcvalue * weightsDPhi->at(k) * (value1_j*value1_i + value2_j*value2_i + value3_j*value3_i);
2885 }
2886 val = absDetB * val;
2887 value[0] = val;
2888
2889 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
2890 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
2891 indices[0] = glob_j;
2892 A->insertGlobalValues(glob_i, indices(), value());
2893 glob_j++;
2894 indices[0] = glob_j;
2895 A->insertGlobalValues(glob_i+1, indices(), value());
2896 glob_j++;
2897 indices[0] = glob_j;
2898 A->insertGlobalValues(glob_i+2, indices(), value());
2899
2900 }
2901 }
2902 }
2903 if (callFillComplete)
2904 {
2905 A->fillComplete();
2906 }
2907 }
2908
2909}
2910
2911
2912
2913template <class SC, class LO, class GO, class NO>
2915 std::string FEType,
2916 MatrixPtr_Type &A,
2917 CoeffFunc_Type func,
2918 int* parameters,
2919 bool callFillComplete)
2920{
2921 // TODO: [JK] This function does the same as Natalie's stress assembly, just that she can also use a nonconstant viscosity. We should think about deprecating this function here.
2922 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2923 int FEloc = this->checkFE(dim,FEType);
2924
2925 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
2926 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
2927 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
2928
2929 vec3D_dbl_ptr_Type dPhi;
2930 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
2931 vec2D_dbl_ptr_Type quadPts;
2932
2933 // double value, value1_j, value2_j , value1_i, value2_i;
2934
2935 // inner( grad(u) + grad(u)^T , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
2936 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
2937 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
2938 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
2939
2940 // SC = double, GO = long, UN = int
2941 SC detB;
2942 SC absDetB;
2943 SmallMatrix<SC> B(dim);
2944 SmallMatrix<SC> Binv(dim);
2945 GO glob_i, glob_j;
2946
2947 if (dim == 2)
2948 {
2949 double v11, v12, v21, v22, value1_j, value2_j , value1_i, value2_i;
2950 double e_11_j_1,e_12_j_1,e_21_j_1,e_22_j_1;
2951 double e_11_j_2,e_12_j_2,e_21_j_2,e_22_j_2;
2952 double e_11_i_1,e_12_i_1,e_21_i_1,e_22_i_1;
2953 double e_11_i_2,e_12_i_2,e_21_i_2,e_22_i_2;
2954
2955 SmallMatrix<double> tmpRes1(dim);
2956 SmallMatrix<double> tmpRes2(dim);
2957 SmallMatrix<double> e1i(dim);
2958 SmallMatrix<double> e2i(dim);
2959 SmallMatrix<double> e1j(dim);
2960 SmallMatrix<double> e2j(dim);
2961
2962 long long glob_i, glob_j;
2963 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
2964
2965 vec_dbl_Type xy(2);
2966 for (int T = 0; T < elements->numberElements(); T++)
2967 {
2968 p1 = pointsRep->at(elements->getElement(T).getNode(0));
2969 p2 = pointsRep->at(elements->getElement(T).getNode(1));
2970 p3 = pointsRep->at(elements->getElement(T).getNode(2));
2971
2972 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2973 detB = B.computeInverse(Binv);
2974 absDetB = std::fabs(detB);
2975
2976 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1)
2977 // Also \hat{grad_phi}.
2978 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2979 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
2980
2981 for (int i = 0; i < dPhi->at(0).size(); i++)
2982 {
2983 Teuchos::Array<SC> value11( 1, 0. );
2984 Teuchos::Array<SC> value12( 1, 0. );
2985 Teuchos::Array<SC> value21( 1, 0. );
2986 Teuchos::Array<SC> value22( 1, 0. );
2987 Teuchos::Array<GO> indices( 1, 0 );
2988
2989 for (int j=0; j < dPhi->at(0).size(); j++)
2990 {
2991 v11 = 0.0;v12 = 0.0;v21 = 0.0;v22 = 0.0;
2992 for (int k = 0; k < dPhi->size(); k++)
2993 {
2994 // Mappen der Gausspunkte (definiert auf T_ref) auf T (bzw. \Omega)
2995 // xy = F(quadPts) = B*quadPts + b, mit b = p1 (affin lineare Transformation)
2996 xy[0]=0.; xy[1]=0.;
2997 for (int r=0; r<2; r++) {
2998 xy[0] += B[0][r]*quadPts->at(k).at(r);
2999 xy[1] += B[1][r]*quadPts->at(k).at(r);
3000 }
3001 xy[0] += p1[0];
3002 xy[1] += p1[1];
3003
3004 value1_j = dPhiTrans.at(k).at(j).at(0);
3005 value2_j = dPhiTrans.at(k).at(j).at(1);
3006
3007 value1_i = dPhiTrans.at(k).at(i).at(0);
3008 value2_i = dPhiTrans.at(k).at(i).at(1);
3009
3010 tmpRes1[0][0] = value1_j;
3011 tmpRes1[0][1] = value2_j;
3012 tmpRes1[1][0] = 0.;
3013 tmpRes1[1][1] = 0.;
3014
3015 tmpRes2[0][0] = value1_j;
3016 tmpRes2[0][1] = 0.;
3017 tmpRes2[1][0] = value2_j;
3018 tmpRes2[1][1] = 0.;
3019
3020 tmpRes1.add(tmpRes2,e1j/*result*/);
3021
3022 e1i[0][0] = value1_i;
3023 e1i[0][1] = value2_i;
3024
3025
3026 tmpRes1[0][0] = 0.;
3027 tmpRes1[0][1] = 0.;
3028 tmpRes1[1][0] = value1_j;
3029 tmpRes1[1][1] = value2_j;
3030
3031 tmpRes2[0][0] = 0.;
3032 tmpRes2[0][1] = value1_j;
3033 tmpRes2[1][0] = 0.;
3034 tmpRes2[1][1] = value2_j;
3035
3036 tmpRes1.add(tmpRes2,e2j/*result*/);
3037
3038 e2i[1][0] = value1_i;
3039 e2i[1][1] = value2_i;
3040
3041 double funcvalue = func(&xy.at(0),parameters);
3042 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
3043 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
3044 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
3045 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
3046
3047 }
3048
3049 v11 = absDetB * v11;
3050 v12 = absDetB * v12;
3051 v21 = absDetB * v21;
3052 v22 = absDetB * v22;
3053
3054 value11[0] = v11;
3055 value12[0] = v12;
3056 value21[0] = v21;
3057 value22[0] = v22;
3058
3059 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
3060 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
3061 indices[0] = glob_j;
3062
3063 A->insertGlobalValues(glob_i, indices(), value11());
3064 A->insertGlobalValues(glob_i+1, indices(), value21());
3065 glob_j++;
3066 indices[0] = glob_j;
3067 A->insertGlobalValues(glob_i, indices(), value12());
3068 A->insertGlobalValues(glob_i+1, indices(), value22());
3069 }
3070 }
3071 }
3072 if (callFillComplete)
3073 {
3074 A->fillComplete();
3075 }
3076 }
3077 else if(dim == 3)
3078 {
3079 double v11, v12, v13, v21, v22, v23, v31, v32, v33, value1_j, value2_j, value3_j , value1_i, value2_i, value3_i;
3080
3081 SmallMatrix<double> e1i(dim);
3082 SmallMatrix<double> e2i(dim);
3083 SmallMatrix<double> e3i(dim);
3084 SmallMatrix<double> e1j(dim);
3085 SmallMatrix<double> e2j(dim);
3086 SmallMatrix<double> e3j(dim);
3087
3088 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
3089 vec_dbl_Type xyz(3);
3090
3091 for (int T = 0; T < elements->numberElements(); T++)
3092 {
3093 p1 = pointsRep->at(elements->getElement(T).getNode(0));
3094 p2 = pointsRep->at(elements->getElement(T).getNode(1));
3095 p3 = pointsRep->at(elements->getElement(T).getNode(2));
3096 p4 = pointsRep->at(elements->getElement(T).getNode(3));
3097
3098 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
3099 detB = B.computeInverse(Binv);
3100 absDetB = std::fabs(detB);
3101
3102 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
3103 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3104 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
3105
3106 for (int i = 0; i < dPhi->at(0).size(); i++)
3107 {
3108 Teuchos::Array<SC> value11( 1, 0. );
3109 Teuchos::Array<SC> value12( 1, 0. );
3110 Teuchos::Array<SC> value13( 1, 0. );
3111 Teuchos::Array<SC> value21( 1, 0. );
3112 Teuchos::Array<SC> value22( 1, 0. );
3113 Teuchos::Array<SC> value23( 1, 0. );
3114 Teuchos::Array<SC> value31( 1, 0. );
3115 Teuchos::Array<SC> value32( 1, 0. );
3116 Teuchos::Array<SC> value33( 1, 0. );
3117 Teuchos::Array<GO> indices( 1, 0 );
3118
3119 for (int j = 0; j < dPhi->at(0).size(); j++)
3120 {
3121 v11 = 0.0;v12 = 0.0;v13 = 0.0;v21 = 0.0;v22 = 0.0;v23 = 0.0;v31 = 0.0;v32 = 0.0;v33 = 0.0;
3122 for (int k = 0; k < dPhi->size(); k++)
3123 {
3124
3125 xyz[0]=0.; xyz[1]=0.; xyz[2]=0.;
3126 for (int r = 0; r < 3; r++)
3127 {
3128 xyz[0] += B[0][r]*quadPts->at(k).at(r);
3129 xyz[1] += B[1][r]*quadPts->at(k).at(r);
3130 xyz[2] += B[2][r]*quadPts->at(k).at(r);
3131 }
3132 xyz[0] += p1[0];
3133 xyz[1] += p1[1];
3134 xyz[2] += p1[2];
3135
3136
3137
3138 value1_j = dPhiTrans.at(k).at(j).at(0);
3139 value2_j = dPhiTrans.at(k).at(j).at(1);
3140 value3_j = dPhiTrans.at(k).at(j).at(2);
3141
3142
3143 value1_i = dPhiTrans.at(k).at(i).at(0);
3144 value2_i = dPhiTrans.at(k).at(i).at(1);
3145 value3_i = dPhiTrans.at(k).at(i).at(2);
3146
3147
3148 e1j[0][0] = 2.*value1_j;
3149 e1j[0][1] = value2_j;
3150 e1j[0][2] = value3_j;
3151 e1j[1][0] = value2_j;
3152 e1j[2][0] = value3_j;
3153
3154 e1i[0][0] = value1_i;
3155 e1i[0][1] = value2_i;
3156 e1i[0][2] = value3_i;
3157
3158
3159 e2j[1][0] = value1_j;
3160 e2j[1][1] = 2.*value2_j;
3161 e2j[1][2] = value3_j;
3162 e2j[0][1] = value1_j;
3163 e2j[2][1] = value3_j;
3164
3165 e2i[1][0] = value1_i;
3166 e2i[1][1] = value2_i;
3167 e2i[1][2] = value3_i;
3168
3169
3170 e3j[2][0] = value1_j;
3171 e3j[2][1] = value2_j;
3172 e3j[2][2] = 2.*value3_j;
3173 e3j[0][2] = value1_j;
3174 e3j[1][2] = value2_j;
3175
3176 e3i[2][0] = value1_i;
3177 e3i[2][1] = value2_i;
3178 e3i[2][2] = value3_i;
3179
3180 double funcvalue = func(&xyz.at(0),parameters);
3181
3182 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
3183 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
3184 v13 = v13 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e3j);
3185
3186 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
3187 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
3188 v23 = v23 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e3j);
3189
3190 v31 = v31 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e1j);
3191 v32 = v32 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e2j);
3192 v33 = v33 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e3j);
3193
3194
3195 }
3196 v11 = absDetB * v11;
3197 v12 = absDetB * v12;
3198 v13 = absDetB * v13;
3199 v21 = absDetB * v21;
3200 v22 = absDetB * v22;
3201 v23 = absDetB * v23;
3202 v31 = absDetB * v31;
3203 v32 = absDetB * v32;
3204 v33 = absDetB * v33;
3205
3206 value11[0] = v11;
3207 value12[0] = v12;
3208 value13[0] = v13;
3209 value21[0] = v21;
3210 value22[0] = v22;
3211 value23[0] = v23;
3212 value31[0] = v31;
3213 value32[0] = v32;
3214 value33[0] = v33;
3215
3216 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
3217 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
3218 indices[0] = glob_j;
3219 A->insertGlobalValues(glob_i, indices(), value11());
3220 A->insertGlobalValues(glob_i+1, indices(), value21());
3221 A->insertGlobalValues(glob_i+2, indices(), value31());
3222
3223 glob_j++;
3224 indices[0] = glob_j;
3225 A->insertGlobalValues(glob_i, indices(), value12());
3226 A->insertGlobalValues(glob_i+1, indices(), value22());
3227 A->insertGlobalValues(glob_i+2, indices(), value32());
3228
3229 glob_j++;
3230 indices[0] = glob_j;
3231 A->insertGlobalValues(glob_i, indices(), value13());
3232 A->insertGlobalValues(glob_i+1, indices(), value23());
3233 A->insertGlobalValues(glob_i+2, indices(), value33());
3234 }
3235 }
3236 }
3237 if (callFillComplete)
3238 {
3239 A->fillComplete();
3240 }
3241 }
3242
3243}
3244
3245
3246template <class SC, class LO, class GO, class NO>
3247double FE<SC,LO,GO,NO>::assemblyAbsorbingBoundaryPaper(int dim,
3248 std::string FEType,
3249 MultiVectorPtr_Type f,
3250 MultiVectorPtr_Type u_rep,
3251 vec_dbl_Type flowRate_vec,
3252 std::vector<SC>& funcParameter,
3253 RhsFunc_Type func,
3254 double areaOutlet_init,
3255 double areaOutlet_T,
3256 ParameterListPtr_Type params,
3257 int FEloc) {
3258
3259 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
3260
3261 ElementsPtr_Type elementsPressure = this->domainVec_.at(FEloc+1)->getElementsC();
3262
3263 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
3264
3265 vec2D_dbl_ptr_Type phi;
3266
3267
3268 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3269
3270 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
3271 Helper::getPhi(phi, weights, dim-1, FEType, deg);
3272
3273 vec2D_dbl_ptr_Type quadPoints;
3274 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
3275 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
3276 w.reset();
3277
3278 double poissonRatio=params->sublist("Parameter Fluid").get("Poisson Ratio",0.49);
3279 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
3280 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
3281
3282 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
3283 double E = params->sublist("Parameter Fluid").get("E",12.0);
3284 double wallThickness = params->sublist("Parameter Fluid").get("Wall thickness",0.0006);
3285 double density = params->sublist("Parameter Fluid").get("Density",1000.0);
3286 double p_ref_input = params->sublist("Parameter Fluid").get("Reference fluid pressure",10666.);
3287
3288 double rampTime = params->sublist("Parameter Fluid").get("Max Ramp Time",0.1);
3289 double unsteadyStart = params->sublist("Parameter Fluid").get("Unsteady Start",0.2);
3290 double flowRateInput = params->sublist("Parameter Fluid").get("Flowrate",3.0);
3291
3292 double bcRamp = params->sublist("Parameter Fluid").get("BC Ramp",0.1);
3293
3294
3295 SC elScaling;
3296 SmallMatrix<SC> B(dim);
3297 SmallMatrix<SC> Binv(dim);
3298 SC detB;
3299 SC absDetB;
3300 vec_dbl_Type b(dim);
3301 f->putScalar(0.);
3302 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
3303
3304 std::vector<double> valueFunc(dim);
3305
3306 double flowRateOutlet=0.;
3307 double flowRateInlet=0.;
3308
3309 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
3310
3311 int isNeg = this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
3312
3313 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
3314
3315 double areaOutlet = 0.;
3316 this->assemblyArea(dim, areaOutlet, flagOutlet);
3317
3318 double areaInlet =0.;
3319 this->assemblyArea(dim, areaInlet, flagInlet);
3320
3321 double beta=0.;
3322 if(funcParameter[0] < unsteadyStart)
3323 beta = ((wallThickness* E)/(1.-pow(poissonRatio,2))) * (M_PI/areaOutlet_init ) ;
3324 else
3325 beta = ((wallThickness* E)/(1.-pow(poissonRatio,2))) * (M_PI/areaOutlet_T ) ;
3326
3327 // We determine p_ref via a ramp
3328 funcParameter.push_back(p_ref_input);
3329 funcParameter.push_back(bcRamp);
3330 funcParameter.push_back(flagOutlet);
3331 SC* paramsFunc = &(funcParameter[0]);
3332 vec_dbl_Type x_tmp(dim,0.); //dummy
3333 paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
3334 paramsFunc[ 1 ] = p_ref_input;
3335 func( &x_tmp[0], &valueFunc[0], paramsFunc);
3336 double p_ref = valueFunc[0];
3337 if(funcParameter[0]+1e-12 >= unsteadyStart){
3338 p_ref = p_ref - std::pow( (std::sqrt(density)/(2*std::sqrt(2)) * flowRateInput/areaOutlet_T + std::sqrt(beta*std::sqrt(areaOutlet_T))),2) + beta*std::sqrt(areaOutlet_T);
3339
3340 if(this->domainVec_.at(0)->getComm()->getRank()==0){
3341 std::cout << " ---------------------------------------------------------- " <<std::endl;
3342 std::cout << " ---------------- Start of unsteady phase ---------------- " <<std::endl;
3343 std::cout << " Reference pressure adjusted from " << p_ref_input << " to " << p_ref <<std::endl;
3344 }
3345
3346 }
3347 // Value of h_x for this timestep
3348 double flowRateUse = flowRateOutlet;
3349 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
3350 flowRateUse = flowRateOutletAveraged;
3351
3352 if(isNeg==1)
3353 flowRateUse = 0.;
3354
3355 double A_bar = 1./((std::sqrt(beta*std::sqrt(areaOutlet_init)+p_ref_input)-std::sqrt(beta*std::sqrt(areaOutlet_init)))*2.*std::sqrt(2.)*(1./std::sqrt(density))*(1./flowRateInput));
3356 double h_x = 0.;
3357
3358 if(funcParameter[0] < unsteadyStart)
3359 h_x= std::pow( (std::sqrt(density)/(2*std::sqrt(2)) * flowRateUse/A_bar + std::sqrt(beta*std::sqrt(areaOutlet_init))),2) - beta*std::sqrt(areaOutlet_init);
3360 else
3361 h_x= std::pow( (std::sqrt(density)/(2*std::sqrt(2)) * flowRateUse/areaOutlet + std::sqrt(beta*std::sqrt(areaOutlet_T))),2) - beta*std::sqrt(areaOutlet_T) + p_ref;
3362
3363 // h_x= pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta*sqrt(areaOutlet_init))),2) - beta*sqrt(areaOutlet_init) + p_ref;
3364
3365 if(this->domainVec_.at(0)->getComm()->getRank()==0){
3366 std::cout << " ---------------------------------------------------------- " <<std::endl;
3367 std::cout << " ---------------------------------------------------------- " <<std::endl;
3368 std::cout << " Absorbing Boundary Condition " <<std::endl;
3369 std::cout << " Input p_ref: " << p_ref_input <<std::endl;
3370 std::cout << " Adjusted p_ref: " << p_ref <<std::endl;
3371 std::cout << " Unsteady start time_ " << unsteadyStart <<std::endl;
3372 std::cout << " Volmetric flow Inlet: " << flowRateInlet <<std::endl;
3373 std::cout << " Volmetric flow Outlet: " << flowRateOutlet <<std::endl;
3374 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged <<std::endl;
3375 std::cout << " beta per Input: " << beta <<std::endl;
3376 std::cout << " Area_init outlet: " << areaOutlet_init <<std::endl;
3377 std::cout << " Area_init outlet_T: " << areaOutlet_T <<std::endl;
3378 std::cout << " Area inlet: " << areaInlet <<std::endl;
3379 std::cout << " Area outlet: " << areaOutlet <<std::endl;
3380 std::cout << " A_bar: " << A_bar <<std::endl;
3381 std::cout << " Flowrate was negative: " << isNeg <<std::endl;
3382 std::cout << " Value h_x at outlet: " << h_x <<std::endl;
3383 std::cout << " --------------------------------------------------------- " <<std::endl;
3384 std::cout << " --------------------------------------------------------- " <<std::endl;
3385
3386 }
3387 // Second step: use flow rate to determine pressure with resistance
3388 for (UN T=0; T<elements->numberElements(); T++) {
3389 FiniteElement fe = elements->getElement( T );
3390 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
3391 for (int surface=0; surface<fe.numSubElements(); surface++) {
3392 FiniteElement feSub = subEl->getElement( surface );
3393 if(subEl->getDimension() == dim-1 ){
3394 if(feSub.getFlag() == flagOutlet){
3395 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
3396 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
3397 int numNodes_T = nodeList.size();
3398 vec_dbl_Type solution_u = this->getSolution(nodeList, u_rep,dim);
3399 vec2D_dbl_Type nodes;
3400 nodes = this->getCoordinates(nodeList, pointsRep);
3401
3402 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
3403
3404 double norm_v_E = 1.;
3405 if(dim==2){
3406 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3407 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
3408 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
3409
3410 }
3411 else if(dim==3){
3412
3413 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
3414 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3415 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
3416
3417 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
3418 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
3419 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
3420
3421 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
3422 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
3423 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
3424
3425 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
3426
3427
3428 }
3429
3430 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
3431 // Step 1: Quadrature Points on physical surface:
3432 // Resulting Quad Points allways (0.5,0,0) (0.5,0.5,0) (0,0.5,0)
3433 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
3434 elScaling = B.computeScaling( );
3435
3436 //cout <<std::endl;
3437
3438 for (UN i=0; i < numNodes_T; i++) {
3439
3440 // 2.
3441 Teuchos::Array<SC> value(0);
3442 value.resize( dim, 0. );
3443 // loop over basis functions quadrature points
3444 for (UN w=0; w<phi->size(); w++) {
3445 for (int j=0; j<dim; j++){
3446 value[j] += weights->at(w) *normalScale*v_E[j]/norm_v_E *h_x*(*phi)[w][i];//valueFunc[0]
3447 }
3448 }
3449
3450 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
3451 for (int j=0; j<value.size(); j++)
3452 valuesF[ dim * nodeList[ i ] + j ] += value[j] * elScaling;
3453 }
3454
3455 }
3456
3457 }
3458 }
3459 }
3460 double p_out = h_x;
3461 return p_out;
3462}
3463
3464template <class SC, class LO, class GO, class NO>
3465double FE<SC,LO,GO,NO>::assemblyAbsorbingBoundary(int dim,
3466 std::string FEType,
3467 MultiVectorPtr_Type f,
3468 MultiVectorPtr_Type u_rep,
3469 vec_dbl_Type flowRate_vec,
3470 std::vector<SC>& funcParameter,
3471 RhsFunc_Type func,
3472 double areaOutlet_init,
3473 double areaOutlet_T,
3474 ParameterListPtr_Type params,
3475 int FEloc) {
3476
3477 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
3478
3479 ElementsPtr_Type elementsPressure = this->domainVec_.at(FEloc+1)->getElementsC();
3480
3481 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
3482
3483 vec2D_dbl_ptr_Type phi;
3484
3485
3486 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3487
3488 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
3489 Helper::getPhi(phi, weights, dim-1, FEType, deg);
3490
3491 vec2D_dbl_ptr_Type quadPoints;
3492 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
3493 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
3494 w.reset();
3495
3496 double poissonRatio=params->sublist("Parameter Fluid").get("Poisson Ratio",0.49);
3497 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
3498 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
3499
3500 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
3501
3502 double density = params->sublist("Parameter Fluid").get("Density",1.0);
3503 double p_ref_input = params->sublist("Parameter Fluid").get("Reference fluid pressure",10666.);
3504
3505 double rampTime = params->sublist("Parameter Fluid").get("Max Ramp Time",0.1);
3506 double unsteadyStart = params->sublist("Parameter Fluid").get("Heart Beat Start",0.2);
3507 double flowRateInput = params->sublist("Parameter Fluid").get("Flowrate",3.0e-06);
3508
3509 double bcRamp = params->sublist("Parameter Fluid").get("BC Ramp",0.1);
3510
3511
3512 SC elScaling;
3513 SmallMatrix<SC> B(dim);
3514 SmallMatrix<SC> Binv(dim);
3515 SC detB;
3516 SC absDetB;
3517 vec_dbl_Type b(dim);
3518 f->putScalar(0.);
3519 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
3520
3521 std::vector<double> valueFunc(dim);
3522
3523 double flowRateOutlet=0.;
3524 double flowRateInlet=0.;
3525
3526 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
3527 int isNeg = this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
3528
3529 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
3530
3531 double areaOutlet = 0.;
3532 this->assemblyArea(dim, areaOutlet, flagOutlet);
3533
3534 double areaInlet =0.;
3535 this->assemblyArea(dim, areaInlet, flagInlet);
3536
3537 double beta=0.;
3538
3539 double E = params->sublist("Parameter Fluid").get("E",12.0);
3540 double wallThickness = params->sublist("Parameter Fluid").get("Wall thickness",0.0006);
3541
3542 beta = ((wallThickness* E)/(1.-pow(poissonRatio,2))) * (M_PI/areaOutlet_init ) ;
3543
3544
3545 funcParameter.push_back(p_ref_input);
3546 funcParameter.push_back(bcRamp);
3547 funcParameter.push_back(flagOutlet);
3548 // We determine p_ref via a ramp
3549 SC* paramsFunc = &(funcParameter[0]);
3550 vec_dbl_Type x_tmp(dim,0.); //dummy
3551 // Adding parameters
3552
3553 // paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
3554 // paramsFunc[ 1 ] = p_ref_input;
3555 func( &x_tmp[0], &valueFunc[0], paramsFunc);
3556 double p_ref = valueFunc[0];
3557 //if(funcParameter[0]+1e-12 >= unsteadyStart){
3558
3559
3560 //}
3561 // Value of h_x for this timestep
3562 double flowRateUse = flowRateOutlet;
3563 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
3564 flowRateUse = flowRateOutletAveraged;
3565
3566 if(isNeg==1)
3567 flowRateUse = 0.;
3568
3569 if(this->domainVec_.at(0)->getComm()->getRank()==0){
3570 std::cout << " ---------------------------------------------------------- " <<std::endl;
3571 std::cout << " ---------------- computing p_ref ---------------- " <<std::endl;
3572 std::cout << " Reference pressure adjusted from " << p_ref_input << " to " << p_ref <<std::endl;
3573 }
3574 //double A_bar = 1./((sqrt(beta*sqrt(areaOutlet_init)+p_ref_input)-sqrt(beta*sqrt(areaOutlet_init)))*2.*sqrt(2.)*(1./sqrt(density))*(1./flowRateInput));
3575
3576 double h_x = pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta*sqrt(areaOutlet_init))),2) - beta*sqrt(areaOutlet_init)+p_ref;
3577
3578 // h_x= pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta*sqrt(areaOutlet_init))),2) - beta*sqrt(areaOutlet_init) + p_ref;
3579
3580 if(this->domainVec_.at(0)->getComm()->getRank()==0){
3581 std::cout << " ---------------------------------------------------------- " <<std::endl;
3582 std::cout << " ---------------------------------------------------------- " <<std::endl;
3583 std::cout << " Absorbing Boundary Condition " <<std::endl;
3584 std::cout << " Input p_ref: " << p_ref_input <<std::endl;
3585 std::cout << " Adjusted p_ref: " << p_ref <<std::endl;
3586 std::cout << " Volmetric flow Inlet: " << flowRateInlet <<std::endl;
3587 std::cout << " Volmetric flow Outlet: " << flowRateOutlet <<std::endl;
3588 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged <<std::endl;
3589 std::cout << " beta per Input: " << beta <<std::endl;
3590 std::cout << " Area_init outlet: " << areaOutlet_init <<std::endl;
3591 std::cout << " Area inlet: " << areaInlet <<std::endl;
3592 std::cout << " Area outlet: " << areaOutlet <<std::endl;
3593 std::cout << " Value h_x at outlet: " << h_x <<std::endl;
3594 std::cout << " --------------------------------------------------------- " <<std::endl;
3595 std::cout << " --------------------------------------------------------- " <<std::endl;
3596
3597 }
3598 // Second step: use flow rate to determine pressure with resistance
3599 for (UN T=0; T<elements->numberElements(); T++) {
3600 FiniteElement fe = elements->getElement( T );
3601 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
3602 for (int surface=0; surface<fe.numSubElements(); surface++) {
3603 FiniteElement feSub = subEl->getElement( surface );
3604 if(subEl->getDimension() == dim-1 ){
3605 if(feSub.getFlag() == flagOutlet){
3606 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
3607 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
3608 int numNodes_T = nodeList.size();
3609 vec_dbl_Type solution_u = this->getSolution(nodeList, u_rep,dim);
3610 vec2D_dbl_Type nodes;
3611 nodes = this->getCoordinates(nodeList, pointsRep);
3612
3613 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
3614
3615 double norm_v_E = 1.;
3616 if(dim==2){
3617 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3618 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
3619 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
3620
3621 }
3622 else if(dim==3){
3623
3624 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
3625 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3626 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
3627
3628 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
3629 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
3630 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
3631
3632 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
3633 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
3634 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
3635
3636 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
3637
3638
3639 }
3640
3641 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
3642 elScaling = B.computeScaling( );
3643
3644 for (UN i=0; i < numNodes_T; i++) {
3645
3646 // 2.
3647 Teuchos::Array<SC> value(0);
3648 value.resize( dim, 0. );
3649 // loop over basis functions quadrature points
3650 for (UN w=0; w<phi->size(); w++) {
3651 for (int j=0; j<dim; j++){
3652 value[j] += weights->at(w) *normalScale*v_E[j]/norm_v_E *h_x*(*phi)[w][i];//valueFunc[0]
3653 }
3654 }
3655
3656 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
3657 for (int j=0; j<value.size(); j++)
3658 valuesF[ dim * nodeList[ i ] + j ] += value[j] * elScaling;
3659 }
3660
3661 }
3662
3663 }
3664 }
3665 }
3666 double p_out = h_x;
3667 return p_out;
3668}
3669
3670
3671template <class SC, class LO, class GO, class NO>
3672double FE<SC,LO,GO,NO>::assemblyAbsorbingResistanceBoundary(int dim,
3673 std::string FEType,
3674 MultiVectorPtr_Type f,
3675 MultiVectorPtr_Type u_rep,
3676 vec_dbl_Type flowRate_vec,
3677 std::vector<SC>& funcParameter,
3678 RhsFunc_Type func,
3679 double areaOutlet_init,
3680 ParameterListPtr_Type params,
3681 int FEloc) {
3682
3683 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
3684
3685 ElementsPtr_Type elementsPressure = this->domainVec_.at(FEloc+1)->getElementsC();
3686
3687 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
3688
3689 vec2D_dbl_ptr_Type phi;
3690
3691
3692 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3693
3694 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
3695 Helper::getPhi(phi, weights, dim-1, FEType, deg);
3696
3697 vec2D_dbl_ptr_Type quadPoints;
3698 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
3699 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
3700 w.reset();
3701
3702 double poissonRatio=params->sublist("Parameter Fluid").get("Poisson Ratio",0.49);
3703 double viscosity=params->sublist("Parameter Fluid").get("Viscosity",1.0e-06);
3704 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
3705 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
3706
3707 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
3708 double E = params->sublist("Parameter Fluid").get("E",12.0);
3709 double wallThickness = params->sublist("Parameter Fluid").get("Wall thickness",0.001);
3710 double density = params->sublist("Parameter Fluid").get("Density",1000.0);
3711 double p_ref_input = params->sublist("Parameter Fluid").get("Reference fluid pressure",8000.);
3712 double resistanceRamp = params->sublist("Parameter Fluid").get("Resistance Ramp",2.); // Ramp time of fluid
3713 double resistance = params->sublist("Parameter Fluid").get("Resistance",1.0);
3714
3715 SC elScaling;
3716 SmallMatrix<SC> B(dim);
3717 SmallMatrix<SC> Binv(dim);
3718 SC detB;
3719 SC absDetB;
3720 vec_dbl_Type b(dim);
3721 f->putScalar(0.);
3722 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
3723
3724 std::vector<double> valueFunc(dim);
3725
3726 double flowRateOutlet=0.;
3727 double flowRateInlet=0.;
3728
3729 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
3730 this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
3731
3732 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
3733
3734 double areaOutlet = 0.;
3735 this->assemblyArea(dim, areaOutlet, flagOutlet);
3736
3737 double areaInlet =0.;
3738 this->assemblyArea(dim, areaInlet, flagInlet);
3739
3740 double beta = (((wallThickness* E)/(1-pow(poissonRatio,2))) * M_PI/areaOutlet_init ) *sqrt(areaOutlet_init);
3741 // We determine p_ref via a ramp
3742 SC* paramsFunc = &(funcParameter[0]);
3743 vec_dbl_Type x_tmp(dim,0.); //dummy
3744 paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
3745 //paramsFunc[ 1 ] = p_ref;
3746 //p_ref = valueFunc[0];
3747 // Value of h_x for this timestep
3748 double flowRateUse = flowRateOutlet;
3749 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
3750 flowRateUse = flowRateOutletAveraged;
3751
3752 double p_ref = 0.;
3753 if(paramsFunc[0] < resistanceRamp){
3754 //func( &x_tmp[0], &valueFunc[0], paramsFunc);
3755 p_ref = flowRateUse*resistance;
3756
3757 }
3758 else{
3759 paramsFunc[ 1 ] = p_ref_input;
3760 func( &x_tmp[0], &valueFunc[0], paramsFunc);
3761 //p_ref = valueFunc[0];
3762 p_ref = valueFunc[0];
3763
3764 }
3765
3766 double h_x = pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta)),2) - beta + p_ref;
3767
3768
3769 if(this->domainVec_.at(0)->getComm()->getRank()==0){
3770 std::cout << " ---------------------------------------------------------- " <<std::endl;
3771 std::cout << " ---------------------------------------------------------- " <<std::endl;
3772 std::cout << " Absorbing Boundary Condition " <<std::endl;
3773 std::cout << " p_ref: " << p_ref <<std::endl;
3774 std::cout << " Volmetric flow Inlet: " << flowRateInlet <<std::endl;
3775 std::cout << " Volmetric flow Outlet: " << flowRateOutlet <<std::endl;
3776 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged <<std::endl;
3777 std::cout << " beta*sqrt(A_0) per Input: " << beta <<std::endl;
3778 std::cout << " Area_init outlet: " << areaOutlet_init <<std::endl;
3779 std::cout << " Area inlet: " << areaInlet <<std::endl;
3780 std::cout << " Area outlet: " << areaOutlet <<std::endl;
3781 std::cout << " Value h_x at outlet: " << h_x <<std::endl;
3782 std::cout << " --------------------------------------------------------- " <<std::endl;
3783 std::cout << " --------------------------------------------------------- " <<std::endl;
3784
3785 }
3786 // Second step: use flow rate to determine pressure with resistance
3787 for (UN T=0; T<elements->numberElements(); T++) {
3788 FiniteElement fe = elements->getElement( T );
3789 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
3790 for (int surface=0; surface<fe.numSubElements(); surface++) {
3791 FiniteElement feSub = subEl->getElement( surface );
3792 if(subEl->getDimension() == dim-1 ){
3793 if(feSub.getFlag() == flagOutlet){
3794 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
3795 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
3796 int numNodes_T = nodeList.size();
3797 vec_dbl_Type solution_u = this->getSolution(nodeList, u_rep,dim);
3798 vec2D_dbl_Type nodes;
3799 nodes = this->getCoordinates(nodeList, pointsRep);
3800
3801 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
3802
3803 double norm_v_E = 1.;
3804 if(dim==2){
3805 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3806 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
3807 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
3808
3809 }
3810 else if(dim==3){
3811
3812 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
3813 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3814 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
3815
3816 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
3817 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
3818 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
3819
3820 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
3821 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
3822 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
3823
3824 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
3825
3826
3827 }
3828
3829 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
3830 // Step 1: Quadrature Points on physical surface:
3831 // Resulting Quad Points allways (0.5,0,0) (0.5,0.5,0) (0,0.5,0)
3832 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
3833 elScaling = B.computeScaling( );
3834
3835 //cout <<std::endl;
3836
3837 for (UN i=0; i < numNodes_T; i++) {
3838
3839 // 2.
3840 Teuchos::Array<SC> value(0);
3841 value.resize( dim, 0. );
3842 // loop over basis functions quadrature points
3843 for (UN w=0; w<phi->size(); w++) {
3844 for (int j=0; j<dim; j++){
3845 value[j] += weights->at(w) *normalScale*v_E[j]/norm_v_E *h_x*(*phi)[w][i];//valueFunc[0]
3846 }
3847 }
3848
3849 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
3850 for (int j=0; j<value.size(); j++)
3851 valuesF[ dim * nodeList[ i ] + j ] += value[j] * elScaling;
3852 }
3853
3854 }
3855
3856 }
3857 }
3858 }
3859 double p_out = h_x;
3860 return p_out;
3861}
3862
3863
3864template <class SC, class LO, class GO, class NO>
3865double FE<SC,LO,GO,NO>::assemblyResistanceBoundary(int dim,
3866 std::string FEType,
3867 MultiVectorPtr_Type f,
3868 MultiVectorPtr_Type u_rep,
3869 vec_dbl_Type flowRate_vec,
3870 std::vector<SC>& funcParameter,
3871 RhsFunc_Type func,
3872 ParameterListPtr_Type params,
3873 int FEloc) {
3874
3875 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
3876
3877 ElementsPtr_Type elementsPressure = this->domainVec_.at(FEloc+1)->getElementsC();
3878
3879 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
3880
3881 vec2D_dbl_ptr_Type phi;
3882 vec2D_dbl_ptr_Type phi1;
3883
3884 vec3D_dbl_ptr_Type dPhi;
3885
3886 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3887 vec_dbl_ptr_Type weights1 = Teuchos::rcp(new vec_dbl_Type(0));
3888
3889 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
3890 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3891 Helper::getPhi(phi, weights, dim-1, FEType, deg);
3892 Helper::getPhi(phi1, weights1, dim-1, FEType, 2);
3893
3894 vec2D_dbl_ptr_Type quadPoints;
3895 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
3896 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
3897 w.reset();
3898
3899 double viscosity=params->sublist("Parameter").get("Viscosity",0.49);
3900 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
3901 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
3902
3903 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
3904 double resistance = params->sublist("Parameter Fluid").get("Resistance",1.0);
3905 double bcRamp = params->sublist("Parameter Fluid").get("BC Ramp",0.1);
3906
3907 double referencePressure = params->sublist("Parameter Fluid").get("Reference fluid pressure",11.99e1);
3908
3909
3910 SC elScaling;
3911 SmallMatrix<SC> B(dim);
3912 SmallMatrix<SC> Binv(dim);
3913 SC detB;
3914 SC absDetB;
3915 vec_dbl_Type b(dim);
3916 f->putScalar(0.);
3917 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
3918
3919 std::vector<double> valueFunc(dim);
3920
3921 // Adding parameters
3922 funcParameter.push_back(resistance);
3923 funcParameter.push_back(bcRamp);
3924 funcParameter.push_back(flagOutlet);
3925
3926 SC* paramsFunc = &(funcParameter[0]);
3927 double flowRateInlet=0.;
3928 double flowRateOutlet=0.;
3929 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
3930 int isNeg = this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
3931
3932 double resistanceRef = referencePressure/flowRateInlet; // The resistance based on a reference pressure value and the current inlet flow rate
3933
3934 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
3935
3936 vec_dbl_Type x_tmp(dim,0.); //dummy
3937 // paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
3938
3939 func( &x_tmp[0], &valueFunc[0], paramsFunc);
3940
3941 if(this->domainVec_.at(0)->getComm()->getRank()==0){
3942 std::cout << " ---------------------------------------------------------- " << std::endl;
3943 std::cout << " ---------------------------------------------------------- " << std::endl;
3944 std::cout << " Resistance Boundary Condition " << std::endl;
3945 std::cout << " Volmetric flow Inlet: " << flowRateInlet << std::endl;
3946 std::cout << " Volmetric flow Outlet: " << flowRateOutlet << std::endl;
3947 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged << std::endl;
3948 std::cout << " Resistance per Input: " << valueFunc[0] << std::endl;
3949 std::cout << " Assumed reference pressure at outlet " << referencePressure<< std::endl;
3950 std::cout << " Implicit pressure at outlet with p=R*Q: " << flowRateOutlet*valueFunc[0] << std::endl;
3951 std::cout << " Resistance based on (referencePressure)/flowRateInlet at this point would be: " << resistanceRef << std::endl;
3952 std::cout << " --------------------------------------------------------- " << std::endl;
3953 std::cout << " --------------------------------------------------------- " << std::endl;
3954
3955 }
3956
3957 double flowRateUse = flowRateOutlet;
3958 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
3959 flowRateUse = flowRateOutletAveraged;
3960
3961 if(isNeg==1)
3962 flowRateUse = 0.;
3963
3964 double p_out = flowRateUse*valueFunc[0];
3965
3966 // Second step: use flow rate to determine pressure with resistance
3967 for (UN T=0; T<elements->numberElements(); T++) {
3968 FiniteElement fe = elements->getElement( T );
3969 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
3970 for (int surface=0; surface<fe.numSubElements(); surface++) {
3971 FiniteElement feSub = subEl->getElement( surface );
3972 if(subEl->getDimension() == dim-1 ){
3973
3974 // We only need to compute it on the outlet of the geometry
3975 if(feSub.getFlag() == flagOutlet){
3976 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
3977 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
3978 int numNodes_T = nodeList.size();
3979 vec_dbl_Type solution_u = this->getSolution(nodeList, u_rep,dim);
3980 vec2D_dbl_Type nodes;
3981 nodes = this->getCoordinates(nodeList, pointsRep);
3982
3983 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
3984
3985 double norm_v_E = 1.;
3986 if(dim==2){
3987 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3988 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
3989 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
3990
3991 }
3992 else if(dim==3){
3993
3994 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
3995 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
3996 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
3997
3998 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
3999 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
4000 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
4001
4002 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
4003 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
4004 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
4005
4006 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
4007 }
4008
4009 // vec_dbl_Type x(dim,0.); //dummy
4010 // paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
4011
4012 // func( &x[0], &valueFunc[0], paramsFunc);
4013 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
4014 // Step 1: Quadrature Points on physical surface:
4015 vec_dbl_Type quadWeights(dim);
4016 quadWeights[0] = 1/6.;
4017 quadWeights[1] = 1/6.;
4018 quadWeights[2] = 1/6.;
4019 vec2D_dbl_Type quadPoints(quadWeights.size(), vec_dbl_Type(dim));
4020
4021 vec_int_Type kn1= elements->getElement(T).getVectorNodeListNonConst();
4022
4023 vec2D_dbl_Type quadPointsT1(quadWeights.size(),vec_dbl_Type(dim));
4024 quadPointsT1.push_back({0.5,0.5,0.0});
4025 quadPointsT1.push_back({0.0,0.5,0.0});
4026 quadPointsT1.push_back({0.5,0.0,0.0});
4027
4028 SC detB1;
4029 SC absDetB1;
4030 SmallMatrix<SC> B1(dim);
4031 SmallMatrix<SC> Binv1(dim);
4032 int index0,index;
4033
4034 index0 = kn1[0];
4035 for (int s=0; s<dim; s++) {
4036 index = kn1[s+1];
4037 for (int t=0; t<dim; t++) {
4038 B1[t][s] = pointsRep->at(index).at(t) -pointsRep->at(index0).at(t);
4039 }
4040 }
4041
4042 detB1 = B1.computeInverse(Binv1);
4043 detB1 = std::fabs(detB1);
4044
4045 // Resulting Quad Points allways (0.5,0,0) (0.5,0.5,0) (0,0.5,0)
4046 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
4047 elScaling = B.computeScaling( );
4048
4049 //cout <<std::endl;
4050
4051 for (UN i=0; i < numNodes_T; i++) {
4052
4053 // 2.
4054 Teuchos::Array<SC> value(0);
4055 value.resize( dim, 0. );
4056 // loop over basis functions quadrature points
4057 for (UN w=0; w<phi->size(); w++) {
4058 for (int d=0; d<dim; d++){
4059 value[d] += weights->at(w) *normalScale*v_E[d]/norm_v_E *flowRateUse*valueFunc[0]*(*phi)[w][i];//valueFunc[0]
4060 }
4061 }
4062
4063 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
4064 for (int d=0; d<dim; d++)
4065 valuesF[ dim * nodeList[ i ] + d ] += value[d] * elScaling;
4066 }
4067
4068 // We make the distinction between a gradient jump calculation or a simple jump calculation
4069 vec_dbl_Type valueSecondComp(dim,0.);
4070
4071 for (UN t=0; t < numNodes_T; t++) {
4072 Teuchos::Array<SC> value( dim, 0. ); //These are value (W_ix,W_iy,W_iz)
4073 for(int l=0; l< quadWeights.size(); l++){
4074 vec_dbl_Type deriPhi1( dim,0.0) ;
4075 vec_dbl_ptr_Type valuePhi(new vec_dbl_Type(dim,0.0));
4076
4077 auto it1 = find( kn1.begin(), kn1.end() ,nodeList[t] );
4078 int id_in_element = distance( kn1.begin() , it1 );
4079
4080 Helper::gradPhi(dim,2,id_in_element,quadPointsT1[l],valuePhi);
4081 for (int j=0; j<3; j++) {
4082 deriPhi1[j] = valuePhi->at(j);
4083 }
4084
4085 vec_dbl_Type deriPhiT1(dim,0.);
4086 for(int q=0; q<dim; q++){
4087 for(int s=0; s< dim ; s++)
4088 deriPhiT1[q] += (deriPhi1[s]*Binv1[s][q]);
4089
4090 }
4091 // Phi might have other quad points
4092 for (UN d=0; d<dim; d++) {
4093 value[d] += quadWeights[l] *solution_u[t*dim+d] * deriPhi1[d]* v_E[d]/norm_v_E * (*phi)[l][t];
4094 }
4095 }
4096 // cout << " Value Second component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
4097 for (int j=0; j<value.size(); j++)
4098 valuesF[ dim * nodeList[ t ] + j ] -= normalScale*value[j] *elScaling*viscosity;
4099
4100 }
4101
4102
4103 }
4104
4105 }
4106 }
4107 }
4108 return p_out;
4109}
4110
4111
4112template <class SC, class LO, class GO, class NO>
4113void FE<SC,LO,GO,NO>::assemblyArea(int dim,
4114 double &area,
4115 int inflowFlag,
4116 int FEloc){
4117
4118 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
4119
4120 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
4121
4122 int inletFlag=inflowFlag; //params->sublist("Parameter Fluid").get("Fluid Flag",4);
4123
4124 double areaSurface=0.;
4125
4126 // Step 0: determie flowrate on inlet to calculate resistance
4127 for (UN T=0; T<elements->numberElements(); T++) {
4128 FiniteElement fe = elements->getElement( T );
4129 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
4130 for (int surface=0; surface<fe.numSubElements(); surface++) {
4131 FiniteElement feSub = subEl->getElement( surface );
4132 if(subEl->getDimension() == dim-1 ){
4133 if(feSub.getFlag() == inletFlag){
4134 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
4135 int numNodes_T = nodeList.size();
4136 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
4137
4138 double norm_v_E = 1.;
4139 if(dim==2){
4140 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
4141 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
4142 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
4143 areaSurface += norm_v_E;
4144
4145 }
4146 else if(dim==3){
4147
4148 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
4149 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
4150 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
4151
4152 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
4153 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
4154 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
4155
4156 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
4157 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
4158 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
4159
4160 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
4161
4162 // A = norm_v_E * 0.5
4163 areaSurface += norm_v_E*0.5;
4164
4165
4166 }
4167
4168
4169
4170 }
4171
4172
4173 }
4174 }
4175 }
4176 reduceAll<int, double> (*this->domainVec_.at(0)->getComm(), REDUCE_SUM, areaSurface, outArg (areaSurface));
4177
4178 area = areaSurface;
4179
4180}
4181
4182template <class SC, class LO, class GO, class NO>
4183int FE<SC,LO,GO,NO>::assemblyFlowRate(int dim,
4184 double &flowRateParabolic,
4185 std::string FEType,
4186 int dofs,
4187 int inflowFlag,
4188 MultiVectorPtr_Type solution_rep,
4189 int FEloc){
4190
4191 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
4192
4193 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
4194
4195 vec2D_dbl_ptr_Type phi;
4196
4197 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4198
4199 Helper::getPhi(phi, weights, dim-1, FEType, 2);
4200
4201 vec2D_dbl_ptr_Type quadPoints;
4202 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
4203 Helper::getQuadratureValues(dim-1, 2, quadPoints, w, FEType);
4204 w.reset();
4205
4206 int inletFlag=inflowFlag; //params->sublist("Parameter Fluid").get("Fluid Flag",4);
4207
4208
4209 SC elScaling;
4210 vec_dbl_Type b(dim);
4211 SmallMatrix<SC> B(dim);
4212 SmallMatrix<SC> Binv(dim);
4213 SC detB;
4214 SC absDetB;
4215
4216 double flowRateInlet=0.;
4217
4218 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
4219
4220 Teuchos::ArrayRCP< const SC > uArray = solution_rep->getData(0);
4221 // Step 0: determie flowrate on inlet to calculate resistance
4222 for (UN T=0; T<elements->numberElements(); T++) {
4223 FiniteElement fe = elements->getElement( T );
4224 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
4225 for (int surface=0; surface<fe.numSubElements(); surface++) {
4226 FiniteElement feSub = subEl->getElement( surface );
4227 if(subEl->getDimension() == dim-1 ){
4228 if(feSub.getFlag() == inletFlag){
4229 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
4230 int numNodes_T = nodeList.size();
4231 vec_dbl_Type solution_u = this->getSolution(nodeList, solution_rep,dofs);
4232
4233
4234 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
4235
4236 double norm_v_E = 1.;
4237 if(dim==2){
4238 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
4239 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
4240 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
4241
4242 }
4243 else if(dim==3){
4244
4245 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
4246 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
4247 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
4248
4249 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
4250 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
4251 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
4252
4253 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
4254 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
4255 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
4256
4257 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
4258
4259 // cout << " Normal Vector " << v_E[0] << " " << v_E[1] << " "<< v_E[2] <<std::endl;
4260 }
4261
4262 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
4263 // Step 1: Quadrature Points on physical surface:
4264 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
4265 elScaling = B.computeScaling( );
4266
4267 Teuchos::Array<SC> value(0);
4268 value.resize( numNodes_T, 0. ); // Volumetric flow rate over one surface is a skalar value
4269 // //cout << " Velocity over node ";
4270 // for (int w=0; w<phi->size(); w++){ //quads points
4271 // for (int d=0; d<dim; d++) {
4272 // uLoc[d][w] = 0.;
4273 // for (int i=0; i < phi->at(0).size(); i++) {
4274 // LO index = dim * nodeList[i] + d;
4275 // uLoc[d][w] += uArray[index] * phi->at(w).at(i);
4276 // }
4277 // }
4278 // }
4279
4280 for (UN i=0; i < numNodes_T; i++) {
4281 // loop over basis functions quadrature points
4282 for (UN w=0; w<phi->size(); w++) {
4283 for (int j=0; j<dim; j++){
4284 if(dofs==1){
4285 value[i] += weights->at(w) *v_E[j]/norm_v_E *solution_u[i]*(*phi)[w][i]; // valueFunc[0]* = 1.0
4286 }
4287 else{
4288 LO index = dim * i + j;
4289 value[i] += weights->at(w) *v_E[j]/norm_v_E *solution_u[index]*(*phi)[w][i]; // valueFunc[0]* = 1.0
4290 }
4291
4292 }
4293 }
4294 flowRateInlet += value[i] * elScaling;
4295
4296 }
4297 }
4298
4299
4300 }
4301 }
4302 }
4303 reduceAll<int, double> (*this->domainVec_.at(0)->getComm(), REDUCE_SUM, flowRateInlet, outArg (flowRateInlet));
4304 // if(flowRateInlet < 0 && this->domainVec_.at(0)->getComm()->getRank() == 0)
4305 // std::cout << " ###### WARNING: the flow rate you computed is negative. Either the surface normal has the wrong orientation, or your solution is negative. Or both :D. Flowrate:"<< flowRateInlet << " ####### " <<std::endl;
4306 int isNeg=0;
4307
4308 if(flowRateInlet <0)
4309 isNeg = 1;
4310 flowRateParabolic = fabs(flowRateInlet);
4311
4312 return isNeg;
4313
4314}
4315
4316
4317template <class SC, class LO, class GO, class NO>
4318void FE<SC,LO,GO,NO>::assemblyAverageVelocity(int dim,
4319 double &averageVelocity,
4320 std::string FEType,
4321 int dofs,
4322 int flag,
4323 MultiVectorPtr_Type solution_rep,
4324 int FEloc){
4325
4326 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
4327
4328 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
4329
4330 vec2D_dbl_ptr_Type phi;
4331
4332 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4333
4334 Helper::getPhi(phi, weights, dim-1, FEType, 2);
4335
4336 vec2D_dbl_ptr_Type quadPoints;
4337 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
4338 Helper::getQuadratureValues(dim-1, 2, quadPoints, w, FEType);
4339 w.reset();
4340
4341 double area =0.;
4342 this->assemblyArea(dim, area, flag);
4343
4344 SC elScaling;
4345 vec_dbl_Type b(dim);
4346 SmallMatrix<SC> B(dim);
4347 SmallMatrix<SC> Binv(dim);
4348 SC detB;
4349 SC absDetB;
4350
4351 double velocity=0.;
4352
4353 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
4354
4355 Teuchos::ArrayRCP< const SC > uArray = solution_rep->getData(0);
4356 // Step 0: determie flowrate on inlet to calculate resistance
4357 for (UN T=0; T<elements->numberElements(); T++) {
4358 FiniteElement fe = elements->getElement( T );
4359 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
4360 for(int surface=0; surface<fe.numSubElements(); surface++) {
4361 FiniteElement feSub = subEl->getElement( surface );
4362 if(subEl->getDimension() == dim-1 ){
4363 if(feSub.getFlag() == flag){
4364 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
4365 int numNodes_T = nodeList.size();
4366 vec_dbl_Type solution_u = this->getSolution(nodeList, solution_rep,dofs);
4367
4368 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
4369
4370 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
4371 // Step 1: Quadrature Points on physical surface:
4372 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
4373 elScaling = B.computeScaling( );
4374
4375 Teuchos::Array<SC> value(0);
4376 value.resize( numNodes_T, 0. ); // Volumetric flow rate over one surface is a skalar value
4377
4378 for (UN i=0; i < numNodes_T; i++) {
4379 // loop over basis functions quadrature points
4380 for (UN w=0; w<phi->size(); w++) {
4381 for (int j=0; j<dim; j++){
4382 if(dofs==1){
4383 value[i] += weights->at(w)*solution_u[i]*(*phi)[w][i]; // valueFunc[0]* = 1.0
4384 }
4385 else{
4386 LO index = dim * i + j;
4387 value[i] += weights->at(w)*solution_u[index]*(*phi)[w][i]; // valueFunc[0]* = 1.0
4388 }
4389
4390 }
4391 }
4392 velocity += value[i] * elScaling;
4393 }
4394 }
4395 }
4396 }
4397 }
4398 reduceAll<int, double> (*this->domainVec_.at(0)->getComm(), REDUCE_SUM, velocity, outArg (velocity));
4399 velocity = velocity/area;
4400 std::cout << " Average Flowvelocity "<< velocity << " ####### " <<std::endl;
4401
4402 averageVelocity = velocity;
4403}
4404
4405
4406
4407template <class SC, class LO, class GO, class NO>
4409 std::string FEType,
4410 MatrixPtr_Type &A,
4411 double lambda,
4412 double mu,
4413 bool callFillComplete)
4414{
4415 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4416 int FEloc = this->checkFE(dim,FEType);
4417
4418 // Get elements and node lists
4419 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
4420 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
4421 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
4422
4423 vec3D_dbl_ptr_Type dPhi;
4424 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4425 vec2D_dbl_ptr_Type quadPts;
4426
4427 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4428
4429 // Get gradient(phi)
4430 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4431 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4432
4433 // Define basisfunctions \phi_i and \phi_j
4434 // vec_dbl_Type basisValues_i(dim,0.), basisValues_j(dim,0.);
4435
4436 // SC = double, GO = long, UN = int
4437 SC detB;
4438 SC absDetB;
4439 SmallMatrix<SC> B(dim);
4440 SmallMatrix<SC> Binv(dim);
4441 GO glob_i, glob_j;
4442
4443 // for intermediate results
4444 SC res;
4445
4446 // for the computation of the trace
4447 double res_trace_i, res_trace_j;
4448
4449 if (dim == 2)
4450 {
4451
4452 double v11, v12, v21, v22;
4453 // Initialize vectors of size 2 with 0.0 (double)
4454 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
4455
4456 // Matrices of size 2x2, in which the individual epsilon tensors are computed; see below for more.
4457 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
4458 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
4459
4460 for (int T = 0; T < elements->numberElements(); T++)
4461 {
4462 // Get vertices of the triangle
4463 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4464 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4465 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4466
4467 // Compute transformation matrix B for the respective element (2D)
4468 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
4469 detB = B.computeInverse(Binv);
4470 absDetB = std::fabs(detB);
4471
4472 // dPhiTrans are the transformed basisfunctions, i.e., B^(-T) * \grad_phi and \grad_phi^T * B^(-1).
4473 // So \hat{grad_phi}.
4474 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4475 applyBTinv( dPhi, dPhiTrans, Binv ); // compute dPhiTrans
4476
4477 for (int i = 0; i < dPhi->at(0).size(); i++)
4478 {
4479 Teuchos::Array<SC> value11( 1, 0. );
4480 Teuchos::Array<SC> value12( 1, 0. );
4481 Teuchos::Array<SC> value21( 1, 0. );
4482 Teuchos::Array<SC> value22( 1, 0. );
4483 Teuchos::Array<GO> indices( 1, 0 );
4484
4485 for (int j = 0; j < dPhi->at(0).size(); j++)
4486 {
4487 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
4488 for (int k = 0; k < dPhi->size(); k++)
4489 {
4490 // In epsilonValuesMat1_i (2x2 matrix), epsilonTensor is contained for a scalar shape function for the direction 1 (cf. Mat1)
4491 // corresponding to shape function i, i.e., \phi_i.
4492 // Thus, in Mat1_i we have \eps of phi_i = (phi_scalar_i, 0).
4493
4494 // Compute \hat{grad_phi_i} = basisValues_i, i.e., B^(-T)*grad_phi_i
4495 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
4496
4497 // \eps(v) = \eps(phi_i)
4498 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x direction
4499 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y direction
4500
4501 // See above, here carried out for j
4502 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4503
4504 // \eps(u) = \eps(phi_j)
4505 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x direction
4506 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y direction
4507
4508 // Now we compute \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
4509 // The result wil be stored in res.
4510 // Compute the trace of the epsilon tensors tr(\eps(u)) (j) and tr(\eps(v)) (i)
4511 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
4512 epsilonValuesMat1_i.trace(res_trace_i);
4513 epsilonValuesMat1_j.trace(res_trace_j);
4514 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4515
4516 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
4517 epsilonValuesMat1_i.trace(res_trace_i);
4518 epsilonValuesMat2_j.trace(res_trace_j);
4519 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4520
4521 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
4522 epsilonValuesMat2_i.trace(res_trace_i);
4523 epsilonValuesMat1_j.trace(res_trace_j);
4524 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4525
4526 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
4527 epsilonValuesMat2_i.trace(res_trace_i);
4528 epsilonValuesMat2_j.trace(res_trace_j);
4529 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4530
4531
4532 }
4533 // Scale with abs(det(B))
4534 v11 = absDetB * v11;
4535 v12 = absDetB * v12;
4536 v21 = absDetB * v21;
4537 v22 = absDetB * v22;
4538
4539 value11[0] = v11;
4540 value12[0] = v12;
4541 value21[0] = v21;
4542 value22[0] = v22;
4543
4544 // Get the global row and column to which the entries need to be written.
4545 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4546 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4547 indices[0] = glob_j;
4548 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
4549 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
4550 glob_j++;
4551 indices[0] = glob_j;
4552 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
4553 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
4554 }
4555 }
4556 }
4557 if (callFillComplete)
4558 {
4559 A->fillComplete();
4560 }
4561 }
4562 else if(dim == 3)
4563 {
4564
4565 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
4566
4567 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4568 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
4569 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
4570
4571 for (int T = 0; T < elements->numberElements(); T++)
4572 {
4573 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4574 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4575 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4576 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4577
4578 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4579 detB = B.computeInverse(Binv);
4580 absDetB = std::fabs(detB);
4581
4582 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4583 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4584 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4585
4586 for (int i = 0; i < dPhi->at(0).size(); i++)
4587 {
4588 Teuchos::Array<SC> value11( 1, 0. );
4589 Teuchos::Array<SC> value12( 1, 0. );
4590 Teuchos::Array<SC> value13( 1, 0. );
4591 Teuchos::Array<SC> value21( 1, 0. );
4592 Teuchos::Array<SC> value22( 1, 0. );
4593 Teuchos::Array<SC> value23( 1, 0. );
4594 Teuchos::Array<SC> value31( 1, 0. );
4595 Teuchos::Array<SC> value32( 1, 0. );
4596 Teuchos::Array<SC> value33( 1, 0. );
4597 Teuchos::Array<GO> indices( 1, 0 );
4598
4599 for (int j = 0; j < dPhi->at(0).size(); j++)
4600 {
4601 v11 = 0.0; v12 = 0.0; v13 = 0.0; v21 = 0.0; v22 = 0.0; v23 = 0.0; v31 = 0.0; v32 = 0.0; v33 = 0.0;
4602 for (int k = 0; k < dPhi->size(); k++)
4603 {
4604
4605 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
4606
4607 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
4608 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
4609 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
4610
4611
4612 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4613
4614 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
4615 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
4616 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
4617
4618 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
4619 epsilonValuesMat1_i.trace(res_trace_i);
4620 epsilonValuesMat1_j.trace(res_trace_j);
4621 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4622
4623 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
4624 epsilonValuesMat1_i.trace(res_trace_i);
4625 epsilonValuesMat2_j.trace(res_trace_j);
4626 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4627
4628 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
4629 epsilonValuesMat1_i.trace(res_trace_i);
4630 epsilonValuesMat3_j.trace(res_trace_j);
4631 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4632
4633 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
4634 epsilonValuesMat2_i.trace(res_trace_i);
4635 epsilonValuesMat1_j.trace(res_trace_j);
4636 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4637
4638 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
4639 epsilonValuesMat2_i.trace(res_trace_i);
4640 epsilonValuesMat2_j.trace(res_trace_j);
4641 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4642
4643 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
4644 epsilonValuesMat2_i.trace(res_trace_i);
4645 epsilonValuesMat3_j.trace(res_trace_j);
4646 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4647
4648 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
4649 epsilonValuesMat3_i.trace(res_trace_i);
4650 epsilonValuesMat1_j.trace(res_trace_j);
4651 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4652
4653 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
4654 epsilonValuesMat3_i.trace(res_trace_i);
4655 epsilonValuesMat2_j.trace(res_trace_j);
4656 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4657
4658 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
4659 epsilonValuesMat3_i.trace(res_trace_i);
4660 epsilonValuesMat3_j.trace(res_trace_j);
4661 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4662
4663 }
4664 v11 = absDetB * v11;
4665 v12 = absDetB * v12;
4666 v13 = absDetB * v13;
4667 v21 = absDetB * v21;
4668 v22 = absDetB * v22;
4669 v23 = absDetB * v23;
4670 v31 = absDetB * v31;
4671 v32 = absDetB * v32;
4672 v33 = absDetB * v33;
4673
4674 value11[0] = v11;
4675 value12[0] = v12;
4676 value13[0] = v13;
4677 value21[0] = v21;
4678 value22[0] = v22;
4679 value23[0] = v23;
4680 value31[0] = v31;
4681 value32[0] = v32;
4682 value33[0] = v33;
4683
4684 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4685 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4686 indices[0] = glob_j;
4687 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
4688 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
4689 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
4690 glob_j++;
4691 indices[0] = glob_j;
4692 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
4693 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
4694 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
4695 glob_j++;
4696 indices[0] = glob_j;
4697 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
4698 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
4699 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
4700 }
4701 }
4702 }
4703 if (callFillComplete)
4704 {
4705 A->fillComplete();
4706 }
4707 }
4708}
4709
4710// Determine the change of emodule depending on concentration
4711template <class SC, class LO, class GO, class NO>
4712void FE<SC,LO,GO,NO>::determineEMod(std::string FEType, MultiVectorPtr_Type solution,MultiVectorPtr_Type &eModVec, DomainConstPtr_Type domain, ParameterListPtr_Type params){
4713
4714
4715 ElementsPtr_Type elements = domain->getElementsC();
4716
4717 int dim = domain->getDimension();
4718 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
4719
4720 //MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
4721
4722 Teuchos::ArrayRCP< const SC > uArray = solution->getData(0);
4723 Teuchos::ArrayRCP< SC > eModVecA = eModVec->getDataNonConst(0);
4724
4725 double E0 = params->sublist("Parameter Solid").get("E",3.0e+6);
4726 double E1 = params->sublist("Parameter Solid").get("E1",3.0e+5);
4727 double c1 = params->sublist("Parameter Solid").get("c1",1.0);
4728 double eModMax =E1;
4729 double eModMin = E0;
4730
4731 int nodesElement = elements->getElement(0).getVectorNodeList().size();
4732 for (UN T=0; T<elements->numberElements(); T++) {
4733
4734 /*buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
4735 detB = B.computeInverse(Binv);
4736 absDetB = std::fabs(detB);*/
4737
4738 double uLoc = 0.;
4739
4740 for(int i=0; i< nodesElement;i++){
4741 LO index = elements->getElement(T).getNode(i) ;
4742 uLoc += 1./nodesElement*uArray[index];
4743 }
4744
4745 eModVecA[T] = E0-(E0-E1)*(uLoc/(uLoc+c1));
4746 if(eModVecA[T] > eModMax )
4747 eModMax = eModVecA[T];
4748 if(eModVecA[T] < eModMin)
4749 eModMin = eModVecA[T];
4750 }
4751 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MIN, eModMin, Teuchos::outArg (eModMin));
4752 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MAX, eModMax, Teuchos::outArg (eModMax));
4753
4754 if(domain->getComm()->getRank()==0)
4755 std::cout << " ################# eMOD Min: " << eModMin << " \t eModMax: " << eModMax<< " ############# " << std::endl;
4756
4757
4758}
4759
4760
4762template <class SC, class LO, class GO, class NO>
4764 std::string FEType,
4765 MatrixPtr_Type &A,
4766 MultiVectorPtr_Type eModVec,
4767 double nu,
4768 bool callFillComplete)
4769{
4770 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4771 int FEloc = this->checkFE(dim,FEType);
4772
4773 // Get elements and node lists
4774 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
4775 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
4776 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
4777
4778 vec3D_dbl_ptr_Type dPhi;
4779 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4780 vec2D_dbl_ptr_Type quadPts;
4781
4782 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4783
4784 // Get gradient(phi)
4785 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4786 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4787
4788 SC detB;
4789 SC absDetB;
4790 SmallMatrix<SC> B(dim);
4791 SmallMatrix<SC> Binv(dim);
4792 GO glob_i, glob_j;
4793
4794 // for intermediate results
4795 SC res;
4796
4797 // for the computation of the trace
4798 double res_trace_i, res_trace_j;
4799
4800 Teuchos::ArrayRCP< const SC > E = eModVec->getData(0);
4801 double lambda;
4802 double mu ;
4803
4804 if (dim == 2)
4805 {
4806
4807 double v11, v12, v21, v22;
4808 // Initialize vectors of size 2 with 0.0 (double)
4809 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
4810
4811 // Matrices of size 2x2, in which the individual epsilon tensors are computed; see below for more.
4812 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
4813 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
4814
4815 for (int T = 0; T < elements->numberElements(); T++)
4816 {
4818 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
4819 mu = E[T] / (2.*(1.+nu));
4820
4821 // Get vertices of the triangle
4822 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4823 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4824 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4825
4826 // Compute transformation matrix B for the respective element (2D)
4827 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
4828 detB = B.computeInverse(Binv);
4829 absDetB = std::fabs(detB);
4830
4831 // dPhiTrans are the transformed basisfunctions, i.e., B^(-T) * \grad_phi and \grad_phi^T * B^(-1).
4832 // So \hat{grad_phi}.
4833 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4834 applyBTinv( dPhi, dPhiTrans, Binv ); // compute dPhiTrans
4835
4836 for (int i = 0; i < dPhi->at(0).size(); i++)
4837 {
4838 Teuchos::Array<SC> value11( 1, 0. );
4839 Teuchos::Array<SC> value12( 1, 0. );
4840 Teuchos::Array<SC> value21( 1, 0. );
4841 Teuchos::Array<SC> value22( 1, 0. );
4842 Teuchos::Array<GO> indices( 1, 0 );
4843
4844 for (int j = 0; j < dPhi->at(0).size(); j++)
4845 {
4846 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
4847 for (int k = 0; k < dPhi->size(); k++)
4848 {
4849 // In epsilonValuesMat1_i (2x2 matrix), epsilonTensor is contained for a scalar shape function for the direction 1 (cf. Mat1)
4850 // corresponding to shape function i, i.e., \phi_i.
4851 // Thus, in Mat1_i we have \eps of phi_i = (phi_scalar_i, 0).
4852
4853 // Compute \hat{grad_phi_i} = basisValues_i, i.e., B^(-T)*grad_phi_i
4854 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
4855
4856 // \eps(v) = \eps(phi_i)
4857 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x direction
4858 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y direction
4859
4860 // See above, here carried out for j
4861 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4862
4863 // \eps(u) = \eps(phi_j)
4864 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x direction
4865 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y direction
4866
4867 // Now we compute \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
4868 // The result wil be stored in res.
4869 // Compute the trace of the epsilon tensors tr(\eps(u)) (j) and tr(\eps(v)) (i)
4870 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
4871 epsilonValuesMat1_i.trace(res_trace_i);
4872 epsilonValuesMat1_j.trace(res_trace_j);
4873 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4874
4875 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
4876 epsilonValuesMat1_i.trace(res_trace_i);
4877 epsilonValuesMat2_j.trace(res_trace_j);
4878 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4879
4880 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
4881 epsilonValuesMat2_i.trace(res_trace_i);
4882 epsilonValuesMat1_j.trace(res_trace_j);
4883 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4884
4885 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
4886 epsilonValuesMat2_i.trace(res_trace_i);
4887 epsilonValuesMat2_j.trace(res_trace_j);
4888 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4889
4890
4891 }
4892 // Scale with abs(det(B))
4893 v11 = absDetB * v11;
4894 v12 = absDetB * v12;
4895 v21 = absDetB * v21;
4896 v22 = absDetB * v22;
4897
4898 value11[0] = v11;
4899 value12[0] = v12;
4900 value21[0] = v21;
4901 value22[0] = v22;
4902
4903 // Get the global row and column to which the entries need to be written.
4904 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4905 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4906 indices[0] = glob_j;
4907 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
4908 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
4909 glob_j++;
4910 indices[0] = glob_j;
4911 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
4912 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
4913 }
4914 }
4915 }
4916 if (callFillComplete)
4917 {
4918 A->fillComplete();
4919 }
4920 }
4921 else if(dim == 3)
4922 {
4923
4924 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
4925
4926 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4927 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
4928 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
4929
4930 for (int T = 0; T < elements->numberElements(); T++)
4931 {
4932 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
4933 mu = E[T] / (2.*(1.+nu));
4934
4935 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4936 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4937 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4938 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4939
4940 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4941 detB = B.computeInverse(Binv);
4942 absDetB = std::fabs(detB);
4943
4944 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4945 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4946 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4947
4948 for (int i = 0; i < dPhi->at(0).size(); i++)
4949 {
4950
4951 Teuchos::Array<SC> value11( 1, 0. );
4952 Teuchos::Array<SC> value12( 1, 0. );
4953 Teuchos::Array<SC> value13( 1, 0. );
4954 Teuchos::Array<SC> value21( 1, 0. );
4955 Teuchos::Array<SC> value22( 1, 0. );
4956 Teuchos::Array<SC> value23( 1, 0. );
4957 Teuchos::Array<SC> value31( 1, 0. );
4958 Teuchos::Array<SC> value32( 1, 0. );
4959 Teuchos::Array<SC> value33( 1, 0. );
4960 Teuchos::Array<GO> indices( 1, 0 );
4961
4962 for (int j = 0; j < dPhi->at(0).size(); j++)
4963 {
4964 v11 = 0.0; v12 = 0.0; v13 = 0.0; v21 = 0.0; v22 = 0.0; v23 = 0.0; v31 = 0.0; v32 = 0.0; v33 = 0.0;
4965 for (int k = 0; k < dPhi->size(); k++)
4966 {
4967
4968 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
4969
4970 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
4971 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
4972 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
4973
4974
4975 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4976
4977 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
4978 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
4979 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
4980
4981 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
4982 epsilonValuesMat1_i.trace(res_trace_i);
4983 epsilonValuesMat1_j.trace(res_trace_j);
4984 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4985
4986 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
4987 epsilonValuesMat1_i.trace(res_trace_i);
4988 epsilonValuesMat2_j.trace(res_trace_j);
4989 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4990
4991 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
4992 epsilonValuesMat1_i.trace(res_trace_i);
4993 epsilonValuesMat3_j.trace(res_trace_j);
4994 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4995
4996 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
4997 epsilonValuesMat2_i.trace(res_trace_i);
4998 epsilonValuesMat1_j.trace(res_trace_j);
4999 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5000
5001 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5002 epsilonValuesMat2_i.trace(res_trace_i);
5003 epsilonValuesMat2_j.trace(res_trace_j);
5004 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5005
5006 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
5007 epsilonValuesMat2_i.trace(res_trace_i);
5008 epsilonValuesMat3_j.trace(res_trace_j);
5009 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5010
5011 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
5012 epsilonValuesMat3_i.trace(res_trace_i);
5013 epsilonValuesMat1_j.trace(res_trace_j);
5014 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5015
5016 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
5017 epsilonValuesMat3_i.trace(res_trace_i);
5018 epsilonValuesMat2_j.trace(res_trace_j);
5019 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5020
5021 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
5022 epsilonValuesMat3_i.trace(res_trace_i);
5023 epsilonValuesMat3_j.trace(res_trace_j);
5024 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5025
5026 }
5027 v11 = absDetB * v11;
5028 v12 = absDetB * v12;
5029 v13 = absDetB * v13;
5030 v21 = absDetB * v21;
5031 v22 = absDetB * v22;
5032 v23 = absDetB * v23;
5033 v31 = absDetB * v31;
5034 v32 = absDetB * v32;
5035 v33 = absDetB * v33;
5036
5037 value11[0] = v11;
5038 value12[0] = v12;
5039 value13[0] = v13;
5040 value21[0] = v21;
5041 value22[0] = v22;
5042 value23[0] = v23;
5043 value31[0] = v31;
5044 value32[0] = v32;
5045 value33[0] = v33;
5046
5047 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5048 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5049 indices[0] = glob_j;
5050 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5051 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5052 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
5053 glob_j++;
5054 indices[0] = glob_j;
5055 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5056 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5057 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
5058 glob_j++;
5059 indices[0] = glob_j;
5060 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
5061 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
5062 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
5063 }
5064 }
5065 }
5066 if (callFillComplete)
5067 {
5068 A->fillComplete();
5069 }
5070 }
5071}
5072
5074template <class SC, class LO, class GO, class NO>
5076 std::string FEType,
5077 MatrixPtr_Type &A,
5078 MultiVectorPtr_Type w,
5079 bool callFillComplete)
5080{
5081
5082 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
5083 int FEloc = this->checkFE(dim,FEType);
5084
5085 DomainConstPtr_Type domain = this->domainVec_.at(FEloc);
5086 ElementsPtr_Type elements = domain->getElementsC();
5087 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5088 MapConstPtr_Type map = domain->getMapRepeated();
5089
5090 vec3D_dbl_ptr_Type dPhi;
5091 vec2D_dbl_ptr_Type phi;
5092 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5093 vec2D_dbl_ptr_Type quadPts;
5094
5095 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); // Fuer diskretes (\grad \cdot w) in den Gausspuntken
5096 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
5097
5098 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
5099 Helper::getPhi(phi, weights, dim, FEType, deg);
5100 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType);
5101
5102 // SC = double, GO = long, UN = int
5103 SC detB;
5104 SC absDetB;
5105 SmallMatrix<SC> B(dim);
5106 SmallMatrix<SC> Binv(dim);
5107 GO glob_i, glob_j;
5108
5109 // Der nichtlineare Teil als Array
5110 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
5111
5112 if (dim == 2)
5113 {
5114 double val;
5115 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
5116
5117 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
5118 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5119 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
5120
5121 for (int T = 0; T < elements->numberElements(); T++)
5122 {
5123 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5124 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5125 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5126
5127 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5128 detB = B.computeInverse(Binv);
5129 absDetB = std::fabs(detB);
5130
5131 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5132 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5133 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5134
5135 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 berechnen,
5136 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
5137 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5138 {
5139 w11[0][k] = 0.0;
5140 w22[0][k] = 0.0;
5141 for(int i = 0; i < dPhiTrans[0].size(); i++)
5142 {
5143 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5144 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5145 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
5146 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
5147
5148 // TEST
5149 // LO indexTest1 = dim * i + 0;
5150 // LO indexTest2 = dim * i + 1;
5151 // w11[0][k] += wTest[indexTest1] * dPhiTrans[k][i][0];
5152 // w22[0][k] += wTest[indexTest2] * dPhiTrans[k][i][1];
5153 }
5154 }
5155
5156 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5157 {
5158 divergenz[0][k] = w11[0][k] + w22[0][k];
5159 // if(T == 0)
5160 // {
5161 // std::cout << "k: " << k << " Divergenz: " << divergenz[0][k] << '\n';
5162 // }
5163 }
5164
5165
5166 for (int i = 0; i < dPhi->at(0).size(); i++)
5167 {
5168 Teuchos::Array<SC> value( 1, 0. );
5169 Teuchos::Array<GO> indices( 1, 0 );
5170
5171 for (int j = 0; j < dPhi->at(0).size(); j++)
5172 {
5173 val = 0.0;
5174 for (int k = 0; k < dPhi->size(); k++)
5175 {
5176 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
5177 }
5178 val = absDetB * val;
5179 value[0] = val;
5180
5181 // if(T == 0)
5182 // {
5183 // std::cout << "i: " << i << " j: " << j << " val: " << val << '\n';
5184 // }
5185
5186 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5187 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5188 indices[0] = glob_j;
5189
5190 A->insertGlobalValues(glob_i, indices(), value());
5191 glob_j++;
5192 indices[0] = glob_j;
5193 A->insertGlobalValues(glob_i+1, indices(), value());
5194 }
5195 }
5196 }
5197 if (callFillComplete)
5198 {
5199 A->fillComplete();
5200 }
5201 }
5202 else if(dim == 3)
5203 {
5204 double val;
5205
5206 // long long glob_i, glob_j;
5207 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
5208
5209 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
5210 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5211 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
5212 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
5213
5214 for (int T = 0; T < elements->numberElements(); T++)
5215 {
5216 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5217 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5218 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5219 p4 = pointsRep->at(elements->getElement(T).getNode(3));
5220
5221 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5222 detB = B.computeInverse(Binv);
5223 absDetB = std::fabs(detB);
5224
5225 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5226 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5227 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5228
5229 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 + w33 berechnen,
5230 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
5231 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5232 {
5233 w11[0][k] = 0.0;
5234 w22[0][k] = 0.0;
5235 w33[0][k] = 0.0;
5236 for(int i = 0; i < dPhiTrans[0].size(); i++)
5237 {
5238 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5239 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5240 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
5241 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
5242 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
5243 w33[0][k] += wArray[index3] * dPhiTrans[k][i][2];
5244 }
5245 }
5246
5247 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5248 {
5249 divergenz[0][k] = w11[0][k] + w22[0][k] + w33[0][k];
5250 }
5251
5252 for (int i = 0; i < dPhi->at(0).size(); i++)
5253 {
5254 Teuchos::Array<SC> value( 1, 0. );
5255 Teuchos::Array<GO> indices( 1, 0 );
5256
5257 for (int j = 0; j < dPhi->at(0).size(); j++)
5258 {
5259 val = 0.0;
5260 for (int k = 0; k < dPhi->size(); k++)
5261 {
5262 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
5263 }
5264 val = absDetB * val;
5265 value[0] = val;
5266
5267 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5268 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5269 indices[0] = glob_j;
5270 A->insertGlobalValues(glob_i, indices(), value());
5271 glob_j++;
5272 indices[0] = glob_j;
5273 A->insertGlobalValues(glob_i+1, indices(), value());
5274 glob_j++;
5275 indices[0] = glob_j;
5276 A->insertGlobalValues(glob_i+2, indices(), value());
5277
5278 }
5279 }
5280 }
5281 if (callFillComplete)
5282 {
5283 A->fillComplete();
5284 }
5285 }
5286}
5287
5288template <class SC, class LO, class GO, class NO>
5289void FE<SC,LO,GO,NO>::assemblyDummyCoupling(int dim,
5290 std::string FEType,
5291 MatrixPtr_Type &C,
5292 int FEloc, // 0 = Fluid, 2 = Struktur
5293 bool callFillComplete)
5294{
5295 DomainConstPtr_Type domain = this->domainVec_.at(FEloc);
5296
5297 MapConstPtr_Type mapInterfaceVecField = domain->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
5298 MapConstPtr_Type mapGlobalInterfaceVecField = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
5299
5300 MapConstPtr_Type mapFieldPartial = domain->getGlobalInterfaceMapVecFieldPartial();
5301
5302 Teuchos::Array<SC> value( 1, 0. );
5303 value[0] = 1.0; // da Einheitsmatrix
5304 Teuchos::Array<GO> indices( 1, 0 );
5305
5306 GO dofGlobal, dofLocal;
5307
5308 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
5309 {
5310 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5311 if ( mapFieldPartial->getLocalElement( dofGlobal ) == Teuchos::OrdinalTraits<LO>::invalid() ) {
5312 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
5313 dofGlobal = mapInterfaceVecField->getGlobalElement( k );
5314 indices[0] = dofGlobal;
5315 C->insertGlobalValues(dofGlobal, indices(), value());
5316 }
5317 }
5318
5319 if (callFillComplete)
5320 C->fillComplete(mapInterfaceVecField, mapInterfaceVecField);
5321
5322}
5323
5324template <class SC, class LO, class GO, class NO>
5325void FE<SC,LO,GO,NO>::assemblyFSICoupling(int dim,
5326 std::string FEType,
5327 MatrixPtr_Type &C,
5328 MatrixPtr_Type &C_T,
5329 int FEloc1, // 0 = Fluid, 2 = Struktur
5330 int FEloc2, // 0 = Fluid, 2 = Struktur
5331 MapConstPtr_Type map1, // DomainMap: InterfaceMapVecFieldUnique = Spalten von C_T
5332 MapConstPtr_Type map2, // RangeMap: this->getDomain(0)->getMapVecFieldUnique() = Zeilen von C_T
5333 bool callFillComplete)
5334{
5335 // int FEloc = this->checkFE(dim,FEType);
5336
5337 DomainConstPtr_Type domain1 = this->domainVec_.at(FEloc1);
5338
5339 MapConstPtr_Type mapInterfaceVecField = domain1->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
5340
5341 MapConstPtr_Type mapGlobalInterfaceVecField;
5342 MapConstPtr_Type mapFieldPartial;
5343 if (FEloc1!=FEloc2){
5344 mapFieldPartial = domain1->getOtherGlobalInterfaceMapVecFieldPartial();
5345 mapGlobalInterfaceVecField = domain1->getOtherGlobalInterfaceMapVecFieldUnique();
5346 }
5347 else{
5348 mapFieldPartial = domain1->getGlobalInterfaceMapVecFieldPartial();
5349 mapGlobalInterfaceVecField = domain1->getGlobalInterfaceMapVecFieldUnique();
5350 }
5351
5352 Teuchos::Array<SC> value( 1, 0. );
5353 value[0] = 1.0; // da Einheitsmatrix
5354 Teuchos::Array<GO> indices( 1, 0 );
5355
5356 GO dofGlobal, dofLocal;
5357 if (mapFieldPartial.is_null()) {
5358 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
5359 {
5360 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
5361 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5362 dofLocal = mapInterfaceVecField->getGlobalElement(k);
5363
5364 indices[0] = dofLocal;
5365 C_T->insertGlobalValues(dofGlobal, indices(), value());
5366 indices[0] = dofGlobal;
5367 C->insertGlobalValues(dofLocal, indices(), value());
5368
5369 }
5370 }
5371 else{
5372 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++) {
5373 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5374 if ( mapFieldPartial->getLocalElement( dofGlobal ) != Teuchos::OrdinalTraits<LO>::invalid() ) {
5375
5376 dofLocal = mapInterfaceVecField->getGlobalElement(k);
5377
5378 indices[0] = dofLocal;
5379 C_T->insertGlobalValues(dofGlobal, indices(), value());
5380 indices[0] = dofGlobal;
5381 C->insertGlobalValues(dofLocal, indices(), value());
5382 }
5383 }
5384 }
5385
5386 if (callFillComplete)
5387 {
5388 // Erstes Argument: Domain (=Spalten von C_T)
5389 // Zweites Arguement: Range (=Zeilen von C_T)
5390 C_T->fillComplete(map1, map2);
5391 C->fillComplete(map2, map1);
5392 }
5393}
5394
5395
5396template <class SC, class LO, class GO, class NO>
5397void FE<SC,LO,GO,NO>::assemblyGeometryCoupling(int dim,
5398 std::string FEType,
5399 MatrixPtr_Type &C,
5400 int FEloc, // 0 = Fluid, 2 = Struktur, 4 = 0 = Geometrie
5401 MapConstPtr_Type map1, // Fluid-Interface-Map
5402 MapConstPtr_Type map2, // DomainMap: this->getDomain(2)->getMapVecFieldUnique() = Spalten von C
5403 MapConstPtr_Type map3, // RangeMap: this->getDomain(4)->getMapVecFieldUnique() = Zeilen von C
5404 bool callFillComplete)
5405{
5406
5407 DomainConstPtr_Type domain = this->domainVec_.at(FEloc);
5408
5409 MapConstPtr_Type mapInt = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
5410 MapConstPtr_Type mapOtherInt = domain->getOtherGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung von other. For FELoc=0 or =4, otherInterface has solid dofs
5411 MapConstPtr_Type mapPartInt = domain->getGlobalInterfaceMapVecFieldPartial();
5412 MapConstPtr_Type mapOtherPartInt = domain->getOtherGlobalInterfaceMapVecFieldPartial();
5413 Teuchos::Array<SC> value( 1, 0. );
5414 value[0] = 1.0; // da Einheitsmatrix
5415 Teuchos::Array<GO> indices( 1, 0 );
5416
5417 GO dofRow;
5418 if (mapPartInt.is_null()) {
5419 for(int k = 0; k < mapInt->getNodeNumElements(); k++){
5420 dofRow = mapInt->getGlobalElement(k);
5421 indices[0] = mapOtherInt->getGlobalElement(k);
5422 C->insertGlobalValues(dofRow, indices(), value());
5423 }
5424 }
5425 else{
5426 for(int k = 0; k < mapPartInt->getNodeNumElements(); k++){
5427 dofRow = mapPartInt->getGlobalElement(k);
5428 indices[0] = mapOtherPartInt->getGlobalElement(k);
5429 C->insertGlobalValues(dofRow, indices(), value());
5430 }
5431 }
5432 if (callFillComplete)
5433 {
5434 // (Domain, Range)
5435 C->fillComplete(map2, map3);
5436 }
5437}
5438
5439
5440template <class SC, class LO, class GO, class NO>
5441void FE<SC,LO,GO,NO>::assemblyShapeDerivativeVelocity(int dim,
5442 std::string FEType1, // P2
5443 std::string FEType2, // P1
5444 MatrixPtr_Type &D,
5445 int FEloc, // 0 = Fluid (Velocity)
5446 MultiVectorPtr_Type u, // Geschwindigkeit
5447 MultiVectorPtr_Type w, // Beschleunigung Gitter
5448 MultiVectorPtr_Type p, // Druck
5449 double dt, // Zeitschrittweite
5450 double rho, // Dichte vom Fluid
5451 double nu, // Viskositaet vom Fluid
5452 bool callFillComplete)
5453{
5454 // int FEloc = this->checkFE(dim,FEType1);
5455
5456 DomainConstPtr_Type domain = this->domainVec_.at(FEloc);
5457 ElementsPtr_Type elements = domain->getElementsC();
5458 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5459 MapConstPtr_Type map = domain->getMapRepeated();
5460
5461 vec3D_dbl_ptr_Type dPhiU;
5462 vec2D_dbl_ptr_Type phiU;
5463 vec2D_dbl_ptr_Type phiP;
5464 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5465 vec2D_dbl_ptr_Type quadPts;
5466
5467 // Hoechste Quadraturordnung angeben (= Zusaetzlicher Term wg. non-conservativ); bei P2/P1 hier Ordnung 6
5468 UN extraDeg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv1);
5469 UN deg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv0) + extraDeg;
5470
5471 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
5472 Helper::getPhi(phiU, weights, dim, FEType1, deg);
5473 Helper::getPhi(phiP, weights, dim, FEType2, deg);
5474 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType1);
5475
5476 // SC = double, GO = long, UN = int
5477 SC detB;
5478 SC absDetB;
5479 SmallMatrix<SC> B(dim);
5480 SmallMatrix<SC> Binv(dim);
5481 GO glob_i, glob_j;
5482
5483 // Der nichtlineare Teil als Array
5484 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
5485 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
5486 Teuchos::ArrayRCP< const SC > pArray = p->getData(0);
5487
5488 if (dim == 2)
5489 {
5490 double val11, val12, val21, val22;
5491 double valDK1_11, valDK1_12, valDK1_21, valDK1_22;
5492 double valDK2_11, valDK2_12, valDK2_21, valDK2_22;
5493 double valDN_11, valDN_12, valDN_21, valDN_22;
5494 double valDW_11, valDW_12, valDW_21, valDW_22;
5495 double valDP_11, valDP_12, valDP_21, valDP_22;
5496 double valDM_11, valDM_12, valDM_21, valDM_22;
5497 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
5498
5499 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
5500 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
5501 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
5502 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
5503 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
5504 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
5505 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
5506 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
5507 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
5508 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
5509 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
5510 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
5511 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
5512 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
5513 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
5514 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5515 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
5516 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
5517 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
5518 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
5519
5520 for (int T = 0; T < elements->numberElements(); T++)
5521 {
5522 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5523 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5524 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5525
5526 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
5527 detB = B.computeInverse(Binv);
5528 absDetB = std::fabs(detB);
5529
5530 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5531 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
5532 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
5533
5534 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
5535 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
5536 {
5537 u1Loc[0][k] = 0.0;
5538 u2Loc[0][k] = 0.0;
5539 w1Loc[0][k] = 0.0;
5540 w2Loc[0][k] = 0.0;
5541 for(int i = 0; i < phiU->at(0).size(); i++)
5542 {
5543 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5544 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5545 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
5546 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
5547 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
5548 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
5549
5550 }
5551 }
5552
5553 // Diskreten Vektor p berechnen
5554 // Beachte: phiP->size() = phiU->size()
5555 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
5556 {
5557 pLoc[0][k] = 0.0;
5558 for(int i = 0; i < phiP->at(0).size(); i++)
5559 {
5560 // Die ersten Eintraege in der Elementliste sind P1
5561 // Alternativ elements2 holen
5562 LO index = elements->getElement(T).getNode(i) + 0;
5563 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
5564
5565 }
5566 }
5567
5568 // Diskrete Grad-Vektoren berechnen,
5569 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
5570 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5571 {
5572 u11[0][k] = 0.0;
5573 u12[0][k] = 0.0;
5574 u21[0][k] = 0.0;
5575 u22[0][k] = 0.0;
5576 w11[0][k] = 0.0;
5577 w12[0][k] = 0.0;
5578 w21[0][k] = 0.0;
5579 w22[0][k] = 0.0;
5580 for(int i = 0; i < dPhiTransU[0].size(); i++)
5581 {
5582 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5583 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5584 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
5585 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
5586 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
5587 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
5588 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
5589 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
5590 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
5591 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
5592
5593 }
5594 }
5595
5596 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
5597 // Beachte: phiP->size() = phiU->size()
5598 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5599 {
5600 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
5601 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
5602 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
5603 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
5604 }
5605
5606
5607 for (int i = 0; i < dPhiU->at(0).size(); i++)
5608 {
5609 Teuchos::Array<SC> value11( 1, 0. ); // x-x
5610 Teuchos::Array<SC> value12( 1, 0. ); // x-y
5611 Teuchos::Array<SC> value21( 1, 0. ); // y-x
5612 Teuchos::Array<SC> value22( 1, 0. ); // y-y
5613 Teuchos::Array<GO> indices( 1, 0 );
5614
5615 for (int j = 0; j < dPhiU->at(0).size(); j++)
5616 {
5617 // DK1
5618 valDK1_11 = 0.0;
5619 valDK1_12 = 0.0;
5620 valDK1_21 = 0.0;
5621 valDK1_22 = 0.0;
5622
5623 // DK2
5624 valDK2_11 = 0.0;
5625 valDK2_12 = 0.0;
5626 valDK2_21 = 0.0;
5627 valDK2_22 = 0.0;
5628
5629 // DN
5630 valDN_11 = 0.0;
5631 valDN_12 = 0.0;
5632 valDN_21 = 0.0;
5633 valDN_22 = 0.0;
5634
5635 // DW
5636 valDW_11 = 0.0;
5637 valDW_12 = 0.0;
5638 valDW_21 = 0.0;
5639 valDW_22 = 0.0;
5640
5641 // DP
5642 valDP_11 = 0.0;
5643 valDP_12 = 0.0;
5644 valDP_21 = 0.0;
5645 valDP_22 = 0.0;
5646
5647 // DM
5648 valDM_11 = 0.0;
5649 valDM_12 = 0.0;
5650 valDM_21 = 0.0;
5651 valDM_22 = 0.0;
5652
5653 for (int k = 0; k < dPhiU->size(); k++)
5654 {
5655 // DK1
5656 valDK1_11 = valDK1_11 + weights->at(k) *
5657 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
5658 u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
5659 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
5660 valDK1_12 = valDK1_12 + weights->at(k) *
5661 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
5662 u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
5663 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
5664 valDK1_21 = valDK1_21 + weights->at(k) *
5665 ( u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
5666 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
5667 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
5668 valDK1_22 = valDK1_22 + weights->at(k) *
5669 ( u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
5670 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
5671 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
5672
5673 // DK2
5674 valDK2_11 = valDK2_11 + weights->at(k) *
5675 ( -sigma12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
5676 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
5677 valDK2_12 = valDK2_12 + weights->at(k) *
5678 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
5679 -sigma11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
5680 valDK2_21 = valDK2_21 + weights->at(k) *
5681 ( -sigma22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
5682 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
5683 valDK2_22 = valDK2_22 + weights->at(k) *
5684 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
5685 -sigma21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
5686
5687 // DN
5688 valDN_11 = valDN_11 + weights->at(k) *
5689 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) +
5690 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
5691 valDN_12 = valDN_12 + weights->at(k) *
5692 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) -
5693 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
5694 valDN_21 = valDN_21 + weights->at(k) *
5695 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) +
5696 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
5697 valDN_22 = valDN_22 + weights->at(k) *
5698 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) -
5699 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
5700
5701 // DW
5702 valDW_11 = valDW_11 + weights->at(k) *
5703 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
5704 valDW_12 = valDW_12 + weights->at(k) *
5705 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
5706 valDW_21 = valDW_21 + weights->at(k) *
5707 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
5708 valDW_22 = valDW_22 + weights->at(k) *
5709 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
5710
5711 // DP
5712 valDP_11 = valDP_11 + weights->at(k) *
5713 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
5714 valDP_12 = valDP_12 + weights->at(k) *
5715 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
5716 valDP_21 = valDP_21 + weights->at(k) *
5717 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
5718 valDP_22 = valDP_22 + weights->at(k) *
5719 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
5720
5721 // DM
5722 valDM_11 = valDM_11 + weights->at(k) *
5723 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
5724 valDM_12 = valDM_12 + weights->at(k) *
5725 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
5726 valDM_21 = valDM_21 + weights->at(k) *
5727 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
5728 valDM_22 = valDM_22 + weights->at(k) *
5729 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
5730 }
5731
5732 val11 = -rho*nu*valDK1_11 + valDK2_11 + rho*valDN_11 - rho*valDP_11 - (1.0/dt)*rho*valDW_11 + (0.5/dt)*rho*valDM_11;
5733 val12 = -rho*nu*valDK1_12 + valDK2_12 + rho*valDN_12 - rho*valDP_12 - (1.0/dt)*rho*valDW_12 + (0.5/dt)*rho*valDM_12;
5734 val21 = -rho*nu*valDK1_21 + valDK2_21 + rho*valDN_21 - rho*valDP_21 - (1.0/dt)*rho*valDW_21 + (0.5/dt)*rho*valDM_21;
5735 val22 = -rho*nu*valDK1_22 + valDK2_22 + rho*valDN_22 - rho*valDP_22 - (1.0/dt)*rho*valDW_22 + (0.5/dt)*rho*valDM_22;
5736
5737 val11 = absDetB * val11;
5738 val12 = absDetB * val12;
5739 val21 = absDetB * val21;
5740 val22 = absDetB * val22;
5741
5742 value11[0] = val11; // x-x
5743 value12[0] = val12; // x-y
5744 value21[0] = val21; // y-x
5745 value22[0] = val22; // y-y
5746
5747 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5748 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5749 indices[0] = glob_j;
5750
5751 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
5752 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5753 glob_j++;
5754 indices[0] = glob_j;
5755 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
5756 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5757 }
5758 }
5759 }
5760 if (callFillComplete)
5761 {
5762 D->fillComplete();
5763 }
5764 }
5765 else if(dim == 3)
5766 {
5767 double val11, val12, val13, val21, val22, val23, val31, val32, val33;
5768 double valDK1_11, valDK1_12, valDK1_13, valDK1_21, valDK1_22, valDK1_23, valDK1_31, valDK1_32, valDK1_33;
5769 double valDK2_11, valDK2_12, valDK2_13, valDK2_21, valDK2_22, valDK2_23, valDK2_31, valDK2_32, valDK2_33;
5770 double valDN_11, valDN_12, valDN_13, valDN_21, valDN_22, valDN_23, valDN_31, valDN_32, valDN_33;
5771 double valDW_11, valDW_12, valDW_13, valDW_21, valDW_22, valDW_23, valDW_31, valDW_32, valDW_33;
5772 double valDP_11, valDP_12, valDP_13, valDP_21, valDP_22, valDP_23, valDP_31, valDP_32, valDP_33;
5773 double valDM_11, valDM_12, valDM_13, valDM_21, valDM_22, valDM_23, valDM_31, valDM_32, valDM_33;
5774 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
5775
5776 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
5777 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
5778 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
5779 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
5780 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
5781 vec2D_dbl_Type u3Loc(1, vec_dbl_Type(weights->size(), -1.));
5782 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
5783 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
5784 vec2D_dbl_Type w3Loc(1, vec_dbl_Type(weights->size(), -1.));
5785 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
5786 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
5787 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
5788 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
5789 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
5790 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
5791 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
5792 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
5793 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
5794 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
5795 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
5796 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
5797 vec2D_dbl_Type w13(1, vec_dbl_Type(weights->size(), -1.));
5798 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
5799 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5800 vec2D_dbl_Type w23(1, vec_dbl_Type(weights->size(), -1.));
5801 vec2D_dbl_Type w31(1, vec_dbl_Type(weights->size(), -1.));
5802 vec2D_dbl_Type w32(1, vec_dbl_Type(weights->size(), -1.));
5803 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
5804 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
5805 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
5806 vec2D_dbl_Type sigma13(1, vec_dbl_Type(weights->size(), -1.));
5807 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
5808 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
5809 vec2D_dbl_Type sigma23(1, vec_dbl_Type(weights->size(), -1.));
5810 vec2D_dbl_Type sigma31(1, vec_dbl_Type(weights->size(), -1.));
5811 vec2D_dbl_Type sigma32(1, vec_dbl_Type(weights->size(), -1.));
5812 vec2D_dbl_Type sigma33(1, vec_dbl_Type(weights->size(), -1.));
5813
5814 for (int T = 0; T < elements->numberElements(); T++)
5815 {
5816 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5817 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5818 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5819 p4 = pointsRep->at(elements->getElement(T).getNode(3));
5820
5821 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
5822 detB = B.computeInverse(Binv);
5823 absDetB = std::fabs(detB);
5824
5825 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5826 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
5827 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
5828
5829 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
5830 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
5831 {
5832 u1Loc[0][k] = 0.0;
5833 u2Loc[0][k] = 0.0;
5834 u3Loc[0][k] = 0.0;
5835 w1Loc[0][k] = 0.0;
5836 w2Loc[0][k] = 0.0;
5837 w3Loc[0][k] = 0.0;
5838 for(int i = 0; i < phiU->at(0).size(); i++)
5839 {
5840 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5841 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5842 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
5843 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
5844 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
5845 u3Loc[0][k] += uArray[index3] * phiU->at(k).at(i);
5846 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
5847 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
5848 w3Loc[0][k] += wArray[index3] * phiU->at(k).at(i);
5849 }
5850 }
5851
5852 // Diskreten Vektor p berechnen
5853 // Beachte: phiP->size() = phiU->size()
5854 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
5855 {
5856 pLoc[0][k] = 0.0;
5857 for(int i = 0; i < phiP->at(0).size(); i++)
5858 {
5859 // Die ersten Eintraege in der Elementliste sind P1
5860 LO index = elements->getElement(T).getNode(i) + 0;
5861 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
5862 }
5863 }
5864
5865 // Diskrete Grad-Vektoren berechnen,
5866 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
5867 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5868 {
5869 u11[0][k] = 0.0;
5870 u12[0][k] = 0.0;
5871 u13[0][k] = 0.0;
5872 u21[0][k] = 0.0;
5873 u22[0][k] = 0.0;
5874 u23[0][k] = 0.0;
5875 u31[0][k] = 0.0;
5876 u32[0][k] = 0.0;
5877 u33[0][k] = 0.0;
5878 w11[0][k] = 0.0;
5879 w12[0][k] = 0.0;
5880 w13[0][k] = 0.0;
5881 w21[0][k] = 0.0;
5882 w22[0][k] = 0.0;
5883 w23[0][k] = 0.0;
5884 w31[0][k] = 0.0;
5885 w32[0][k] = 0.0;
5886 w33[0][k] = 0.0;
5887 for(int i = 0; i < dPhiTransU[0].size(); i++)
5888 {
5889 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5890 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5891 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
5892 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
5893 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
5894 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
5895 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
5896 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
5897 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
5898 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
5899 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
5900 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
5901 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
5902 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
5903 w13[0][k] += wArray[index1] * dPhiTransU[k][i][2];
5904 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
5905 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
5906 w23[0][k] += wArray[index2] * dPhiTransU[k][i][2];
5907 w31[0][k] += wArray[index3] * dPhiTransU[k][i][0];
5908 w32[0][k] += wArray[index3] * dPhiTransU[k][i][1];
5909 w33[0][k] += wArray[index3] * dPhiTransU[k][i][2];
5910 }
5911 }
5912
5913 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
5914 // Beachte: phiP->size() = phiU->size()
5915 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5916 {
5917 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
5918 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
5919 sigma13[0][k] = rho * nu * (u13[0][k] + u31[0][k]);
5920 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
5921 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
5922 sigma23[0][k] = rho * nu * (u23[0][k] + u32[0][k]);
5923 sigma31[0][k] = rho * nu * (u31[0][k] + u13[0][k]);
5924 sigma32[0][k] = rho * nu * (u32[0][k] + u23[0][k]);
5925 sigma33[0][k] = rho * nu * (u33[0][k] + u33[0][k]) - pLoc[0][k];
5926 }
5927
5928
5929 for (int i = 0; i < dPhiU->at(0).size(); i++)
5930 {
5931 Teuchos::Array<SC> value11( 1, 0. ); // x-x
5932 Teuchos::Array<SC> value12( 1, 0. ); // x-y
5933 Teuchos::Array<SC> value13( 1, 0. ); // x-z
5934 Teuchos::Array<SC> value21( 1, 0. ); // y-x
5935 Teuchos::Array<SC> value22( 1, 0. ); // y-y
5936 Teuchos::Array<SC> value23( 1, 0. ); // y-z
5937 Teuchos::Array<SC> value31( 1, 0. ); // z-x
5938 Teuchos::Array<SC> value32( 1, 0. ); // z-y
5939 Teuchos::Array<SC> value33( 1, 0. ); // z-z
5940 Teuchos::Array<GO> indices( 1, 0 );
5941
5942 for (int j = 0; j < dPhiU->at(0).size(); j++)
5943 {
5944 // DK1
5945 valDK1_11 = 0.0;
5946 valDK1_12 = 0.0;
5947 valDK1_13 = 0.0;
5948 valDK1_21 = 0.0;
5949 valDK1_22 = 0.0;
5950 valDK1_23 = 0.0;
5951 valDK1_31 = 0.0;
5952 valDK1_32 = 0.0;
5953 valDK1_33 = 0.0;
5954
5955 // DK2
5956 valDK2_11 = 0.0;
5957 valDK2_12 = 0.0;
5958 valDK2_13 = 0.0;
5959 valDK2_21 = 0.0;
5960 valDK2_22 = 0.0;
5961 valDK2_23 = 0.0;
5962 valDK2_31 = 0.0;
5963 valDK2_32 = 0.0;
5964 valDK2_33 = 0.0;
5965
5966 // DN
5967 valDN_11 = 0.0;
5968 valDN_12 = 0.0;
5969 valDN_13 = 0.0;
5970 valDN_21 = 0.0;
5971 valDN_22 = 0.0;
5972 valDN_23 = 0.0;
5973 valDN_31 = 0.0;
5974 valDN_32 = 0.0;
5975 valDN_33 = 0.0;
5976
5977 // DW
5978 valDW_11 = 0.0;
5979 valDW_12 = 0.0;
5980 valDW_13 = 0.0;
5981 valDW_21 = 0.0;
5982 valDW_22 = 0.0;
5983 valDW_23 = 0.0;
5984 valDW_31 = 0.0;
5985 valDW_32 = 0.0;
5986 valDW_33 = 0.0;
5987
5988 // DP
5989 valDP_11 = 0.0;
5990 valDP_12 = 0.0;
5991 valDP_13 = 0.0;
5992 valDP_21 = 0.0;
5993 valDP_22 = 0.0;
5994 valDP_23 = 0.0;
5995 valDP_31 = 0.0;
5996 valDP_32 = 0.0;
5997 valDP_33 = 0.0;
5998
5999 // DM
6000 valDM_11 = 0.0;
6001 valDM_12 = 0.0;
6002 valDM_13 = 0.0;
6003 valDM_21 = 0.0;
6004 valDM_22 = 0.0;
6005 valDM_23 = 0.0;
6006 valDM_31 = 0.0;
6007 valDM_32 = 0.0;
6008 valDM_33 = 0.0;
6009
6010 for (int k = 0; k < dPhiU->size(); k++)
6011 {
6012 // DK1
6013 valDK1_11 = valDK1_11 + weights->at(k) *
6014 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6015 ( u11[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6016 ( u11[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6017 valDK1_12 = valDK1_12 + weights->at(k) *
6018 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6019 ( u12[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6020 ( u12[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6021 valDK1_13 = valDK1_13 + weights->at(k) *
6022 ( 2 * u13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6023 ( u13[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6024 ( u13[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6025 valDK1_21 = valDK1_21 + weights->at(k) *
6026 ( ( u21[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6027 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6028 ( u21[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6029 valDK1_22 = valDK1_22 + weights->at(k) *
6030 ( ( u22[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6031 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6032 ( u22[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6033 valDK1_23 = valDK1_23 + weights->at(k) *
6034 ( ( u23[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6035 2 * u23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6036 ( u23[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6037 valDK1_31 = valDK1_31 + weights->at(k) *
6038 ( ( u31[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6039 ( u31[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6040 2 * u31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6041 valDK1_32 = valDK1_32 + weights->at(k) *
6042 ( ( u32[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6043 ( u32[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6044 2 * u32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6045 valDK1_33 = valDK1_33 + weights->at(k) *
6046 ( ( u33[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6047 ( u33[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6048 2 * u33[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6049
6050 // DK2
6051 valDK2_11 = valDK2_11 + weights->at(k) *
6052 ( ( -sigma12[0][k] * dPhiTransU[k][j][1] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6053 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6054 sigma13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6055 valDK2_12 = valDK2_12 + weights->at(k) *
6056 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6057 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6058 sigma13[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6059 valDK2_13 = valDK2_13 + weights->at(k) *
6060 ( sigma11[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6061 sigma12[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6062 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6063 valDK2_21 = valDK2_21 + weights->at(k) *
6064 ( ( -sigma22[0][k] * dPhiTransU[k][j][1] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6065 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6066 sigma23[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6067 valDK2_22 = valDK2_22 + weights->at(k) *
6068 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6069 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6070 sigma23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6071 valDK2_23 = valDK2_23 + weights->at(k) *
6072 ( sigma21[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6073 sigma22[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6074 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma22[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6075 valDK2_31 = valDK2_31 + weights->at(k) *
6076 ( ( -sigma32[0][k] * dPhiTransU[k][j][1] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6077 sigma32[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6078 sigma33[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6079 valDK2_32 = valDK2_32 + weights->at(k) *
6080 ( sigma31[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6081 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6082 sigma33[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6083 valDK2_33 = valDK2_33 + weights->at(k) *
6084 ( sigma31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6085 sigma32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6086 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6087
6088 // DN
6089 double ZN_11; // Die Z_i fuer das DN wie in der Masterarbeit definiert
6090 double ZN_12;
6091 double ZN_13;
6092 double ZN_21;
6093 double ZN_22;
6094 double ZN_23;
6095 double ZN_31;
6096 double ZN_32;
6097 double ZN_33;
6098 ZN_11 = - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
6099 ZN_12 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][0];
6100 ZN_13 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][0];
6101 ZN_21 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][1];
6102 ZN_22 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
6103 ZN_23 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][1];
6104 ZN_31 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][2];
6105 ZN_32 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][2];
6106 ZN_33 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1];
6107
6108 valDN_11 = valDN_11 + weights->at(k) *
6109 ( ZN_11 * u11[0][k] * phiU->at(k).at(i) +
6110 ZN_12 * u12[0][k] * phiU->at(k).at(i) +
6111 ZN_13 * u13[0][k] * phiU->at(k).at(i) );
6112 valDN_12 = valDN_12 + weights->at(k) *
6113 ( ZN_21 * u11[0][k] * phiU->at(k).at(i) +
6114 ZN_22 * u12[0][k] * phiU->at(k).at(i) +
6115 ZN_23 * u13[0][k] * phiU->at(k).at(i) );
6116 valDN_13 = valDN_13 + weights->at(k) *
6117 ( ZN_31 * u11[0][k] * phiU->at(k).at(i) +
6118 ZN_32 * u12[0][k] * phiU->at(k).at(i) +
6119 ZN_33 * u13[0][k] * phiU->at(k).at(i) );
6120 valDN_21 = valDN_21 + weights->at(k) *
6121 ( ZN_11 * u21[0][k] * phiU->at(k).at(i) +
6122 ZN_12 * u22[0][k] * phiU->at(k).at(i) +
6123 ZN_13 * u23[0][k] * phiU->at(k).at(i) );
6124 valDN_22 = valDN_22 + weights->at(k) *
6125 ( ZN_21 * u21[0][k] * phiU->at(k).at(i) +
6126 ZN_22 * u22[0][k] * phiU->at(k).at(i) +
6127 ZN_23 * u23[0][k] * phiU->at(k).at(i) );
6128 valDN_23 = valDN_23 + weights->at(k) *
6129 ( ZN_31 * u21[0][k] * phiU->at(k).at(i) +
6130 ZN_32 * u22[0][k] * phiU->at(k).at(i) +
6131 ZN_33 * u23[0][k] * phiU->at(k).at(i) );
6132 valDN_31 = valDN_31 + weights->at(k) *
6133 ( ZN_11 * u31[0][k] * phiU->at(k).at(i) +
6134 ZN_12 * u32[0][k] * phiU->at(k).at(i) +
6135 ZN_13 * u33[0][k] * phiU->at(k).at(i) );
6136 valDN_32 = valDN_32 + weights->at(k) *
6137 ( ZN_21 * u31[0][k] * phiU->at(k).at(i) +
6138 ZN_22 * u32[0][k] * phiU->at(k).at(i) +
6139 ZN_23 * u33[0][k] * phiU->at(k).at(i) );
6140 valDN_33 = valDN_33 + weights->at(k) *
6141 ( ZN_31 * u31[0][k] * phiU->at(k).at(i) +
6142 ZN_32 * u32[0][k] * phiU->at(k).at(i) +
6143 ZN_33 * u33[0][k] * phiU->at(k).at(i) );
6144
6145 // DW
6146 valDW_11 = valDW_11 + weights->at(k) *
6147 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6148 valDW_12 = valDW_12 + weights->at(k) *
6149 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6150 valDW_13 = valDW_13 + weights->at(k) *
6151 ( u13[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6152 valDW_21 = valDW_21 + weights->at(k) *
6153 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6154 valDW_22 = valDW_22 + weights->at(k) *
6155 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6156 valDW_23 = valDW_23 + weights->at(k) *
6157 ( u23[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6158 valDW_31 = valDW_31 + weights->at(k) *
6159 ( u31[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6160 valDW_32 = valDW_32 + weights->at(k) *
6161 ( u32[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6162 valDW_33 = valDW_33 + weights->at(k) *
6163 ( u33[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6164
6165 // DP
6166 double ZP_1; // Die Z_i fuer das DP wie in der Masterarbeit definiert
6167 double ZP_2;
6168 double ZP_3;
6169 ZP_1 = -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] -
6170 w31[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][0];
6171 ZP_2 = w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] -
6172 w32[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][1];
6173 ZP_3 = w11[0][k] * dPhiTransU[k][j][2] - w13[0][k] * dPhiTransU[k][j][0] +
6174 w22[0][k] * dPhiTransU[k][j][2] - w23[0][k] * dPhiTransU[k][j][1];
6175
6176 valDP_11 = valDP_11 + weights->at(k) *
6177 ( ZP_1 * u1Loc[0][k] * phiU->at(k).at(i) );
6178 valDP_12 = valDP_12 + weights->at(k) *
6179 ( ZP_2 * u1Loc[0][k] * phiU->at(k).at(i) );
6180 valDP_13 = valDP_13 + weights->at(k) *
6181 ( ZP_3 * u1Loc[0][k] * phiU->at(k).at(i) );
6182 valDP_21 = valDP_21 + weights->at(k) *
6183 ( ZP_1 * u2Loc[0][k] * phiU->at(k).at(i) );
6184 valDP_22 = valDP_22 + weights->at(k) *
6185 ( ZP_2 * u2Loc[0][k] * phiU->at(k).at(i) );
6186 valDP_23 = valDP_23 + weights->at(k) *
6187 ( ZP_3 * u2Loc[0][k] * phiU->at(k).at(i) );
6188 valDP_31 = valDP_31 + weights->at(k) *
6189 ( ZP_1 * u3Loc[0][k] * phiU->at(k).at(i) );
6190 valDP_32 = valDP_32 + weights->at(k) *
6191 ( ZP_2 * u3Loc[0][k] * phiU->at(k).at(i) );
6192 valDP_33 = valDP_33 + weights->at(k) *
6193 ( ZP_3 * u3Loc[0][k] * phiU->at(k).at(i) );
6194
6195 // DM
6196 valDM_11 = valDM_11 + weights->at(k) *
6197 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
6198 valDM_12 = valDM_12 + weights->at(k) *
6199 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
6200 valDM_13 = valDM_13 + weights->at(k) *
6201 ( dPhiTransU[k][j][2] * u1Loc[0][k] * phiU->at(k).at(i) );
6202 valDM_21 = valDM_21 + weights->at(k) *
6203 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
6204 valDM_22 = valDM_22 + weights->at(k) *
6205 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
6206 valDM_23 = valDM_23 + weights->at(k) *
6207 ( dPhiTransU[k][j][2] * u2Loc[0][k] * phiU->at(k).at(i) );
6208 valDM_31 = valDM_31 + weights->at(k) *
6209 ( dPhiTransU[k][j][0] * u3Loc[0][k] * phiU->at(k).at(i) );
6210 valDM_32 = valDM_32 + weights->at(k) *
6211 ( dPhiTransU[k][j][1] * u3Loc[0][k] * phiU->at(k).at(i) );
6212 valDM_33 = valDM_33 + weights->at(k) *
6213 ( dPhiTransU[k][j][2] * u3Loc[0][k] * phiU->at(k).at(i) );
6214 }
6215
6216 val11 = -rho*nu*valDK1_11 + valDK2_11 + rho*valDN_11 - rho*valDP_11 - (1.0/dt)*rho*valDW_11 + (0.5/dt)*rho*valDM_11;
6217 val12 = -rho*nu*valDK1_12 + valDK2_12 + rho*valDN_12 - rho*valDP_12 - (1.0/dt)*rho*valDW_12 + (0.5/dt)*rho*valDM_12;
6218 val13 = -rho*nu*valDK1_13 + valDK2_13 + rho*valDN_13 - rho*valDP_13 - (1.0/dt)*rho*valDW_13 + (0.5/dt)*rho*valDM_13;
6219 val21 = -rho*nu*valDK1_21 + valDK2_21 + rho*valDN_21 - rho*valDP_21 - (1.0/dt)*rho*valDW_21 + (0.5/dt)*rho*valDM_21;
6220 val22 = -rho*nu*valDK1_22 + valDK2_22 + rho*valDN_22 - rho*valDP_22 - (1.0/dt)*rho*valDW_22 + (0.5/dt)*rho*valDM_22;
6221 val23 = -rho*nu*valDK1_23 + valDK2_23 + rho*valDN_23 - rho*valDP_23 - (1.0/dt)*rho*valDW_23 + (0.5/dt)*rho*valDM_23;
6222 val31 = -rho*nu*valDK1_31 + valDK2_31 + rho*valDN_31 - rho*valDP_31 - (1.0/dt)*rho*valDW_31 + (0.5/dt)*rho*valDM_31;
6223 val32 = -rho*nu*valDK1_32 + valDK2_32 + rho*valDN_32 - rho*valDP_32 - (1.0/dt)*rho*valDW_32 + (0.5/dt)*rho*valDM_32;
6224 val33 = -rho*nu*valDK1_33 + valDK2_33 + rho*valDN_33 - rho*valDP_33 - (1.0/dt)*rho*valDW_33 + (0.5/dt)*rho*valDM_33;
6225
6226 val11 = absDetB * val11;
6227 val12 = absDetB * val12;
6228 val13 = absDetB * val13;
6229 val21 = absDetB * val21;
6230 val22 = absDetB * val22;
6231 val23 = absDetB * val23;
6232 val31 = absDetB * val31;
6233 val32 = absDetB * val32;
6234 val33 = absDetB * val33;
6235
6236 value11[0] = val11; // x-x
6237 value12[0] = val12; // x-y
6238 value13[0] = val13; // x-z
6239 value21[0] = val21; // y-x
6240 value22[0] = val22; // y-y
6241 value23[0] = val23; // y-z
6242 value31[0] = val31; // z-x
6243 value32[0] = val32; // z-y
6244 value33[0] = val33; // z-z
6245
6246
6247 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6248 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6249 indices[0] = glob_j;
6250
6251 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
6252 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6253 D->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
6254 glob_j++;
6255 indices[0] = glob_j;
6256 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
6257 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6258 D->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
6259 glob_j++;
6260 indices[0] = glob_j;
6261 D->insertGlobalValues(glob_i, indices(), value13()); // x-z
6262 D->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
6263 D->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
6264 }
6265 }
6266 }
6267 if (callFillComplete)
6268 {
6269 D->fillComplete();
6270 }
6271 }
6272
6273}
6274
6275
6276template <class SC, class LO, class GO, class NO>
6277void FE<SC,LO,GO,NO>::assemblyShapeDerivativeDivergence(int dim,
6278 std::string FEType1,
6279 std::string FEType2,
6280 MatrixPtr_Type &DB,
6281 int FEloc1, // 1 = Fluid-Pressure
6282 int FEloc2, // 0 = Fluid-Velocity
6283 MapConstPtr_Type map1_unique, // Pressure-Map
6284 MapConstPtr_Type map2_unique, // Velocity-Map unique als VecField
6285 MultiVectorPtr_Type u, // Geschwindigkeit
6286 bool callFillComplete)
6287{
6288 DomainConstPtr_Type domain1 = this->domainVec_.at(FEloc1);
6289 ElementsPtr_Type elements = domain1->getElementsC();
6290 vec2D_dbl_ptr_Type pointsRep = domain1->getPointsRepeated();
6291 MapConstPtr_Type map1_rep = domain1->getMapRepeated();
6292
6293 // Fuer die Fluid-Velocity-Map
6294 DomainConstPtr_Type domain2 = this->domainVec_.at(FEloc2);
6295 MapConstPtr_Type map2_rep = domain2->getMapRepeated();
6296 ElementsPtr_Type elements2 = domain2->getElementsC();
6297
6298 vec3D_dbl_ptr_Type dPhiU;
6299 vec2D_dbl_ptr_Type phiU;
6300 vec2D_dbl_ptr_Type phiP;
6301 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6302 vec2D_dbl_ptr_Type quadPts;
6303
6304 UN extraDeg = Helper::determineDegree( dim, FEType1, Helper::Deriv1);
6305 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv0) + 2*extraDeg;
6306
6307
6308 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
6309 Helper::getPhi(phiU, weights, dim, FEType1, deg);
6310 Helper::getPhi(phiP, weights, dim, FEType2, deg);
6311 Helper::getQuadratureValues(dim, deg, quadPts, weights, FEType1);
6312
6313 // SC = double, GO = long, UN = int
6314 SC detB;
6315 SC absDetB;
6316 SmallMatrix<SC> B(dim);
6317 SmallMatrix<SC> Binv(dim);
6318 GO glob_i, glob_j;
6319
6320 // Der nichtlineare Teil als Array
6321 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
6322
6323 if (dim == 2)
6324 {
6325 double val1, val2;
6326 double valDB_1, valDB_2;
6327 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
6328
6329 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6330 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6331 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6332 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6333 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6334 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6335 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6336
6337 for (int T = 0; T < elements->numberElements(); T++)
6338 {
6339 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6340 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6341 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6342
6343 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6344 detB = B.computeInverse(Binv);
6345 absDetB = std::fabs(detB);
6346
6347 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6348 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6349 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6350
6351 // Diskrete Grad-Vektoren berechnen,
6352 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6353 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6354 {
6355 u11[0][k] = 0.0;
6356 u12[0][k] = 0.0;
6357 u21[0][k] = 0.0;
6358 u22[0][k] = 0.0;
6359 for(int i = 0; i < dPhiTransU[0].size(); i++)
6360 {
6361 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
6362 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
6363 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6364 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6365 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6366 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6367
6368 }
6369 }
6370
6371 for (int i = 0; i < phiP->at(0).size(); i++)
6372 {
6373 Teuchos::Array<SC> value1( 1, 0. ); // p-x
6374 Teuchos::Array<SC> value2( 1, 0. ); // p-y
6375 Teuchos::Array<GO> indices( 1, 0 );
6376
6377 for (int j = 0; j < dPhiU->at(0).size(); j++)
6378 {
6379 valDB_1 = 0.0;
6380 valDB_2 = 0.0;
6381
6382 for (int k = 0; k < dPhiU->size(); k++)
6383 {
6384 // DB
6385 valDB_1 = valDB_1 + weights->at(k) *
6386 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) );
6387 valDB_2 = valDB_2 + weights->at(k) *
6388 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] ) );
6389 }
6390
6391 val1 = valDB_1;
6392 val2 = valDB_2;
6393
6394 val1 = absDetB * val1;
6395 val2 = absDetB * val2;
6396
6397 value1[0] = val1; // p-x
6398 value2[0] = val2; // p-y
6399
6400 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
6401 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
6402 indices[0] = glob_j;
6403
6404 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
6405 glob_j++;
6406 indices[0] = glob_j;
6407 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
6408 }
6409 }
6410 }
6411 if (callFillComplete)
6412 {
6413 DB->fillComplete(map2_unique, map1_unique);
6414 }
6415 }
6416 else if(dim == 3)
6417 {
6418 double val1, val2, val3;
6419 double valDB_1, valDB_2, valDB_3;
6420 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6421
6422 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6423 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6424 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6425 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6426 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6427 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
6428 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6429 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6430 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
6431 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
6432 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
6433 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
6434
6435 for (int T = 0; T < elements->numberElements(); T++)
6436 {
6437 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6438 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6439 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6440 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6441
6442 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6443 detB = B.computeInverse(Binv);
6444 absDetB = std::fabs(detB);
6445
6446 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6447 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6448 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6449
6450 // Diskrete Grad-Vektoren berechnen,
6451 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6452 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6453 {
6454 u11[0][k] = 0.0;
6455 u12[0][k] = 0.0;
6456 u13[0][k] = 0.0;
6457 u21[0][k] = 0.0;
6458 u22[0][k] = 0.0;
6459 u23[0][k] = 0.0;
6460 u31[0][k] = 0.0;
6461 u32[0][k] = 0.0;
6462 u33[0][k] = 0.0;
6463
6464 for(int i = 0; i < dPhiTransU[0].size(); i++)
6465 {
6466 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
6467 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
6468 LO index3 = dim * elements2->getElement(T).getNode(i) + 2; // z
6469 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6470 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6471 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
6472 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6473 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6474 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
6475 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
6476 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
6477 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
6478 }
6479 }
6480
6481 for (int i = 0; i < phiP->at(0).size(); i++)
6482 {
6483 Teuchos::Array<SC> value1( 1, 0. ); // p-x
6484 Teuchos::Array<SC> value2( 1, 0. ); // p-y
6485 Teuchos::Array<SC> value3( 1, 0. ); // p-z
6486 Teuchos::Array<GO> indices( 1, 0 );
6487
6488 for (int j = 0; j < dPhiU->at(0).size(); j++)
6489 {
6490 valDB_1 = 0.0;
6491 valDB_2 = 0.0;
6492 valDB_3 = 0.0;
6493
6494 for (int k = 0; k < dPhiU->size(); k++)
6495 {
6496 // DB
6497 valDB_1 = valDB_1 + weights->at(k) *
6498 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] -
6499 u31[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) );
6500 valDB_2 = valDB_2 + weights->at(k) *
6501 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] -
6502 u32[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) );
6503 valDB_3 = valDB_3 + weights->at(k) *
6504 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][2] - u13[0][k] * dPhiTransU[k][j][0] +
6505 u22[0][k] * dPhiTransU[k][j][2] - u23[0][k] * dPhiTransU[k][j][1] ) );
6506 }
6507
6508 val1 = valDB_1;
6509 val2 = valDB_2;
6510 val3 = valDB_3;
6511
6512 val1 = absDetB * val1;
6513 val2 = absDetB * val2;
6514 val3 = absDetB * val3;
6515
6516 value1[0] = val1; // p-x
6517 value2[0] = val2; // p-y
6518 value3[0] = val3; // p-z
6519
6520 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
6521 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
6522 indices[0] = glob_j;
6523
6524 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
6525 glob_j++;
6526 indices[0] = glob_j;
6527 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
6528 glob_j++;
6529 indices[0] = glob_j;
6530 DB->insertGlobalValues(glob_i, indices(), value3()); // p-z
6531 }
6532 }
6533 }
6534 if (callFillComplete)
6535 {
6536 DB->fillComplete(map2_unique, map1_unique);
6537 }
6538 }
6539
6540}
6541
6542template <class SC, class LO, class GO, class NO>
6543void FE<SC,LO,GO,NO>::assemblySurfaceIntegralExternal(int dim,
6544 std::string FEType,
6545 MultiVectorPtr_Type f,
6546 MultiVectorPtr_Type d_rep,
6547 std::vector<SC>& funcParameter,
6548 RhsFunc_Type func,
6549 ParameterListPtr_Type params,
6550 int FEloc) {
6551
6552 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
6553
6554 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
6555
6556 SC elScaling;
6557 SmallMatrix<SC> B(dim);
6558 vec_dbl_Type b(dim);
6559 f->putScalar(0.);
6560 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
6561
6562 int flagSurface = params->sublist("Parameter Solid").get("Flag Surface",5);
6563
6564 std::vector<double> valueFunc(dim);
6565
6566 SC* paramsFunc = &(funcParameter[0]);
6567
6568 // The second last entry is a placeholder for the surface element flag. It will be set below
6569 for (UN T=0; T<elements->numberElements(); T++) {
6570 FiniteElement fe = elements->getElement( T );
6571 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
6572 for (int surface=0; surface<fe.numSubElements(); surface++) {
6573 FiniteElement feSub = subEl->getElement( surface );
6574 if(subEl->getDimension() == dim-1 ){
6575
6576 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
6577
6578
6579 vec_dbl_Type solution_d = this->getSolution(nodeList, d_rep,dim);
6580 vec2D_dbl_Type nodes;
6581 nodes = this->getCoordinates(nodeList, pointsRep);
6582
6583
6584 double positions[18];
6585 int count =0;
6586 for(int i=0;i<6;i++)
6587 for(int j=0;j<3;j++){
6588 positions[count] = nodes[i][j];
6589 count++;
6590
6591 }
6592
6593
6594 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
6595 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
6596 func( &p1[0], &valueFunc[0], paramsFunc);
6597
6598 if(valueFunc[0] != 0.){
6599
6600 double *residuumVector;
6601 #ifdef FEDD_HAVE_ACEGENINTERFACE
6602
6603 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1., 35, &positions[0], &solution_d[0]);
6604 pt.computeTangentResidual();
6605 residuumVector = pt.getResiduum();
6606 #endif
6607
6608 for(int i=0; i< nodeList.size() ; i++){
6609 for(int d=0; d<dim; d++)
6610 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
6611 }
6612
6613 // free(residuumVector);
6614 }
6615
6616 }
6617 }
6618 }
6619 //f->scale(-1.);
6620
6621}
6622
6625
6626template <class SC, class LO, class GO, class NO>
6628 std::string FEType,
6629 MultiVectorPtr_Type f,
6630 MultiVectorPtr_Type d_rep,
6631 MatrixPtr_Type &Kext,
6632 std::vector<SC>& funcParameter,
6633 RhsFunc_Type func,
6634 ParameterListPtr_Type params,
6635 int FEloc) {
6636
6637 // degree of function funcParameter[0]
6638
6639 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
6640
6641 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
6642
6643 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
6644 SC elScaling;
6645 SmallMatrix<SC> B(dim);
6646 vec_dbl_Type b(dim);
6647 f->putScalar(0.);
6648 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
6649
6650 std::vector<double> valueFunc(dim);
6651
6652 SC* paramsFunc = &(funcParameter[0]);
6653
6654 // The second last entry is a placeholder for the surface element flag. It will be set below
6655 for (UN T=0; T<elements->numberElements(); T++) {
6656 FiniteElement fe = elements->getElement( T );
6657 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
6658 for (int surface=0; surface<fe.numSubElements(); surface++) {
6659 FiniteElement feSub = subEl->getElement( surface );
6660 if(subEl->getDimension() == dim-1 ){
6661 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
6662
6663 vec_dbl_Type solution_d = this->getSolution(nodeList, d_rep,dim);
6664 vec2D_dbl_Type nodes;
6665 nodes = this->getCoordinates(nodeList, pointsRep);
6666
6667
6668 double positions[18];
6669 int count =0;
6670 for(int i=0;i<6;i++){
6671 for(int j=0;j<3;j++){
6672 positions[count] = nodes[i][j];
6673 count++;
6674
6675 }
6676 }
6677
6678 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
6679 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
6680 func( &p1[0], &valueFunc[0], paramsFunc);
6681
6682 if(valueFunc[0] != 0.){
6683
6684 double *residuumVector;
6685 double **stiffMat;
6686
6687 #ifdef FEDD_HAVE_ACEGENINTERFACE
6688 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1.0, 35, &positions[0], &solution_d[0]);
6689 pt.computeTangentResidual();
6690
6691 residuumVector = pt.getResiduum();
6692 stiffMat = pt.getStiffnessMatrix();
6693 #endif
6694
6695
6696
6697 int dofs1 = dim;
6698 int numNodes1 =nodeList.size();
6699
6700 SmallMatrix_Type elementMatrixPrint(18,0.);
6701 for(int i=0; i< 18 ; i++){
6702 for(int j=0; j< 18; j++){
6703 if(std::fabs(stiffMat[i][j]) >1e-13)
6704 elementMatrixPrint[i][j] = stiffMat[i][j];
6705
6706 }
6707 }
6708
6709 SmallMatrix_Type elementMatrixWrite(18,0.);
6710
6711 SmallMatrix_Type elementMatrixIDsRow(18,0.);
6712 SmallMatrix_Type elementMatrixIDsCol(18,0.);
6713
6714
6715 for (UN i=0; i < numNodes1 ; i++) {
6716 for(int di=0; di<dim; di++){
6717 Teuchos::Array<SC> value1( numNodes1*dim, 0. );
6718 Teuchos::Array<GO> columnIndices1( numNodes1*dim, 0 );
6719 GO row =GO (dim* map->getGlobalElement( nodeList[i] )+di);
6720 LO rowLO = dim*i+di;
6721 // Zeilenweise werden die Einträge global assembliert
6722 for (UN j=0; j <numNodes1; j++){
6723 for(int d=0; d<dim; d++){
6724 columnIndices1[dim*j+d] = GO ( dim * map->getGlobalElement( nodeList[j] ) + d );
6725 value1[dim*j+d] = stiffMat[rowLO][dim*j+d];
6726 }
6727 }
6728 Kext->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
6729 }
6730 }
6731
6732
6733
6734 for(int i=0; i< nodeList.size() ; i++){
6735 for(int d=0; d<dim; d++){
6736 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
6737 }
6738 }
6739
6740
6741 }
6742
6743
6744 }
6745 }
6746 }
6747 //f->scale(-1.);
6748 Kext->fillComplete(this->domainVec_.at(FEloc)->getMapVecFieldUnique(),this->domainVec_.at(FEloc)->getMapVecFieldUnique());
6749}
6750
6751
6752
6753template <class SC, class LO, class GO, class NO>
6754void FE<SC,LO,GO,NO>::assemblySurfaceIntegral(int dim,
6755 std::string FEType,
6756 MultiVectorPtr_Type f,
6757 std::string fieldType,
6758 RhsFunc_Type func,
6759 std::vector<SC>& funcParameter) {
6760
6761 // degree of function funcParameter[0]
6762 //TEUCHOS_TEST_FOR_EXCEPTION( funcParameter[funcParameter.size()-1] > 0., std::logic_error, "We only support constant functions for now.");
6763 UN FEloc = this->checkFE(dim,FEType);
6764
6765 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
6766
6767 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
6768
6769 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
6770 vec2D_dbl_ptr_Type phi;
6771 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6772
6773 UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // Degree from function set/determined externally
6774 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
6775
6776 Helper::getPhi(phi, weights, dim-1, FEType, deg);
6777
6778 vec2D_dbl_ptr_Type quadPoints;
6779 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
6780 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
6781 w.reset();
6782
6783 SC elScaling;
6784 SmallMatrix<SC> B(dim);
6785 vec_dbl_Type b(dim);
6786 f->putScalar(0.);
6787 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
6788 int parameters;
6789
6790
6791 std::vector<double> valueFunc(dim);
6792 // The second last entry is a placeholder for the surface element flag. It will be set below
6793 SC* params = &(funcParameter[0]);
6794 for (UN T=0; T<elements->numberElements(); T++) {
6795 FiniteElement fe = elements->getElement( T );
6796 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
6797 for (int surface=0; surface<fe.numSubElements(); surface++) {
6798 FiniteElement feSub = subEl->getElement( surface );
6799 if(subEl->getDimension() == dim-1){
6800 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
6801 params[ funcParameter.size() - 1 ] = feSub.getFlag();
6802
6803 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
6804
6805 vec_dbl_Type v_E(dim,1.);
6806 double norm_v_E=1.;
6807
6808 Helper::computeSurfaceNormal(dim, pointsRep,nodeList,v_E,norm_v_E);
6809
6810 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
6811 elScaling = B.computeScaling( );
6812 // loop over basis functions
6813 for (UN i=0; i < phi->at(0).size(); i++) {
6814 Teuchos::Array<SC> value(0);
6815 if ( fieldType == "Scalar" )
6816 value.resize( 1, 0. );
6817 else if ( fieldType == "Vector" )
6818 value.resize( dim, 0. );
6819 // loop over basis functions quadrature points
6820 for (UN w=0; w<phi->size(); w++) {
6821 vec_dbl_Type x(dim,0.); //coordinates
6822 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
6823 for (int l=0; l<dim-1; l++){
6824 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
6825 }
6826 x[k] += b[k];
6827 }
6828
6829 func( &x[0], &valueFunc[0], params);
6830 if ( fieldType == "Scalar" )
6831 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
6832 else if ( fieldType == "Vector" ){
6833 for (int j=0; j<value.size(); j++){
6834 value[j] += weights->at(w) * valueFunc[j]*v_E[j]/norm_v_E * (*phi)[w][i];
6835 }
6836 }
6837 }
6838
6839 for (int j=0; j<value.size(); j++)
6840 value[j] *= elScaling;
6841
6842 if ( fieldType== "Scalar" )
6843 valuesF[ nodeList[ i ] ] += value[0];
6844
6845
6846 else if ( fieldType== "Vector" ){
6847 for (int j=0; j<value.size(); j++)
6848 valuesF[ dim * nodeList[ i ] + j ] += value[j];
6849 }
6850 }
6851 }
6852 }
6853 }
6854 f->scale(-1.); // Generally the pressure is definied in opposite direction of the normal
6855}
6856
6857template <class SC, class LO, class GO, class NO>
6858void FE<SC,LO,GO,NO>::assemblySurfaceIntegralFlag(int dim,
6859 std::string FEType,
6860 MultiVectorPtr_Type f,
6861 std::string fieldType,
6862 BC_func_Type func,
6863 std::vector<SC>& funcParameter) {
6864
6865// degree of function funcParameter[0]
6866 TEUCHOS_TEST_FOR_EXCEPTION(funcParameter[0]!=0,std::logic_error, "We only support constant functions for now.");
6867
6868 UN FEloc = this->checkFE(dim,FEType);
6869
6870 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
6871
6872 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
6873
6874 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
6875 vec2D_dbl_ptr_Type phi;
6876 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6877 UN degFunc = funcParameter[0] + 1.e-14;
6878 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
6879
6880 Helper::getPhi(phi, weights, dim-1, FEType, deg);
6881
6882 vec2D_dbl_ptr_Type quadPoints;
6883 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
6884 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
6885 w.reset();
6886
6887 SC elScaling;
6888 SmallMatrix<SC> B(dim);
6889 vec_dbl_Type b(dim);
6890 f->putScalar(0.);
6891 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
6892 int parameters;
6893
6894 std::vector<double> valueFunc(dim);
6895 SC* params = &(funcParameter[1]);
6896 for (UN T=0; T<elements->numberElements(); T++) {
6897 FiniteElement fe = elements->getElement( T );
6898 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
6899 for (int surface=0; surface<fe.numSubElements(); surface++) {
6900 FiniteElement feSub = subEl->getElement( surface );
6901 if (params[1] == feSub.getFlag()){
6902 FiniteElement feSub = subEl->getElement( surface );
6903 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
6904 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
6905 elScaling = B.computeScaling( );
6906 // loop over basis functions
6907 for (UN i=0; i < phi->at(0).size(); i++) {
6908 Teuchos::Array<SC> value(0);
6909 if ( fieldType == "Scalar" )
6910 value.resize( 1, 0. );
6911 else if ( fieldType == "Vector" )
6912 value.resize( dim, 0. );
6913 // loop over basis functions quadrature points
6914 for (UN w=0; w<phi->size(); w++) {
6915 vec_dbl_Type x(dim,0.); //coordinates
6916 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
6917 for (int l=0; l<dim-1; l++)
6918 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
6919 x[k] += b[k];
6920 }
6921
6922 func( &x[0], &valueFunc[0], params[0], params);
6923// func( &x[0], &valueFunc[0], params);
6924 if ( fieldType == "Scalar" )
6925 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
6926 else if ( fieldType == "Vector" ){
6927 for (int j=0; j<value.size(); j++){
6928 value[j] += weights->at(w) * valueFunc[j] * (*phi)[w][i];
6929 }
6930 }
6931 }
6932
6933 for (int j=0; j<value.size(); j++)
6934 value[j] *= elScaling;
6935
6936 if ( fieldType== "Scalar" )
6937 valuesF[ nodeList[ i ] ] += value[0];
6938
6939
6940 else if ( fieldType== "Vector" ){
6941 for (int j=0; j<value.size(); j++)
6942 valuesF[ dim * nodeList[ i ] + j ] += value[j];
6943 }
6944 }
6945 }
6946 }
6947
6948 }
6949}
6950
6951template <class SC, class LO, class GO, class NO>
6952void FE<SC,LO,GO,NO>::assemblyRHS( int dim,
6953 std::string FEType,
6954 MultiVectorPtr_Type a,
6955 std::string fieldType,
6956 RhsFunc_Type func,
6957 std::vector<SC>& funcParameter
6958 ) {
6959
6960 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
6961
6962 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
6963 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
6964 UN FEloc;
6965 FEloc = this->checkFE(dim,FEType);
6966
6967 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
6968
6969 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
6970
6971 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
6972 vec2D_dbl_ptr_Type phi;
6973 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6974
6975 // last parameter should alwayss be the degree
6976 //UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // TODO: [JK] Can we remove this?
6977 // inner( f(x), phi(x) ) requires the integration degree of the basis function + some
6978 // extra user-provided degree that accounts for the heterogeneity of f(x).
6979 UN degFunc = 2; // TODO: [JK] Hard coded for now, but needs to be passed by the user. See GitHub issue #66.
6980 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv0) + degFunc;
6981
6982 vec2D_dbl_ptr_Type quadPoints;
6983 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
6984
6985
6986 Helper::getPhi(phi, weights, dim, FEType, deg);
6987
6988 SC detB;
6989 SC absDetB;
6990 SmallMatrix<SC> B(dim);
6991 GO glob_i, glob_j;
6992 vec_dbl_Type v_i(dim);
6993 vec_dbl_Type v_j(dim);
6994
6995 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
6996 int parameters;
6997 double x;
6998 //for now just const!
6999 std::vector<double> valueFunc(dim);
7000 SC* paras = &(funcParameter[0]);
7001
7002 func( &x, &valueFunc[0], paras );
7003 SC value;
7004
7005 for (UN T=0; T<elements->numberElements(); T++) {
7006
7007 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
7008 detB = B.computeDet( );
7009 absDetB = std::fabs(detB);
7010
7011 vec2D_dbl_Type quadPointsTrans(weights->size(),vec_dbl_Type(dim));
7012 for(int i=0; i< weights->size(); i++){
7013 for(int j=0; j< dim ; j++){
7014 for(int k=0; k< dim; k++){
7015 quadPointsTrans[i][j] += B[j][k]* quadPoints->at(i).at(k) ;
7016 }
7017 quadPointsTrans[i][j] += pointsRep->at(elements->getElement(T).getNode(0)).at(j);
7018 }
7019 }
7020 for (UN i=0; i < phi->at(0).size(); i++) {
7021 if ( !fieldType.compare("Scalar") ) {
7022 value = Teuchos::ScalarTraits<SC>::zero();
7023 for (UN w=0; w<weights->size(); w++){
7024 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
7025 value += weights->at(w) * phi->at(w).at(i)*valueFunc[0];
7026 }
7027 value *= absDetB;
7028 LO row = (LO) elements->getElement(T).getNode(i);
7029 valuesRhs[row] += value;
7030 }
7031 else if( !fieldType.compare("Vector") ) {
7032 for (UN d=0; d<dim; d++) {
7033 value = Teuchos::ScalarTraits<SC>::zero();
7034 for (UN w=0; w<weights->size(); w++){
7035 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
7036 value += weights->at(w) * phi->at(w).at(i)*valueFunc[d];
7037 }
7038 value *= absDetB;
7039 SC v_i = value;
7040 LO row = (LO) ( dim * elements->getElement(T).getNode(i) + d );
7041 valuesRhs[row] += v_i;
7042 }
7043 }
7044 else
7045 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
7046 }
7047 }
7048}
7049
7050
7051
7056template <class SC, class LO, class GO, class NO>
7058 std::string FEType,
7059 MultiVectorPtr_Type a)
7060 {
7061
7062 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7063
7064 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "Multivector is null." );
7065
7066 UN FEloc;
7067 FEloc = this->checkFE(dim,FEType);
7068
7069 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
7070
7071 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
7072
7073 vec2D_dbl_ptr_Type phi;
7074 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7075
7076 UN deg = 2;
7077
7078 vec2D_dbl_ptr_Type quadPoints;
7079 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
7080
7081 Helper::getPhi(phi, weights, dim, FEType, deg);
7082
7083 SC detB;
7084 SC absDetB;
7085 SmallMatrix<SC> B(dim);
7086
7087 // Repeated version we assemble
7088 MultiVectorPtr_Type a_rep = Teuchos::rcp( new MultiVector_Type( this->domainVec_.at(FEloc)->getMapRepeated(), 1 ) );
7089 a_rep->putScalar(0.);
7090 Teuchos::ArrayRCP< SC > values_a = a_rep->getDataNonConst(0);
7091
7092 for (UN T=0; T<elements->numberElements(); T++) {
7093
7094 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
7095 detB = B.computeDet( );
7096 absDetB = std::fabs(detB);
7097
7098 for (UN i=0; i < phi->at(0).size(); i++) {
7099 Teuchos::Array<SC> value( 1, 0. );
7100 for (UN w=0; w<weights->size(); w++){
7101 value[0] += weights->at(w) * phi->at(w).at(i)*1.0; // We integrate the 1 function over the elements
7102 }
7103 value[0] *= absDetB;
7104 LO row = (LO) elements->getElement(T).getNode(i);
7105
7106 values_a[row] += value[0];
7107 }
7108 }
7109
7110 // Adding it together in the unique vector
7111 a->putScalar(0.);
7112 a->exportFromVector( a_rep, true, "Add" );
7113}
7114
7115
7116template <class SC, class LO, class GO, class NO>
7117void FE<SC,LO,GO,NO>::assemblyRHSDegTest( int dim,
7118 std::string FEType,
7119 MultiVectorPtr_Type a,
7120 std::string fieldType,
7121 RhsFunc_Type func,
7122 std::vector<SC>& funcParameter,
7123 int degree) {
7124 // TODO: [JK] What is the aim of this function? It is not called by any problems, only by a test.
7125 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7126
7127 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
7128 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
7129
7130 UN FEloc = this->checkFE(dim,FEType);
7131
7132 ElementsPtr_Type elements = this->domainVec_.at(FEloc)->getElementsC();
7133
7134 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(FEloc)->getPointsRepeated();
7135
7136 MapConstPtr_Type map = this->domainVec_.at(FEloc)->getMapRepeated();
7137 vec2D_dbl_ptr_Type phi;
7138 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7139 Helper::getPhi(phi, weights, dim, FEType, degree);
7140
7141 vec2D_dbl_ptr_Type quadPoints;
7142 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7143 Helper::getQuadratureValues(dim, degree, quadPoints, w, FEType);
7144 w.reset();
7145
7146
7147 SC detB;
7148 SC absDetB;
7149 SmallMatrix<SC> B(dim);
7150 vec_dbl_Type b(dim);
7151 GO glob_i, glob_j;
7152 vec_dbl_Type v_i(dim);
7153 vec_dbl_Type v_j(dim);
7154
7155 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
7156 int parameters;
7157 double x;
7158 //for now just const!
7159 std::vector<double> valueFunc(dim);
7160 SC* params = &(funcParameter[1]);
7161 for (UN T=0; T<elements->numberElements(); T++) {
7162
7163 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, b, FEType);
7164 detB = B.computeDet( );
7165 absDetB = std::fabs(detB);
7166
7167 for (UN i=0; i < phi->at(0).size(); i++) {
7168 Teuchos::Array<SC> value(1);
7169 for (UN w=0; w<weights->size(); w++){
7170 vec_dbl_Type x(dim,0.); //coordinates
7171 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7172 for (int l=0; l<dim; l++)
7173 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ] + b[k];
7174 }
7175
7176 func( &x[0], &valueFunc[0], params);
7177 if ( !fieldType.compare("Scalar") ) {
7178 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7179 }
7180 else if( !fieldType.compare("Vector") ) {
7181 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No test for field type Vector." );
7182 }
7183 else
7184 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
7185
7186 }
7187 value[0] *= absDetB;
7188 LO row = (LO) elements->getElement(T).getNode(i);
7189 valuesRhs[row] += value[0];
7190
7191 }
7192 }
7193}
7194
7195
7196template <class SC, class LO, class GO, class NO>
7197void FE<SC,LO,GO,NO>::buildFullDPhi(vec3D_dbl_ptr_Type dPhi, Teuchos::Array<SmallMatrix<double> >& dPhiMat){
7198
7199 TEUCHOS_TEST_FOR_EXCEPTION(dPhi->size()*dPhi->at(0).size()*dPhi->at(0).at(0).size() != dPhiMat.size(), std::logic_error, "Wrong sizes for dPhi and dPhiMat.");
7200
7201 int dim = dPhi->at(0).at(0).size();
7202 int nmbBasisFunc = dPhi->at(0).size();
7203 int nmbTotalBasisFunc = nmbBasisFunc * dim;
7204 if (dim==2) {
7205 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
7206 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
7207 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
7208 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
7209 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
7210 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
7211
7212 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
7213 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
7214 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
7215 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
7216 }
7217 }
7218 }
7219 else if(dim==3){
7220 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
7221 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
7222 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
7223 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
7224 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][2] = dPhi->at(p).at(i).at(2);
7225 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
7226 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
7227 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][2] = 0.;
7228 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][0] = 0.;
7229 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][1] = 0.;
7230 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][2] = 0.;
7231
7232 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
7233 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
7234 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][2] = 0.;
7235 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
7236 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
7237 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][2] = dPhi->at(p).at(i).at(2);
7238 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][0] = 0.;
7239 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][1] = 0.;
7240 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][2] = 0.;
7241
7242 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][0] = 0.;
7243 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][1] = 0.;
7244 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][2] = 0.;
7245 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][0] = 0.;
7246 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][1] = 0.;
7247 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][2] = 0.;
7248 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][0] = dPhi->at(p).at(i).at(0);
7249 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][1] = dPhi->at(p).at(i).at(1);
7250 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][2] = dPhi->at(p).at(i).at(2);
7251 }
7252 }
7253 }
7254}
7255
7256template <class SC, class LO, class GO, class NO>
7257void FE<SC,LO,GO,NO>::fillMatrixArray(SmallMatrix<double> &matIn, double* matArrayOut, std::string order,int offset){
7258 if (!order.compare("cols")) {
7259 for (int j=0; j<matIn.size(); j++) {
7260 for (int i=0; i<matIn.size(); i++) {
7261 matArrayOut[ j * matIn.size() + i + offset ] = matIn[i][j]; //Spalten der Matrix werden hintereinander in array geschrieben
7262 }
7263 }
7264 }
7265 else if(!order.compare("rows")) {
7266 for (int i=0; i<matIn.size(); i++) {
7267 for (int j=0; j<matIn.size(); j++) {
7268 matArrayOut[ i * matIn.size() + j + offset ] = matIn[i][j]; //Zeilen der Matrix werden hintereinander in array geschrieben
7269 }
7270 }
7271 }
7272 else
7273 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Unknown ordering for matrix to array conversion. Choose rows or cols.");
7274}
7275
7276template <class SC, class LO, class GO, class NO>
7277void FE<SC,LO,GO,NO>::epsilonTensor(vec_dbl_Type &basisValues, SmallMatrix<SC> &epsilonValues, int activeDof){
7278
7279 for (int i=0; i<epsilonValues.size(); i++) {
7280 for (int j=0; j<epsilonValues.size(); j++) {
7281 epsilonValues[i][j] = 0.;
7282 if (i==activeDof) {
7283 epsilonValues[i][j] += 0.5*basisValues.at(j);
7284 }
7285 if (j==activeDof) {
7286 epsilonValues[i][j] += 0.5*basisValues.at(i);
7287 }
7288 }
7289 }
7290}
7291
7292
7293/*************************************************************
7294 * AceGen 6.921 MacOSX (29 Jan 19) *
7295 * Co. J. Korelc 2013 12 Feb 19 12:07:04 *
7296 **************************************************************
7297 User : Full professional version
7298 Notebook : nh3d_C
7299 Evaluation time : 6 s Mode : Optimal
7300 Number of formulae : 181 Method: Automatic
7301 Subroutine : nh3d size: 4928
7302 Total size of Mathematica code : 4928 subexpressions
7303 Total size of C code : 10178 bytes */
7304/******************* S U B R O U T I N E *********************/
7305template <class SC, class LO, class GO, class NO>
7306void FE<SC,LO,GO,NO>::nh3d(double* v, double (*E), double (*Nu), double** F , double** Pmat, double**** Amat)
7307{
7308 v[356]=2e0*F[0][2];
7309 v[354]=2e0*F[0][1];
7310 v[323]=(*E)/(1e0+(*Nu));
7311 v[3]=((*Nu)*v[323])/(1e0-2e0*(*Nu));
7312 v[5]=v[323]/2e0;
7313 v[36]=v[5]/2e0;
7314 v[65]=2e0*F[0][1];
7315 v[86]=2e0*F[0][2];
7316 v[57]=2e0*F[1][0];
7317 v[66]=2e0*F[1][1];
7318 v[87]=2e0*F[1][2];
7319 v[58]=2e0*F[2][0];
7320 v[67]=2e0*F[2][1];
7321 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
7322 v[335]=(v[18]*v[18]);
7323 v[88]=2e0*F[2][2];
7324 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
7325 v[334]=(v[24]*v[24]);
7326 v[325]=v[18]*v[24];
7327 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
7328 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
7329 v[228]=-(F[2][1]*v[18]);
7330 v[225]=F[2][2]*v[18];
7331 v[217]=-(F[1][1]*v[18]);
7332 v[214]=F[1][2]*v[18];
7333 v[194]=-(F[2][0]*v[18]);
7334 v[185]=-(F[1][0]*v[18]);
7335 v[268]=F[2][1]*v[22];
7336 v[264]=-(F[2][2]*v[22]);
7337 v[255]=F[1][1]*v[22];
7338 v[251]=-(F[1][2]*v[22]);
7339 v[190]=-(F[2][0]*v[22]);
7340 v[181]=-(F[1][0]*v[22]);
7341 v[172]=-(F[0][0]*v[22]);
7342 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
7343 v[324]=-(v[20]*v[22]);
7344 v[327]=2e0*(v[324]+v[325]);
7345 v[94]=v[20]*v[88];
7346 v[92]=v[20]*v[87];
7347 v[90]=v[20]*v[86];
7348 v[138]=v[15]*v[20]-v[335];
7349 v[270]=F[2][0]*v[24];
7350 v[260]=-(F[2][2]*v[24]);
7351 v[257]=F[1][0]*v[24];
7352 v[247]=-(F[1][2]*v[24]);
7353 v[244]=F[0][0]*v[24];
7354 v[232]=-(F[0][2]*v[24]);
7355 v[222]=-(F[2][1]*v[24]);
7356 v[211]=-(F[1][1]*v[24]);
7357 v[198]=-(F[0][1]*v[24]);
7358 v[168]=v[18]*v[22]-v[15]*v[24];
7359 v[331]=2e0*v[168];
7360 v[329]=2e0*v[168];
7361 v[326]=2e0*v[168];
7362 v[38]=-(v[22]*v[22]);
7363 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
7364 v[333]=v[20]*v[26]-v[334];
7365 v[351]=2e0*F[0][0]*v[333];
7366 v[236]=v[22]*v[24]-v[18]*v[26];
7367 v[332]=2e0*v[236];
7368 v[330]=2e0*v[236];
7369 v[328]=2e0*v[236];
7370 v[99]=v[26]*v[58];
7371 v[97]=v[26]*v[57];
7372 v[93]=v[26]*v[67];
7373 v[91]=v[26]*v[66];
7374 v[89]=v[26]*v[65];
7375 v[148]=v[15]*v[26]+v[38];
7376 v[29]=v[148]*v[20]+2e0*v[22]*v[325]-v[15]*v[334]-v[26]*v[335];
7377 v[336]=1e0/Power(v[29],2);
7378 v[32]=-v[5]+v[3]*std::log(std::sqrt(v[29]));
7379 v[337]=(v[3]/4e0-v[32]/2e0)*v[336];
7380 v[137]=v[337]*(F[2][1]*v[326]+F[2][0]*v[327]-v[335]*v[88]+v[15]*v[94]);
7381 v[147]=v[137]*v[138];
7382 v[136]=v[337]*(F[2][2]*v[329]+F[2][0]*v[330]+v[38]*v[67]+v[15]*v[93]);
7383 v[156]=v[136]*v[148];
7384 v[135]=v[337]*(F[2][2]*v[327]+F[2][1]*v[328]-v[334]*v[58]+v[20]*v[99]);
7385 v[165]=v[135]*v[333];
7386 v[134]=v[337]*(F[1][1]*v[326]+F[1][0]*v[327]-v[335]*v[87]+v[15]*v[92]);
7387 v[144]=v[134]*v[138];
7388 v[133]=v[337]*(F[1][2]*v[331]+F[1][0]*v[332]+v[38]*v[66]+v[15]*v[91]);
7389 v[153]=v[133]*v[148];
7390 v[132]=v[337]*(F[1][2]*v[327]+F[1][1]*v[328]-v[334]*v[57]+v[20]*v[97]);
7391 v[162]=v[132]*v[333];
7392 v[131]=v[337]*(F[0][0]*v[327]+F[0][1]*v[329]-v[335]*v[86]+v[15]*v[90]);
7393 v[130]=v[337]*(F[0][2]*v[331]+F[0][0]*v[332]+v[38]*v[65]+v[15]*v[89]);
7394 v[128]=v[337]*(F[0][2]*v[327]+F[0][1]*v[330]+v[351]);
7395 v[37]=v[32]/(2e0*v[29]);
7396 v[355]=v[37]*(2e0*v[172]+v[15]*v[86]);
7397 v[353]=v[37]*(2e0*v[232]+v[89]);
7398 v[352]=v[37]*(2e0*v[198]+v[90]);
7399 v[349]=-2e0*(F[1][0]*v[20]+v[217])*v[37];
7400 v[348]=-(v[37]*(2e0*v[185]+v[15]*v[66]));
7401 v[347]=-2e0*(F[2][0]*v[20]+v[228])*v[37];
7402 v[346]=-(v[37]*(2e0*v[194]+v[15]*v[67]));
7403 v[345]=-(v[37]*(2e0*v[251]+v[97]));
7404 v[344]=-(v[37]*(2e0*v[181]+v[15]*v[87]));
7405 v[343]=-(v[37]*(2e0*v[264]+v[99]));
7406 v[342]=-(v[37]*(2e0*v[190]+v[15]*v[88]));
7407 v[341]=-(v[37]*(2e0*v[247]+v[91]));
7408 v[340]=-(v[37]*(2e0*v[211]+v[92]));
7409 v[339]=-(v[37]*(2e0*v[260]+v[93]));
7410 v[338]=-(v[37]*(2e0*v[222]+v[94]));
7411 v[272]=v[137]*v[328]+v[37]*(2e0*v[268]+2e0*v[270]-2e0*v[18]*v[88]);
7412 v[267]=v[136]*v[328]+v[343];
7413 v[263]=v[135]*v[328]+v[339];
7414 v[259]=v[134]*v[328]+v[37]*(2e0*v[255]+2e0*v[257]-2e0*v[18]*v[87]);
7415 v[254]=v[133]*v[328]+v[345];
7416 v[250]=v[132]*v[328]+v[341];
7417 v[246]=v[131]*v[328]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[244]-2e0*v[18]*v[86]);
7418 v[241]=v[130]*v[328]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
7419 v[231]=v[137]*v[327]+v[347];
7420 v[227]=v[136]*v[327]+v[37]*(2e0*v[225]+2e0*v[270]-2e0*v[22]*v[67]);
7421 v[224]=v[135]*v[327]+v[338];
7422 v[301]=2e0*F[1][0]*v[165]+F[1][2]*v[224]+F[1][1]*v[263];
7423 v[279]=2e0*F[0][0]*v[165]+F[0][2]*v[224]+F[0][1]*v[263];
7424 v[220]=v[134]*v[327]+v[349];
7425 v[216]=v[133]*v[327]+v[37]*(2e0*v[214]+2e0*v[257]-2e0*v[22]*v[66]);
7426 v[213]=v[132]*v[327]+v[340];
7427 v[276]=2e0*F[0][0]*v[162]+F[0][2]*v[213]+F[0][1]*v[250];
7428 v[209]=v[131]*v[327]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
7429 v[196]=v[137]*v[326]+v[346];
7430 v[314]=2e0*F[1][2]*v[147]+F[1][1]*v[196]+F[1][0]*v[231];
7431 v[296]=2e0*F[0][2]*v[147]+F[0][1]*v[196]+F[0][0]*v[231];
7432 v[192]=v[136]*v[326]+v[342];
7433 v[308]=2e0*F[1][1]*v[156]+F[1][2]*v[192]+F[1][0]*v[267];
7434 v[288]=2e0*F[0][1]*v[156]+F[0][2]*v[192]+F[0][0]*v[267];
7435 v[188]=v[135]*v[326]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[24]*v[58]);
7436 v[187]=v[134]*v[326]+v[348];
7437 v[293]=2e0*F[0][2]*v[144]+F[0][1]*v[187]+F[0][0]*v[220];
7438 v[183]=v[133]*v[326]+v[344];
7439 v[285]=2e0*F[0][1]*v[153]+F[0][2]*v[183]+F[0][0]*v[254];
7440 v[179]=v[132]*v[326]+v[37]*(2e0*v[214]+2e0*v[255]-2e0*v[24]*v[57]);
7441 v[178]=v[131]*v[326]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
7442 v[167]=v[137]*v[333]-v[338];
7443 v[303]=2e0*F[1][0]*v[167]+F[1][2]*v[231]+F[1][1]*v[272];
7444 v[281]=2e0*F[0][0]*v[167]+F[0][2]*v[231]+F[0][1]*v[272];
7445 v[166]=v[136]*v[333]-v[339];
7446 v[302]=2e0*F[1][0]*v[166]+F[1][2]*v[227]+F[1][1]*v[267];
7447 v[280]=2e0*F[0][0]*v[166]+F[0][2]*v[227]+F[0][1]*v[267];
7448 v[164]=v[134]*v[333]-v[340];
7449 v[278]=2e0*F[0][0]*v[164]+F[0][2]*v[220]+F[0][1]*v[259];
7450 v[163]=v[133]*v[333]-v[341];
7451 v[277]=2e0*F[0][0]*v[163]+F[0][2]*v[216]+F[0][1]*v[254];
7452 v[157]=v[137]*v[148]-v[342];
7453 v[309]=2e0*F[1][1]*v[157]+F[1][2]*v[196]+F[1][0]*v[272];
7454 v[289]=2e0*F[0][1]*v[157]+F[0][2]*v[196]+F[0][0]*v[272];
7455 v[155]=v[135]*v[148]-v[343];
7456 v[307]=2e0*F[1][1]*v[155]+F[1][2]*v[188]+F[1][0]*v[263];
7457 v[287]=2e0*F[0][1]*v[155]+F[0][2]*v[188]+F[0][0]*v[263];
7458 v[154]=v[134]*v[148]-v[344];
7459 v[286]=2e0*F[0][1]*v[154]+F[0][2]*v[187]+F[0][0]*v[259];
7460 v[284]=F[0][2]*v[179]+F[0][0]*v[250]+2e0*F[0][1]*(v[132]*v[148]-v[345]);
7461 v[146]=v[136]*v[138]-v[346];
7462 v[313]=2e0*F[1][2]*v[146]+F[1][1]*v[192]+F[1][0]*v[227];
7463 v[295]=2e0*F[0][2]*v[146]+F[0][1]*v[192]+F[0][0]*v[227];
7464 v[145]=v[135]*v[138]-v[347];
7465 v[312]=2e0*F[1][2]*v[145]+F[1][1]*v[188]+F[1][0]*v[224];
7466 v[294]=2e0*F[0][2]*v[145]+F[0][1]*v[188]+F[0][0]*v[224];
7467 v[292]=F[0][1]*v[183]+F[0][0]*v[216]+2e0*F[0][2]*(v[133]*v[138]-v[348]);
7468 v[291]=F[0][1]*v[179]+F[0][0]*v[213]+(v[132]*v[138]-v[349])*v[356];
7469 v[35]=v[36]+v[138]*v[37];
7470 v[310]=2e0*v[35];
7471 v[40]=v[36]+v[148]*v[37];
7472 v[304]=2e0*v[40];
7473 v[43]=v[36]+v[333]*v[37];
7474 v[297]=2e0*v[43];
7475 v[44]=v[326]*v[37];
7476 v[319]=2e0*F[2][1]*v[157]+F[2][2]*v[196]+F[2][0]*v[272]+v[44];
7477 v[306]=2e0*F[1][1]*v[154]+F[1][2]*v[187]+F[1][0]*v[259]+v[44];
7478 v[283]=F[0][2]*v[178]+F[0][0]*v[246]+v[354]*(v[131]*v[148]+v[355])+v[44];
7479 v[45]=v[327]*v[37];
7480 v[317]=2e0*F[2][0]*v[167]+F[2][2]*v[231]+F[2][1]*v[272]+v[45];
7481 v[300]=2e0*F[1][0]*v[164]+F[1][2]*v[220]+F[1][1]*v[259]+v[45];
7482 v[275]=F[0][2]*v[209]+F[0][1]*v[246]+2e0*F[0][0]*(v[131]*v[333]+v[352])+v[45];
7483 v[46]=v[328]*v[37];
7484 v[316]=2e0*F[2][0]*v[166]+F[2][2]*v[227]+F[2][1]*v[267]+v[46];
7485 v[299]=2e0*F[1][0]*v[163]+F[1][2]*v[216]+F[1][1]*v[254]+v[46];
7486 v[274]=F[0][1]*v[241]+2e0*F[0][0]*(v[130]*v[333]+v[353])+v[46]+F[0][2]*(v[130]*v[327]+v[37]*
7487 (2e0*F[0][2]*v[18]+2e0*v[244]-2e0*v[22]*v[65]));
7488 Pmat[0][0]=F[0][0]*v[297]+F[0][2]*v[45]+F[0][1]*v[46];
7489 Pmat[0][1]=F[0][1]*v[304]+F[0][2]*v[44]+F[0][0]*v[46];
7490 Pmat[0][2]=F[0][2]*v[310]+F[0][1]*v[44]+F[0][0]*v[45];
7491 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[45]+F[1][1]*v[46];
7492 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[44]+F[1][0]*v[46];
7493 Pmat[1][2]=2e0*F[1][2]*v[35]+F[1][1]*v[44]+F[1][0]*v[45];
7494 Pmat[2][0]=F[2][0]*v[297]+F[2][2]*v[45]+F[2][1]*v[46];
7495 Pmat[2][1]=F[2][1]*v[304]+F[2][2]*v[44]+F[2][0]*v[46];
7496 Pmat[2][2]=F[2][2]*v[310]+F[2][1]*v[44]+F[2][0]*v[45];
7497 Amat[0][0][0][0]=v[297]+v[128]*v[351]+F[0][2]*(v[128]*v[327]-v[352])+F[0][1]*(v[128]*v[328]-v[353]
7498 );
7499 Amat[0][0][0][1]=v[274];
7500 Amat[0][0][0][2]=v[275];
7501 Amat[0][0][1][0]=v[276];
7502 Amat[0][0][1][1]=v[277];
7503 Amat[0][0][1][2]=v[278];
7504 Amat[0][0][2][0]=v[279];
7505 Amat[0][0][2][1]=v[280];
7506 Amat[0][0][2][2]=v[281];
7507 Amat[0][1][0][0]=v[274];
7508 Amat[0][1][0][1]=F[0][0]*v[241]+v[304]+v[130]*v[148]*v[354]+F[0][2]*(v[130]*v[326]-v[355]);
7509 Amat[0][1][0][2]=v[283];
7510 Amat[0][1][1][0]=v[284];
7511 Amat[0][1][1][1]=v[285];
7512 Amat[0][1][1][2]=v[286];
7513 Amat[0][1][2][0]=v[287];
7514 Amat[0][1][2][1]=v[288];
7515 Amat[0][1][2][2]=v[289];
7516 Amat[0][2][0][0]=v[275];
7517 Amat[0][2][0][1]=v[283];
7518 Amat[0][2][0][2]=F[0][1]*v[178]+F[0][0]*v[209]+v[310]+v[131]*v[138]*v[356];
7519 Amat[0][2][1][0]=v[291];
7520 Amat[0][2][1][1]=v[292];
7521 Amat[0][2][1][2]=v[293];
7522 Amat[0][2][2][0]=v[294];
7523 Amat[0][2][2][1]=v[295];
7524 Amat[0][2][2][2]=v[296];
7525 Amat[1][0][0][0]=v[276];
7526 Amat[1][0][0][1]=v[284];
7527 Amat[1][0][0][2]=v[291];
7528 Amat[1][0][1][0]=2e0*F[1][0]*v[162]+F[1][2]*v[213]+F[1][1]*v[250]+v[297];
7529 Amat[1][0][1][1]=v[299];
7530 Amat[1][0][1][2]=v[300];
7531 Amat[1][0][2][0]=v[301];
7532 Amat[1][0][2][1]=v[302];
7533 Amat[1][0][2][2]=v[303];
7534 Amat[1][1][0][0]=v[277];
7535 Amat[1][1][0][1]=v[285];
7536 Amat[1][1][0][2]=v[292];
7537 Amat[1][1][1][0]=v[299];
7538 Amat[1][1][1][1]=2e0*F[1][1]*v[153]+F[1][2]*v[183]+F[1][0]*v[254]+v[304];
7539 Amat[1][1][1][2]=v[306];
7540 Amat[1][1][2][0]=v[307];
7541 Amat[1][1][2][1]=v[308];
7542 Amat[1][1][2][2]=v[309];
7543 Amat[1][2][0][0]=v[278];
7544 Amat[1][2][0][1]=v[286];
7545 Amat[1][2][0][2]=v[293];
7546 Amat[1][2][1][0]=v[300];
7547 Amat[1][2][1][1]=v[306];
7548 Amat[1][2][1][2]=2e0*F[1][2]*v[144]+F[1][1]*v[187]+F[1][0]*v[220]+v[310];
7549 Amat[1][2][2][0]=v[312];
7550 Amat[1][2][2][1]=v[313];
7551 Amat[1][2][2][2]=v[314];
7552 Amat[2][0][0][0]=v[279];
7553 Amat[2][0][0][1]=v[287];
7554 Amat[2][0][0][2]=v[294];
7555 Amat[2][0][1][0]=v[301];
7556 Amat[2][0][1][1]=v[307];
7557 Amat[2][0][1][2]=v[312];
7558 Amat[2][0][2][0]=2e0*F[2][0]*v[165]+F[2][2]*v[224]+F[2][1]*v[263]+v[297];
7559 Amat[2][0][2][1]=v[316];
7560 Amat[2][0][2][2]=v[317];
7561 Amat[2][1][0][0]=v[280];
7562 Amat[2][1][0][1]=v[288];
7563 Amat[2][1][0][2]=v[295];
7564 Amat[2][1][1][0]=v[302];
7565 Amat[2][1][1][1]=v[308];
7566 Amat[2][1][1][2]=v[313];
7567 Amat[2][1][2][0]=v[316];
7568 Amat[2][1][2][1]=2e0*F[2][1]*v[156]+F[2][2]*v[192]+F[2][0]*v[267]+v[304];
7569 Amat[2][1][2][2]=v[319];
7570 Amat[2][2][0][0]=v[281];
7571 Amat[2][2][0][1]=v[289];
7572 Amat[2][2][0][2]=v[296];
7573 Amat[2][2][1][0]=v[303];
7574 Amat[2][2][1][1]=v[309];
7575 Amat[2][2][1][2]=v[314];
7576 Amat[2][2][2][0]=v[317];
7577 Amat[2][2][2][1]=v[319];
7578 Amat[2][2][2][2]=2e0*F[2][2]*v[147]+F[2][1]*v[196]+F[2][0]*v[231]+v[310];
7579}
7580
7581
7582/*************************************************************
7583 * AceGen 6.921 MacOSX (29 Jan 19) *
7584 * Co. J. Korelc 2013 12 Feb 19 12:06:46 *
7585 **************************************************************
7586 User : Full professional version
7587 Notebook : mr3d_C
7588 Evaluation time : 7 s Mode : Optimal
7589 Number of formulae : 190 Method: Automatic
7590 Subroutine : mr3d size: 5215
7591 Total size of Mathematica code : 5215 subexpressions
7592 Total size of C code : 10798 bytes */
7593
7594/******************* S U B R O U T I N E *********************/
7595template <class SC, class LO, class GO, class NO>
7596void FE<SC,LO,GO,NO>::mr3d(double* v,double (*E),double (*Nu),double (*C)
7597 ,double** F,double** Pmat,double**** Amat)
7598{
7599 v[366]=2e0*F[0][2];
7600 v[364]=2e0*F[0][1];
7601 v[4]=(*E)/(2e0+2e0*(*Nu));
7602 v[139]=((*C)*v[4])/2e0;
7603 v[5]=(*E)/(3e0-6e0*(*Nu));
7604 v[57]=2e0*F[0][0];
7605 v[150]=v[139]*v[57];
7606 v[66]=2e0*F[0][1];
7607 v[165]=v[139]*v[66];
7608 v[87]=2e0*F[0][2];
7609 v[167]=v[139]*v[87];
7610 v[58]=2e0*F[1][0];
7611 v[155]=v[139]*v[58];
7612 v[67]=2e0*F[1][1];
7613 v[170]=v[139]*v[67];
7614 v[88]=2e0*F[1][2];
7615 v[172]=v[139]*v[88];
7616 v[59]=2e0*F[2][0];
7617 v[159]=v[139]*v[59];
7618 v[68]=2e0*F[2][1];
7619 v[175]=v[139]*v[68];
7620 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
7621 v[345]=(v[18]*v[18]);
7622 v[89]=2e0*F[2][2];
7623 v[177]=v[139]*v[89];
7624 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
7625 v[344]=(v[24]*v[24]);
7626 v[335]=v[18]*v[24];
7627 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
7628 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
7629 v[239]=-(F[2][1]*v[18]);
7630 v[236]=F[2][2]*v[18];
7631 v[228]=-(F[1][1]*v[18]);
7632 v[225]=F[1][2]*v[18];
7633 v[205]=-(F[2][0]*v[18]);
7634 v[196]=-(F[1][0]*v[18]);
7635 v[279]=F[2][1]*v[22];
7636 v[275]=-(F[2][2]*v[22]);
7637 v[266]=F[1][1]*v[22];
7638 v[262]=-(F[1][2]*v[22]);
7639 v[201]=-(F[2][0]*v[22]);
7640 v[192]=-(F[1][0]*v[22]);
7641 v[183]=-(F[0][0]*v[22]);
7642 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
7643 v[334]=-(v[20]*v[22]);
7644 v[337]=2e0*(v[334]+v[335]);
7645 v[95]=v[20]*v[89];
7646 v[93]=v[20]*v[88];
7647 v[91]=v[20]*v[87];
7648 v[140]=v[15]*v[20]-v[345];
7649 v[281]=F[2][0]*v[24];
7650 v[271]=-(F[2][2]*v[24]);
7651 v[268]=F[1][0]*v[24];
7652 v[258]=-(F[1][2]*v[24]);
7653 v[255]=F[0][0]*v[24];
7654 v[243]=-(F[0][2]*v[24]);
7655 v[233]=-(F[2][1]*v[24]);
7656 v[222]=-(F[1][1]*v[24]);
7657 v[209]=-(F[0][1]*v[24]);
7658 v[179]=v[18]*v[22]-v[15]*v[24];
7659 v[341]=2e0*v[179];
7660 v[339]=2e0*v[179];
7661 v[336]=2e0*v[179];
7662 v[38]=-(v[22]*v[22]);
7663 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
7664 v[343]=v[20]*v[26]-v[344];
7665 v[361]=v[343]*v[57];
7666 v[247]=v[22]*v[24]-v[18]*v[26];
7667 v[342]=2e0*v[247];
7668 v[340]=2e0*v[247];
7669 v[338]=2e0*v[247];
7670 v[100]=v[26]*v[59];
7671 v[98]=v[26]*v[58];
7672 v[94]=v[26]*v[68];
7673 v[92]=v[26]*v[67];
7674 v[90]=v[26]*v[66];
7675 v[151]=v[15]*v[26]+v[38];
7676 v[29]=v[151]*v[20]+2e0*v[22]*v[335]-v[15]*v[344]-v[26]*v[345];
7677 v[346]=1e0/Power(v[29],2);
7678 v[33]=-2e0*v[139]-v[4]+v[5]*std::log(std::sqrt(v[29]));
7679 v[347]=v[346]*(-v[33]/2e0+v[5]/4e0);
7680 v[138]=v[347]*(F[2][1]*v[336]+F[2][0]*v[337]-v[345]*v[89]+v[15]*v[95]);
7681 v[149]=v[138]*v[140];
7682 v[137]=v[347]*(F[2][2]*v[339]+F[2][0]*v[340]+v[38]*v[68]+v[15]*v[94]);
7683 v[161]=v[137]*v[151];
7684 v[136]=v[347]*(v[100]*v[20]+F[2][2]*v[337]+F[2][1]*v[338]-v[344]*v[59]);
7685 v[174]=v[136]*v[343];
7686 v[135]=v[347]*(F[1][1]*v[336]+F[1][0]*v[337]-v[345]*v[88]+v[15]*v[93]);
7687 v[146]=v[135]*v[140];
7688 v[134]=v[347]*(F[1][2]*v[341]+F[1][0]*v[342]+v[38]*v[67]+v[15]*v[92]);
7689 v[157]=v[134]*v[151];
7690 v[133]=v[347]*(F[1][2]*v[337]+F[1][1]*v[338]-v[344]*v[58]+v[20]*v[98]);
7691 v[169]=v[133]*v[343];
7692 v[132]=v[347]*(F[0][0]*v[337]+F[0][1]*v[339]-v[345]*v[87]+v[15]*v[91]);
7693 v[131]=v[347]*(F[0][2]*v[341]+F[0][0]*v[342]+v[38]*v[66]+v[15]*v[90]);
7694 v[129]=v[347]*(F[0][2]*v[337]+F[0][1]*v[340]+v[361]);
7695 v[37]=v[33]/(2e0*v[29]);
7696 v[365]=v[37]*(2e0*v[183]+v[15]*v[87]);
7697 v[363]=v[37]*(2e0*v[243]+v[90]);
7698 v[362]=v[37]*(2e0*v[209]+v[91]);
7699 v[359]=-2e0*(F[1][0]*v[20]+v[228])*v[37];
7700 v[358]=-(v[37]*(2e0*v[196]+v[15]*v[67]));
7701 v[357]=-2e0*(F[2][0]*v[20]+v[239])*v[37];
7702 v[356]=-(v[37]*(2e0*v[205]+v[15]*v[68]));
7703 v[355]=-(v[37]*(2e0*v[262]+v[98]));
7704 v[354]=-(v[37]*(2e0*v[192]+v[15]*v[88]));
7705 v[353]=-((v[100]+2e0*v[275])*v[37]);
7706 v[352]=-(v[37]*(2e0*v[201]+v[15]*v[89]));
7707 v[351]=-(v[37]*(2e0*v[258]+v[92]));
7708 v[350]=-(v[37]*(2e0*v[222]+v[93]));
7709 v[349]=-(v[37]*(2e0*v[271]+v[94]));
7710 v[348]=-(v[37]*(2e0*v[233]+v[95]));
7711 v[283]=v[138]*v[338]+v[37]*(2e0*v[279]+2e0*v[281]-2e0*v[18]*v[89]);
7712 v[278]=-v[159]+v[137]*v[338]+v[353];
7713 v[274]=-v[175]+v[136]*v[338]+v[349];
7714 v[270]=v[135]*v[338]+v[37]*(2e0*v[266]+2e0*v[268]-2e0*v[18]*v[88]);
7715 v[265]=-v[155]+v[134]*v[338]+v[355];
7716 v[261]=-v[170]+v[133]*v[338]+v[351];
7717 v[257]=v[132]*v[338]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[255]-2e0*v[18]*v[87]);
7718 v[252]=-v[150]+v[131]*v[338]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
7719 v[242]=-v[159]+v[138]*v[337]+v[357];
7720 v[238]=v[137]*v[337]+v[37]*(2e0*v[236]+2e0*v[281]-2e0*v[22]*v[68]);
7721 v[235]=-v[177]+v[136]*v[337]+v[348];
7722 v[312]=2e0*F[1][0]*v[174]+F[1][2]*v[235]+F[1][1]*v[274];
7723 v[290]=2e0*F[0][0]*v[174]+F[0][2]*v[235]+F[0][1]*v[274];
7724 v[231]=-v[155]+v[135]*v[337]+v[359];
7725 v[227]=v[134]*v[337]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[22]*v[67]);
7726 v[224]=-v[172]+v[133]*v[337]+v[350];
7727 v[287]=2e0*F[0][0]*v[169]+F[0][2]*v[224]+F[0][1]*v[261];
7728 v[220]=-v[150]+v[132]*v[337]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
7729 v[207]=-v[175]+v[138]*v[336]+v[356];
7730 v[325]=2e0*F[1][2]*v[149]+F[1][1]*v[207]+F[1][0]*v[242];
7731 v[307]=2e0*F[0][2]*v[149]+F[0][1]*v[207]+F[0][0]*v[242];
7732 v[203]=-v[177]+v[137]*v[336]+v[352];
7733 v[319]=2e0*F[1][1]*v[161]+F[1][2]*v[203]+F[1][0]*v[278];
7734 v[299]=2e0*F[0][1]*v[161]+F[0][2]*v[203]+F[0][0]*v[278];
7735 v[199]=v[136]*v[336]+v[37]*(2e0*v[236]+2e0*v[279]-2e0*v[24]*v[59]);
7736 v[198]=-v[170]+v[135]*v[336]+v[358];
7737 v[304]=2e0*F[0][2]*v[146]+F[0][1]*v[198]+F[0][0]*v[231];
7738 v[194]=-v[172]+v[134]*v[336]+v[354];
7739 v[296]=2e0*F[0][1]*v[157]+F[0][2]*v[194]+F[0][0]*v[265];
7740 v[190]=v[133]*v[336]+v[37]*(2e0*v[225]+2e0*v[266]-2e0*v[24]*v[58]);
7741 v[189]=-v[165]+v[132]*v[336]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
7742 v[178]=v[177]+v[138]*v[343]-v[348];
7743 v[314]=2e0*F[1][0]*v[178]+F[1][2]*v[242]+F[1][1]*v[283];
7744 v[292]=2e0*F[0][0]*v[178]+F[0][2]*v[242]+F[0][1]*v[283];
7745 v[176]=v[175]+v[137]*v[343]-v[349];
7746 v[313]=2e0*F[1][0]*v[176]+F[1][2]*v[238]+F[1][1]*v[278];
7747 v[291]=2e0*F[0][0]*v[176]+F[0][2]*v[238]+F[0][1]*v[278];
7748 v[173]=v[172]+v[135]*v[343]-v[350];
7749 v[289]=2e0*F[0][0]*v[173]+F[0][2]*v[231]+F[0][1]*v[270];
7750 v[171]=v[170]+v[134]*v[343]-v[351];
7751 v[288]=2e0*F[0][0]*v[171]+F[0][2]*v[227]+F[0][1]*v[265];
7752 v[162]=v[138]*v[151]+v[177]-v[352];
7753 v[320]=2e0*F[1][1]*v[162]+F[1][2]*v[207]+F[1][0]*v[283];
7754 v[300]=2e0*F[0][1]*v[162]+F[0][2]*v[207]+F[0][0]*v[283];
7755 v[160]=v[136]*v[151]+v[159]-v[353];
7756 v[318]=2e0*F[1][1]*v[160]+F[1][2]*v[199]+F[1][0]*v[274];
7757 v[298]=2e0*F[0][1]*v[160]+F[0][2]*v[199]+F[0][0]*v[274];
7758 v[158]=v[135]*v[151]+v[172]-v[354];
7759 v[297]=2e0*F[0][1]*v[158]+F[0][2]*v[198]+F[0][0]*v[270];
7760 v[295]=F[0][2]*v[190]+F[0][0]*v[261]+2e0*F[0][1]*(v[133]*v[151]+v[155]-v[355]);
7761 v[148]=v[137]*v[140]+v[175]-v[356];
7762 v[324]=2e0*F[1][2]*v[148]+F[1][1]*v[203]+F[1][0]*v[238];
7763 v[306]=2e0*F[0][2]*v[148]+F[0][1]*v[203]+F[0][0]*v[238];
7764 v[147]=v[136]*v[140]+v[159]-v[357];
7765 v[323]=2e0*F[1][2]*v[147]+F[1][1]*v[199]+F[1][0]*v[235];
7766 v[305]=2e0*F[0][2]*v[147]+F[0][1]*v[199]+F[0][0]*v[235];
7767 v[303]=F[0][1]*v[194]+F[0][0]*v[227]+2e0*F[0][2]*(v[134]*v[140]+v[170]-v[358]);
7768 v[302]=F[0][1]*v[190]+F[0][0]*v[224]+(v[133]*v[140]+v[155]-v[359])*v[366];
7769 v[36]=v[140]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[20]))*v[4])/2e0;
7770 v[321]=2e0*v[36];
7771 v[40]=v[151]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[26]))*v[4])/2e0;
7772 v[315]=2e0*v[40];
7773 v[43]=v[343]*v[37]+((1e0+(*C)*(-1e0+v[20]+v[26]))*v[4])/2e0;
7774 v[308]=2e0*v[43];
7775 v[45]=-2e0*v[139]*v[24]+v[336]*v[37];
7776 v[330]=2e0*F[2][1]*v[162]+F[2][2]*v[207]+F[2][0]*v[283]+v[45];
7777 v[317]=2e0*F[1][1]*v[158]+F[1][2]*v[198]+F[1][0]*v[270]+v[45];
7778 v[294]=F[0][2]*v[189]+F[0][0]*v[257]+v[364]*(v[132]*v[151]+v[167]+v[365])+v[45];
7779 v[46]=-2e0*v[139]*v[22]+v[337]*v[37];
7780 v[328]=2e0*F[2][0]*v[178]+F[2][2]*v[242]+F[2][1]*v[283]+v[46];
7781 v[311]=2e0*F[1][0]*v[173]+F[1][2]*v[231]+F[1][1]*v[270]+v[46];
7782 v[286]=F[0][2]*v[220]+F[0][1]*v[257]+2e0*F[0][0]*(v[167]+v[132]*v[343]+v[362])+v[46];
7783 v[47]=-2e0*v[139]*v[18]+v[338]*v[37];
7784 v[327]=2e0*F[2][0]*v[176]+F[2][2]*v[238]+F[2][1]*v[278]+v[47];
7785 v[310]=2e0*F[1][0]*v[171]+F[1][2]*v[227]+F[1][1]*v[265]+v[47];
7786 v[285]=F[0][1]*v[252]+2e0*F[0][0]*(v[165]+v[131]*v[343]+v[363])+v[47]+F[0][2]*(v[131]*v[337]+v[37]*
7787 (2e0*F[0][2]*v[18]+2e0*v[255]-2e0*v[22]*v[66]));
7788 Pmat[0][0]=F[0][0]*v[308]+F[0][2]*v[46]+F[0][1]*v[47];
7789 Pmat[0][1]=F[0][1]*v[315]+F[0][2]*v[45]+F[0][0]*v[47];
7790 Pmat[0][2]=F[0][2]*v[321]+F[0][1]*v[45]+F[0][0]*v[46];
7791 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[46]+F[1][1]*v[47];
7792 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[45]+F[1][0]*v[47];
7793 Pmat[1][2]=2e0*F[1][2]*v[36]+F[1][1]*v[45]+F[1][0]*v[46];
7794 Pmat[2][0]=F[2][0]*v[308]+F[2][2]*v[46]+F[2][1]*v[47];
7795 Pmat[2][1]=F[2][1]*v[315]+F[2][2]*v[45]+F[2][0]*v[47];
7796 Pmat[2][2]=F[2][2]*v[321]+F[2][1]*v[45]+F[2][0]*v[46];
7797 Amat[0][0][0][0]=v[308]+v[129]*v[361]+F[0][2]*(-v[167]+v[129]*v[337]-v[362])+F[0][1]*(-v[165]
7798 +v[129]*v[338]-v[363]);
7799 Amat[0][0][0][1]=v[285];
7800 Amat[0][0][0][2]=v[286];
7801 Amat[0][0][1][0]=v[287];
7802 Amat[0][0][1][1]=v[288];
7803 Amat[0][0][1][2]=v[289];
7804 Amat[0][0][2][0]=v[290];
7805 Amat[0][0][2][1]=v[291];
7806 Amat[0][0][2][2]=v[292];
7807 Amat[0][1][0][0]=v[285];
7808 Amat[0][1][0][1]=F[0][0]*v[252]+v[315]+v[131]*v[151]*v[364]+F[0][2]*(-v[167]+v[131]*v[336]-v[365]);
7809 Amat[0][1][0][2]=v[294];
7810 Amat[0][1][1][0]=v[295];
7811 Amat[0][1][1][1]=v[296];
7812 Amat[0][1][1][2]=v[297];
7813 Amat[0][1][2][0]=v[298];
7814 Amat[0][1][2][1]=v[299];
7815 Amat[0][1][2][2]=v[300];
7816 Amat[0][2][0][0]=v[286];
7817 Amat[0][2][0][1]=v[294];
7818 Amat[0][2][0][2]=F[0][1]*v[189]+F[0][0]*v[220]+v[321]+v[132]*v[140]*v[366];
7819 Amat[0][2][1][0]=v[302];
7820 Amat[0][2][1][1]=v[303];
7821 Amat[0][2][1][2]=v[304];
7822 Amat[0][2][2][0]=v[305];
7823 Amat[0][2][2][1]=v[306];
7824 Amat[0][2][2][2]=v[307];
7825 Amat[1][0][0][0]=v[287];
7826 Amat[1][0][0][1]=v[295];
7827 Amat[1][0][0][2]=v[302];
7828 Amat[1][0][1][0]=2e0*F[1][0]*v[169]+F[1][2]*v[224]+F[1][1]*v[261]+v[308];
7829 Amat[1][0][1][1]=v[310];
7830 Amat[1][0][1][2]=v[311];
7831 Amat[1][0][2][0]=v[312];
7832 Amat[1][0][2][1]=v[313];
7833 Amat[1][0][2][2]=v[314];
7834 Amat[1][1][0][0]=v[288];
7835 Amat[1][1][0][1]=v[296];
7836 Amat[1][1][0][2]=v[303];
7837 Amat[1][1][1][0]=v[310];
7838 Amat[1][1][1][1]=2e0*F[1][1]*v[157]+F[1][2]*v[194]+F[1][0]*v[265]+v[315];
7839 Amat[1][1][1][2]=v[317];
7840 Amat[1][1][2][0]=v[318];
7841 Amat[1][1][2][1]=v[319];
7842 Amat[1][1][2][2]=v[320];
7843 Amat[1][2][0][0]=v[289];
7844 Amat[1][2][0][1]=v[297];
7845 Amat[1][2][0][2]=v[304];
7846 Amat[1][2][1][0]=v[311];
7847 Amat[1][2][1][1]=v[317];
7848 Amat[1][2][1][2]=2e0*F[1][2]*v[146]+F[1][1]*v[198]+F[1][0]*v[231]+v[321];
7849 Amat[1][2][2][0]=v[323];
7850 Amat[1][2][2][1]=v[324];
7851 Amat[1][2][2][2]=v[325];
7852 Amat[2][0][0][0]=v[290];
7853 Amat[2][0][0][1]=v[298];
7854 Amat[2][0][0][2]=v[305];
7855 Amat[2][0][1][0]=v[312];
7856 Amat[2][0][1][1]=v[318];
7857 Amat[2][0][1][2]=v[323];
7858 Amat[2][0][2][0]=2e0*F[2][0]*v[174]+F[2][2]*v[235]+F[2][1]*v[274]+v[308];
7859 Amat[2][0][2][1]=v[327];
7860 Amat[2][0][2][2]=v[328];
7861 Amat[2][1][0][0]=v[291];
7862 Amat[2][1][0][1]=v[299];
7863 Amat[2][1][0][2]=v[306];
7864 Amat[2][1][1][0]=v[313];
7865 Amat[2][1][1][1]=v[319];
7866 Amat[2][1][1][2]=v[324];
7867 Amat[2][1][2][0]=v[327];
7868 Amat[2][1][2][1]=2e0*F[2][1]*v[161]+F[2][2]*v[203]+F[2][0]*v[278]+v[315];
7869 Amat[2][1][2][2]=v[330];
7870 Amat[2][2][0][0]=v[292];
7871 Amat[2][2][0][1]=v[300];
7872 Amat[2][2][0][2]=v[307];
7873 Amat[2][2][1][0]=v[314];
7874 Amat[2][2][1][1]=v[320];
7875 Amat[2][2][1][2]=v[325];
7876 Amat[2][2][2][0]=v[328];
7877 Amat[2][2][2][1]=v[330];
7878 Amat[2][2][2][2]=2e0*F[2][2]*v[149]+F[2][1]*v[207]+F[2][0]*v[242]+v[321];
7879};
7880
7881
7882/*************************************************************
7883 * AceGen 6.921 MacOSX (29 Jan 19) *
7884 * Co. J. Korelc 2013 17 Jul 19 15:09:55 *
7885 **************************************************************
7886 User : Full professional version
7887 Notebook : st_venant_kirchhoff_3d
7888 Evaluation time : 3 s Mode : Optimal
7889 Number of formulae : 91 Method: Automatic
7890 Subroutine : stvk3d size: 2846
7891 Total size of Mathematica code : 2846 subexpressions
7892 Total size of C code : 5830 bytes */
7893
7894/******************* S U B R O U T I N E *********************/
7895template <class SC, class LO, class GO, class NO>
7896void FE<SC,LO,GO,NO>::stvk3d(double* v,double (*lam),double (*mue),double** F
7897 ,double** Pmat,double**** Amat)
7898{
7899 v[169]=Power(F[0][0],2);
7900 v[168]=2e0*(*mue);
7901 v[167]=Power(F[0][2],2);
7902 v[166]=F[2][2]*(*mue);
7903 v[165]=F[2][1]*(*mue);
7904 v[164]=F[2][0]*(*mue);
7905 v[163]=F[1][2]*(*mue);
7906 v[162]=F[1][1]*(*mue);
7907 v[161]=F[1][0]*(*mue);
7908 v[88]=F[0][0]*(*mue);
7909 v[116]=F[0][0]*v[88];
7910 v[70]=F[0][1]*(*lam);
7911 v[93]=F[0][1]*(*mue);
7912 v[117]=F[0][1]*v[93];
7913 v[71]=F[0][2]*(*lam);
7914 v[105]=(*mue)*v[167];
7915 v[72]=F[1][0]*(*lam);
7916 v[85]=2e0*v[161]+v[72];
7917 v[142]=F[1][0]*v[161];
7918 v[121]=F[0][0]*v[161];
7919 v[73]=F[1][1]*(*lam);
7920 v[100]=F[0][1]*v[161]+F[0][0]*v[73];
7921 v[82]=2e0*v[162]+v[73];
7922 v[143]=F[1][1]*v[162];
7923 v[122]=F[0][1]*v[162];
7924 v[108]=F[0][0]*v[162]+F[0][1]*v[72];
7925 v[74]=F[1][2]*(*lam);
7926 v[111]=F[0][2]*v[162]+F[0][1]*v[74];
7927 v[101]=F[0][2]*v[161]+F[0][0]*v[74];
7928 v[79]=2e0*v[163]+v[74];
7929 v[123]=v[121]+v[122]+F[0][2]*v[79];
7930 v[135]=F[1][2]*v[163];
7931 v[120]=F[0][1]*v[163]+F[0][2]*v[73];
7932 v[119]=F[0][0]*v[163]+F[0][2]*v[72];
7933 v[109]=F[0][2]*v[163];
7934 v[110]=v[109]+v[121]+F[0][1]*v[82];
7935 v[99]=v[109]+v[122]+F[0][0]*v[85];
7936 v[75]=F[2][0]*(*lam);
7937 v[86]=2e0*v[164]+v[75];
7938 v[156]=F[2][0]*v[164];
7939 v[147]=F[1][0]*v[164];
7940 v[126]=F[0][0]*v[164];
7941 v[76]=F[2][1]*(*lam);
7942 v[133]=F[1][1]*v[164]+F[1][0]*v[76];
7943 v[103]=F[0][1]*v[164]+F[0][0]*v[76];
7944 v[83]=2e0*v[165]+v[76];
7945 v[157]=F[2][1]*v[165];
7946 v[148]=F[1][1]*v[165];
7947 v[138]=F[1][0]*v[165]+F[1][1]*v[75];
7948 v[127]=F[0][1]*v[165];
7949 v[112]=F[0][0]*v[165]+F[0][1]*v[75];
7950 v[77]=F[2][2]*(*lam);
7951 v[141]=F[1][2]*v[165]+F[1][1]*v[77];
7952 v[134]=F[1][2]*v[164]+F[1][0]*v[77];
7953 v[115]=F[0][2]*v[165]+F[0][1]*v[77];
7954 v[104]=F[0][2]*v[164]+F[0][0]*v[77];
7955 v[80]=2e0*v[166]+v[77];
7956 v[149]=v[147]+v[148]+F[1][2]*v[80];
7957 v[128]=v[126]+v[127]+F[0][2]*v[80];
7958 v[153]=F[2][2]*v[166];
7959 v[146]=F[1][1]*v[166]+F[1][2]*v[76];
7960 v[145]=F[1][0]*v[166]+F[1][2]*v[75];
7961 v[139]=F[1][2]*v[166];
7962 v[140]=v[139]+v[147]+F[1][1]*v[83];
7963 v[132]=v[139]+v[148]+F[1][0]*v[86];
7964 v[125]=F[0][1]*v[166]+F[0][2]*v[76];
7965 v[124]=F[0][0]*v[166]+F[0][2]*v[75];
7966 v[113]=F[0][2]*v[166];
7967 v[114]=v[113]+v[126]+F[0][1]*v[83];
7968 v[102]=v[113]+v[127]+F[0][0]*v[86];
7969 v[24]=(-1e0+Power(F[1][0],2)+Power(F[2][0],2)+v[169])/2e0;
7970 v[28]=(-1e0+Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2))/2e0;
7971 v[32]=(-1e0+Power(F[1][2],2)+Power(F[2][2],2)+v[167])/2e0;
7972 v[36]=(*lam)*(v[24]+v[28]+v[32]);
7973 v[35]=2e0*(*mue)*v[32]+v[36];
7974 v[37]=2e0*(*mue)*v[28]+v[36];
7975 v[38]=2e0*(*mue)*v[24]+v[36];
7976 v[39]=(F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2])*(*mue);
7977 v[152]=F[2][2]*v[164]+v[39]+F[2][0]*v[77];
7978 v[131]=F[1][2]*v[161]+v[39]+F[1][0]*v[74];
7979 v[98]=v[39]+F[0][0]*v[71]+F[0][2]*v[88];
7980 v[40]=(F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2])*(*mue);
7981 v[155]=F[2][2]*v[165]+v[40]+F[2][1]*v[77];
7982 v[137]=F[1][2]*v[162]+v[40]+F[1][1]*v[74];
7983 v[107]=v[40]+F[0][1]*v[71]+F[0][2]*v[93];
7984 v[41]=(F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1])*(*mue);
7985 v[151]=F[2][1]*v[164]+v[41]+F[2][0]*v[76];
7986 v[130]=F[1][1]*v[161]+v[41]+F[1][0]*v[73];
7987 v[97]=v[41]+F[0][0]*v[70]+F[0][1]*v[88];
7988 Pmat[0][0]=F[0][0]*v[38]+F[0][2]*v[39]+F[0][1]*v[41];
7989 Pmat[0][1]=F[0][1]*v[37]+F[0][2]*v[40]+F[0][0]*v[41];
7990 Pmat[0][2]=F[0][2]*v[35]+F[0][0]*v[39]+F[0][1]*v[40];
7991 Pmat[1][0]=F[1][0]*v[38]+F[1][2]*v[39]+F[1][1]*v[41];
7992 Pmat[1][1]=F[1][1]*v[37]+F[1][2]*v[40]+F[1][0]*v[41];
7993 Pmat[1][2]=F[1][2]*v[35]+F[1][0]*v[39]+F[1][1]*v[40];
7994 Pmat[2][0]=F[2][0]*v[38]+F[2][2]*v[39]+F[2][1]*v[41];
7995 Pmat[2][1]=F[2][1]*v[37]+F[2][2]*v[40]+F[2][0]*v[41];
7996 Pmat[2][2]=F[2][2]*v[35]+F[2][0]*v[39]+F[2][1]*v[40];
7997 Amat[0][0][0][0]=v[105]+v[117]+((*lam)+v[168])*v[169]+v[38];
7998 Amat[0][0][0][1]=v[97];
7999 Amat[0][0][0][2]=v[98];
8000 Amat[0][0][1][0]=v[99];
8001 Amat[0][0][1][1]=v[100];
8002 Amat[0][0][1][2]=v[101];
8003 Amat[0][0][2][0]=v[102];
8004 Amat[0][0][2][1]=v[103];
8005 Amat[0][0][2][2]=v[104];
8006 Amat[0][1][0][0]=v[97];
8007 Amat[0][1][0][1]=v[105]+v[116]+v[37]+F[0][1]*(v[70]+2e0*v[93]);
8008 Amat[0][1][0][2]=v[107];
8009 Amat[0][1][1][0]=v[108];
8010 Amat[0][1][1][1]=v[110];
8011 Amat[0][1][1][2]=v[111];
8012 Amat[0][1][2][0]=v[112];
8013 Amat[0][1][2][1]=v[114];
8014 Amat[0][1][2][2]=v[115];
8015 Amat[0][2][0][0]=v[98];
8016 Amat[0][2][0][1]=v[107];
8017 Amat[0][2][0][2]=v[116]+v[117]+v[35]+F[0][2]*(F[0][2]*v[168]+v[71]);
8018 Amat[0][2][1][0]=v[119];
8019 Amat[0][2][1][1]=v[120];
8020 Amat[0][2][1][2]=v[123];
8021 Amat[0][2][2][0]=v[124];
8022 Amat[0][2][2][1]=v[125];
8023 Amat[0][2][2][2]=v[128];
8024 Amat[1][0][0][0]=v[99];
8025 Amat[1][0][0][1]=v[108];
8026 Amat[1][0][0][2]=v[119];
8027 Amat[1][0][1][0]=v[135]+v[143]+v[38]+F[1][0]*v[85];
8028 Amat[1][0][1][1]=v[130];
8029 Amat[1][0][1][2]=v[131];
8030 Amat[1][0][2][0]=v[132];
8031 Amat[1][0][2][1]=v[133];
8032 Amat[1][0][2][2]=v[134];
8033 Amat[1][1][0][0]=v[100];
8034 Amat[1][1][0][1]=v[110];
8035 Amat[1][1][0][2]=v[120];
8036 Amat[1][1][1][0]=v[130];
8037 Amat[1][1][1][1]=v[135]+v[142]+v[37]+F[1][1]*v[82];
8038 Amat[1][1][1][2]=v[137];
8039 Amat[1][1][2][0]=v[138];
8040 Amat[1][1][2][1]=v[140];
8041 Amat[1][1][2][2]=v[141];
8042 Amat[1][2][0][0]=v[101];
8043 Amat[1][2][0][1]=v[111];
8044 Amat[1][2][0][2]=v[123];
8045 Amat[1][2][1][0]=v[131];
8046 Amat[1][2][1][1]=v[137];
8047 Amat[1][2][1][2]=v[142]+v[143]+v[35]+F[1][2]*v[79];
8048 Amat[1][2][2][0]=v[145];
8049 Amat[1][2][2][1]=v[146];
8050 Amat[1][2][2][2]=v[149];
8051 Amat[2][0][0][0]=v[102];
8052 Amat[2][0][0][1]=v[112];
8053 Amat[2][0][0][2]=v[124];
8054 Amat[2][0][1][0]=v[132];
8055 Amat[2][0][1][1]=v[138];
8056 Amat[2][0][1][2]=v[145];
8057 Amat[2][0][2][0]=v[153]+v[157]+v[38]+F[2][0]*v[86];
8058 Amat[2][0][2][1]=v[151];
8059 Amat[2][0][2][2]=v[152];
8060 Amat[2][1][0][0]=v[103];
8061 Amat[2][1][0][1]=v[114];
8062 Amat[2][1][0][2]=v[125];
8063 Amat[2][1][1][0]=v[133];
8064 Amat[2][1][1][1]=v[140];
8065 Amat[2][1][1][2]=v[146];
8066 Amat[2][1][2][0]=v[151];
8067 Amat[2][1][2][1]=v[153]+v[156]+v[37]+F[2][1]*v[83];
8068 Amat[2][1][2][2]=v[155];
8069 Amat[2][2][0][0]=v[104];
8070 Amat[2][2][0][1]=v[115];
8071 Amat[2][2][0][2]=v[128];
8072 Amat[2][2][1][0]=v[134];
8073 Amat[2][2][1][1]=v[141];
8074 Amat[2][2][1][2]=v[149];
8075 Amat[2][2][2][0]=v[152];
8076 Amat[2][2][2][1]=v[155];
8077 Amat[2][2][2][2]=v[156]+v[157]+v[35]+F[2][2]*v[80];
8078};
8079/*************************************************************
8080 * AceGen 6.921 MacOSX (29 Jan 19) *
8081 * Co. J. Korelc 2013 17 Jul 19 16:01:42 *
8082 **************************************************************
8083 User : Full professional version
8084 Notebook : st_venant_kirchhoff_2d
8085 Evaluation time : 1 s Mode : Optimal
8086 Number of formulae : 25 Method: Automatic
8087 Subroutine : stvk2d size: 772
8088 Total size of Mathematica code : 772 subexpressions
8089 Total size of C code : 1672 bytes */
8090
8091
8092/******************* S U B R O U T I N E *********************/
8093template <class SC, class LO, class GO, class NO>
8094void FE<SC,LO,GO,NO>::stvk2d(double* v, double (*lam),double (*mue),double** F
8095 ,double** Pmat,double**** Amat)
8096{
8097 v[43]=F[0][0]*F[1][0];
8098 v[42]=F[0][1]*F[1][1];
8099 v[37]=Power(F[0][0],2);
8100 v[12]=F[0][0]/2e0;
8101 v[36]=Power(F[0][1],2);
8102 v[34]=F[0][0]*F[0][1];
8103 v[11]=F[0][1]/2e0;
8104 v[27]=Power(F[1][0],2);
8105 v[31]=-1e0+v[27]+v[37];
8106 v[14]=F[1][0]/2e0;
8107 v[25]=Power(F[1][1],2);
8108 v[26]=-1e0+v[25]+v[36];
8109 v[23]=F[1][0]*F[1][1];
8110 v[22]=v[23]+v[34];
8111 v[35]=(*lam)*v[34]+(*mue)*(v[22]+v[34]);
8112 v[24]=(*lam)*v[23]+(*mue)*(v[22]+v[23]);
8113 v[21]=(*lam)*v[42]+2e0*(*mue)*(2e0*v[12]*v[14]+v[42]);
8114 v[20]=F[0][0]*F[1][1]*(*lam)+4e0*(*mue)*v[11]*v[14];
8115 v[13]=F[1][1]/2e0;
8116 v[30]=F[0][1]*F[1][0]*(*lam)+4e0*(*mue)*v[12]*v[13];
8117 v[29]=(*lam)*v[43]+2e0*(*mue)*(2e0*v[11]*v[13]+v[43]);
8118 v[44]=2e0*v[22];
8119 v[32]=((*lam)*(v[26]+v[31]))/2e0;
8120 Pmat[0][0]=F[0][0]*v[32]+(*mue)*(F[0][0]*v[31]+v[11]*v[44]);
8121 Pmat[0][1]=F[0][1]*v[32]+(*mue)*(F[0][1]*v[26]+v[12]*v[44]);
8122 Pmat[1][0]=F[1][0]*v[32]+(*mue)*(F[1][0]*v[31]+v[13]*v[44]);
8123 Pmat[1][1]=F[1][1]*v[32]+(*mue)*(F[1][1]*v[26]+v[14]*v[44]);
8124 Amat[0][0][0][0]=v[32]+(*lam)*v[37]+(*mue)*(v[31]+v[36]+2e0*v[37]);
8125 Amat[0][0][0][1]=v[35];
8126 Amat[0][0][1][0]=v[29];
8127 Amat[0][0][1][1]=v[20];
8128 Amat[0][1][0][0]=v[35];
8129 Amat[0][1][0][1]=v[32]+(*lam)*v[36]+(*mue)*(v[26]+2e0*v[36]+v[37]);
8130 Amat[0][1][1][0]=v[30];
8131 Amat[0][1][1][1]=v[21];
8132 Amat[1][0][0][0]=v[29];
8133 Amat[1][0][0][1]=v[30];
8134 Amat[1][0][1][0]=(*lam)*v[27]+(*mue)*(v[25]+2e0*v[27]+v[31])+v[32];
8135 Amat[1][0][1][1]=v[24];
8136 Amat[1][1][0][0]=v[20];
8137 Amat[1][1][0][1]=v[21];
8138 Amat[1][1][1][0]=v[24];
8139 Amat[1][1][1][1]=(*lam)*v[25]+(*mue)*(2e0*v[25]+v[26]+v[27])+v[32];
8140};
8141
8142}
8143#endif
vec2D_dbl_Type getCoordinates(vec_LO_Type localIDs, vec2D_dbl_ptr_Type points)
Definition FE_ElementAssembly_def.hpp:1383
int checkFE(int Dimension, std::string FEType)
Checks which domain corresponds to certain FE Type and dimension.
Definition FE_ElementAssembly_def.hpp:1608
vec_dbl_Type getSolution(vec_LO_Type localIDs, MultiVectorPtr_Type u_rep, int dofsVelocity)
Definition FE_ElementAssembly_def.hpp:1404
void assemblyNonlinearSurfaceIntegralExternal(int dim, std::string FEType, MultiVectorPtr_Type f, MultiVectorPtr_Type d_rep, MatrixPtr_Type &Kext, std::vector< SC > &funcParameter, RhsFunc_Type func, ParameterListPtr_Type params, int FEloc=0)
assemblyNonlinearSurfaceIntegralExternal -
Definition FE_def.hpp:6627
void assemblyAdvectionVecFieldScalar(int dim, std::string FEType, std::string FETypeV, MatrixPtr_Type &A, MultiVectorPtr_Type u, bool callFillComplete)
Assembly of operator \int ((u_h \cdot \nabla ) p_h)p_h dx.
Definition FE_def.hpp:2338
void assemblyDivAndDivT(int dim, std::string FEType1, std::string FEType2, int degree, MatrixPtr_Type &Bmat, MatrixPtr_Type &BTmat, MapConstPtr_Type map1, MapConstPtr_Type map2, bool callFillComplete=true)
Assembly of \int q_h (nabla \cdot v_h) dx.
Definition FE_def.hpp:2425
void assemblyStress(int dim, std::string FEType, MatrixPtr_Type &A, CoeffFunc_Type func, int *parameters, bool callFillComplete=true)
(\grad u + (\grad u)^T, \grad v ); symmetrischer Gradient, wenn func = 1.0
Definition FE_def.hpp:2914
void assemblyBDStabilization(int dim, std::string FEType, MatrixPtr_Type &A, bool callFillComplete=true)
Bochev- Dohrmann Stabilization.
Definition FE_def.hpp:2649
void assemblyDivAndDivTFast(int dim, std::string FEType1, std::string FEType2, int degree, MatrixPtr_Type &Bmat, MatrixPtr_Type &BTmat, MapConstPtr_Type map1, MapConstPtr_Type map2, bool callFillComplete=true)
Assembly of \int q_h (nabla \cdot v_h) dx.
Definition FE_def.hpp:2555
void assemblyLaplaceXDim(int dim, std::string FEType, MatrixPtr_Type &A, CoeffFuncDbl_Type func, double *parameters, bool callFillComplete=true)
Definition FE_def.hpp:2732
void assemblyAdvectionVecField(int dim, std::string FEType, MatrixPtr_Type &A, MultiVectorPtr_Type u, bool callFillComplete)
Assembly of operator \int ((u_h \cdot \nabla ) v_h)v_h dx.
Definition FE_def.hpp:2153
void assemblyAdvectionInUVecField(int dim, std::string FEType, MatrixPtr_Type &A, MultiVectorPtr_Type u, bool callFillComplete)
Assembly of operator \int ((v_h \cdot \nabla ) u_h)v_h dx.
Definition FE_def.hpp:2247
FE(bool saveAssembly=false)
Constructor of FE calling the constructor of FE_ElementAssembly accordingly.
Definition FE_def.hpp:64
void assemblyLinElasXDimE(int dim, std::string FEType, MatrixPtr_Type &A, MultiVectorPtr_Type eModVec, double nu, bool callFillComplete=true)
Same as assemblyLinElasXDim except for changing E Module Value.
Definition FE_def.hpp:4763
void assemblyAdditionalConvection(int dim, std::string FEType, MatrixPtr_Type &A, MultiVectorPtr_Type w, bool callFillComplete=true)
Addional Matrix due to ALE derivation: \int \rho_f div(w) u_h \cdot v_f dx, with mesh velocity w.
Definition FE_def.hpp:5075
void assemblyLinElasXDim(int dim, std::string FEType, MatrixPtr_Type &A, double lambda, double mu, bool callFillComplete=true)
Definition FE_def.hpp:4408
void assemblyPressureMeanValue(int dim, std::string FEType, MultiVectorPtr_Type a)
Assembling \int p \dx = 0. Thus, we need the integral part for the mean pressure value.
Definition FE_def.hpp:7057
Definition FiniteElement.hpp:17
static void buildTransformationSurface(const vec_int_Type &element, vec2D_dbl_ptr_Type pointsRep, SmallMatrix< SC > &B, vec_dbl_Type &b, std::string FEType="P")
Transformation of a surface to the reference element.
Definition Helper.cpp:79
static UN determineDegree(UN dim, std::string FEType, VarType orderOfDerivative)
Determine polynomial degree of a finite element basis function or its gradient that is required to se...
Definition Helper.cpp:68
static void gradPhi(int Dimension, int intFE, int i, vec_dbl_Type &QuadPts, vec_dbl_ptr_Type &value)
Returning gradient of phi evaluated at the quadrature points.
Definition Helper.cpp:301
@ Deriv0
order 0, f(x)
Definition Helper.hpp:27
@ Deriv1
order 1, gradient(f(x))
Definition Helper.hpp:28
static void buildTransformation(const vec_int_Type &element, vec2D_dbl_ptr_Type pointsRep, SmallMatrix< SC > &B, std::string FEType="P")
Build transformation of element to reference element depending on FEType.
Definition Helper.cpp:138
static int getPhi(vec2D_dbl_ptr_Type &Phi, vec_dbl_ptr_Type &weightsPhi, int dim, std::string FEType, int Degree, std::string FETypeQuadPoints="")
Get basisfunction phi per quadrature point.
Definition Helper.cpp:921
static void computeSurfaceNormal(int dim, vec2D_dbl_ptr_Type pointsRep, vec_int_Type nodeList, vec_dbl_Type &v_E, double &norm_v_E)
Compute surface normal of corresponding surface.
Definition Helper.cpp:103
static int getDPhi(vec3D_dbl_ptr_Type &DPhi, vec_dbl_ptr_Type &weightsDPhi, int Dimension, std::string FEType, int Degree)
Full matrix representation of gradient of a basis function for each quadrature point.
Definition Helper.cpp:215
static void getQuadratureValues(int Dimension, int Degree, vec2D_dbl_ptr_Type &QuadPts, vec_dbl_ptr_Type &QuadW, std::string FEType)
Get quadrature formula.
Definition Helper.cpp:1138
This class represents a templated small Matrix of type T. Primarily created for 2x2 and 3x3 matrices....
Definition SmallMatrix.hpp:20
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement_decl.hpp:36