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
60
61template <class SC, class LO, class GO, class NO>
62FE<SC,LO,GO,NO>::FE(bool saveAssembly):
63domainVec_(0),
64es_(),
65setZeros_(false),
66myeps_(),
67ed_(0),
68saveAssembly_(saveAssembly)
69{
70}
71
72template <class SC, class LO, class GO, class NO>
73void FE<SC,LO,GO,NO>::addFE(DomainConstPtr_Type domain){
74
75 if (saveAssembly_){
76 DomainPtr_Type domainNC = Teuchos::rcp_const_cast<Domain_Type>( domain );
77 domainNC->initializeFEData();
78 }
79 domainVec_.push_back(domain);
80
81}
82
83template <class SC, class LO, class GO, class NO>
84void FE<SC,LO,GO,NO>::doSetZeros(double eps){
85
86 setZeros_ = true;
87 myeps_ = eps;
88
89}
90
91template <class SC, class LO, class GO, class NO>
92void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
93 vec3D_dbl_Type& dPhiOut,
94 SmallMatrix<SC>& Binv){
95 UN dim = Binv.size();
96 for (UN w=0; w<dPhiIn->size(); w++){
97 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
98 for (UN d1=0; d1<dim; d1++) {
99 for (UN d2=0; d2<dim; d2++) {
100 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
101 }
102 }
103 }
104 }
105}
106
118
119// Check the order of chemistry and solid in system matrix
120/*template <class SC, class LO, class GO, class NO>
121void FE<SC,LO,GO,NO>::globalAssembly(std::string ProblemType,
122 int dim,
123 int degree,
124 MultiVectorPtr_Type sol_rep,
125 BlockMatrixPtr_Type &A,
126 BlockMultiVectorPtr_Type &resVec,
127 ParameterListPtr_Type params,
128 std::string assembleMode,
129 bool callFillComplete,
130 int FELocExternal){
131
132 int problemSize = domainVec_.size(); // Problem size, as in number of subproblems
133
134 // Depending on problem size we extract necessary information
135
138 int numChem=3;
139 if(FETypeChem == "P2"){
140 numChem=6;
141 }
142 if(dim==3){
143 numChem=4;
144 if(FETypeChem == "P2")
145 numChem=10;
146 }
147 int numSolid=3;
148 if(FETypeSolid == "P2")
149 numSolid=6;
150
151 if(dim==3){
152 numSolid=4;
153 if(FETypeSolid == "P2")
154 numSolid=10;
155 }
156
157 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 2) );
158
159 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
160 for(int i=0; i< problemSize; i++){
161 int numNodes=0.;
162 if(domainVec.at(i)->getFEType() == "P2"){
163 numNodes=6;
164 }
165 if(dim==3){
166 numNodes=4;
167 if(domainVec.at(i)->getFEType() == "P2")
168 numNodes=10;
169 }
170 tuple_ssii_Type infoTuple (domainVec.at(i)->getPhysic(),domainVec.at(i)->getFEType(),domainVec.at(i)->getDofs(),numChem);
171 problemDisk->push_back(infoTuple);
172
173 MultiVectorPtr_Type resVec;
174 if(domainVec.at(i)->getDofs() == 1)
175 resVec = Teuchos::rcp( new MultiVector_Type( domainVec_.at(i)->getMapRepeated(), 1 ) );
176 else
177 resVec = Teuchos::rcp( new MultiVector_Type( domainVec_.at(i)->getMapVecFieldRepeated(), 1 ) );
178
179 resVecRep->addBlock(resVec,i);
180
181
182 }
183
184
185 if(assemblyFEElements_.size()== 0){
186 initAssembleFEElements(ProblemType,problemDisk,domainVec_.at(0)->getElementsC(), params,domainVec_.at(0)->getPointsRepeated(),domainVec_.at(0)->getElementMap());
187 }
188 else if(assemblyFEElements_.size() != domainVec_.at(0)->getElementsC()->numberElements())
189 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
190
191 vec_dbl_Type solution_tmp;
192 for (UN T=0; T<assemblyFEElements_.size(); T++) {
193 vec_dbl_Type solution(0);
194 vec_FE_Type elements;
195 for(int i=0; i< problemSize; i++){
196 solution_tmp = getSolution(domainVec_.at(i)->getElementsC()->getElement(T).getVectorNodeList(), sol_rep->getBlock(i),domainVec.at(i)->getDofs());
197 solution.insert( solution.end(), solution_tmp.begin(), solution_tmp.end() );
198
199
200 }
201
202 assemblyFEElements_[T]->updateSolution(solution);
203
204 SmallMatrixPtr_Type elementMatrix;
205 vec_dbl_ptr_Type rhsVec;
206
207 if(assembleMode == "Jacobian"){
208 assemblyFEElements_[T]->assembleJacobian();
209
210 elementMatrix = assemblyFEElements_[T]->getJacobian();
211 //elementMatrix->print();
212 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
213
214 addFeBlockMatrix(A, elementMatrix, domainVec_.at(0)->getElementsC()->getElement(T), problemDisk);
215
216 }
217 if(assembleMode == "Rhs"){
218 assemblyFEElements_[T]->assembleRHS();
219 rhsVec = assemblyFEElements_[T]->getRHS();
220 addFeBlockMv(resVecRep, rhsVec, elementsSolid->getElement(T),elementsChem->getElement(T), dofsSolid,dofsChem);
221
222 }
223
224 }
225 if ( assembleMode == "Jacobian"){
226 for(int probRow = 0; probRow < problemSize; probRow++){
227 for(int probCol = 0; probCol < problemSize; probCol++){
228 MapConstPtr_Type rowMap;
229 MapConstPtr_Type domainMap;
230
231 if(domainVec.at(probRow)->getDofs() == 1)
232 rowMap = domainVec_.at(FElocRow)->getMapUnique();
233 else
234 rowMap = domainVec_.at(probRow)->getMapVecFieldUnique();
235
236 if(domainVec.at(probCol)->getDofs() == 1)
237 domainMap = domainVec_.at(probCol)->getMapUnique()
238 else
239 domainMap = domainVec_.at(probCol)->getMapVecFieldUnique()
240
241 A->getBlock(probRow,probCol)->fillComplete(domainMap,rowMap);
242 }
243 }
244 }
245 else if(assembleMode == "Rhs"){
246
247 for(int probRow = 0; probRow < problemSize; probRow++){
248 MapConstPtr_Type rowMap;
249 if(domainVec.at(probRow)->getDofs() == 1)
250 rowMap = domainVec_.at(FElocRow)->getMapUnique();
251 else
252 rowMap = domainVec_.at(probRow)->getMapVecFieldUnique();
253
254 MultiVectorPtr_Type resVecUnique = Teuchos::rcp( new MultiVector_Type( rowMap, 1 ) );
255
256 resVecUnique->putScalar(0.);
257
258 resVecUnique->exportFromVector( resVecRep, true, "Add" );
259
260 resVec->addBlock(resVecUnique,probRow);
261 }
262 }
263
264}*/
265
278/*template <class SC, class LO, class GO, class NO>
279void FE<SC,LO,GO,NO>::addFeBlockMatrix(BlockMatrixPtr_Type &A, SmallMatrixPtr_Type elementMatrix, FiniteElement_vec element, tuple_disk_vec_ptr_Type problemDisk){
280
281 int numDisk = problemDisk->size();
282
283 for(int probRow = 0; probRow < numDisk; probRow++){
284 for(int probCol = 0; probCol < numDisk; probCol++){
285 int dofs1 = std::get<2>(problemDisk->at(probRow));
286 int dofs2 = std::get<2>(problemDisk->at(probCol));
287
288 int numNodes1 = std::get<3>(problemDisk->at(probRow));
289 int numNodes2=std::get<3>(problemDisk->at(probCol));
290
291 int offsetRow= numNodes1*dofs1*probRow;
292 int offsetCol= numNodes1*dofs1*probCol;
293
294 mapRow = domainVec.at(probRow)->getMapRepeated();
295 mapCol = domainVec.at(probCol)->getMapRepeated();
296
297 Teuchos::Array<SC> value2( numNodes2, 0. );
298 Teuchos::Array<GO> columnIndices2( numNodes2, 0 );
299 for (UN i=0; i < numNodes1; i++){
300 for(int di=0; di<dofs1; di++){
301 GO row =GO (dofs1* mapRow->getGlobalElement( element[probRow].getNode(i) )+di);
302 for(int d=0; d<dofs2; d++){
303 for (UN j=0; j < numNodes2 ; j++) {
304 value2[j] = (*elementMatrix)[offsetRow+i*dofs1+di][offsetCol+j*dofs2+d];
305 columnIndices2[j] =GO (dofs2* mapCol->getGlobalElement( element.getNode(j) )+d);
306 }
307 A->getBlock(probRow,probCol)->insertGlobalValues( row, columnIndices2(), value2() ); // Automatically adds entries if a value already exists
308 }
309 }
310 }
311
312 }
313 }
314}
315
316*/
328/*
329template <class SC, class LO, class GO, class NO>
330void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec,tuple_disk_vec_ptr_Type problemDisk, FiniteElement_vec element)
331 int numDisk = problemDisk->size();
332
333 for(int probRow = 0; probRow < numDisk; probRow++){
334 Teuchos::ArrayRCP<SC> resArray_block = res->getBlockNonConst(probRow)->getDataNonConst(0);
335 vec_LO_Type nodeList_block = element[probRow].getVectorNodeList();
336 int dofs = std::get<2>(problemDisk->at(probRow));
337 int numNodes = std::get<3>(problemDisk->at(probRow));
338
339 int offset = numNodes*dofs;
340 for(int i=0; i< nodeList_block.size() ; i++){
341 for(int d=0; d<dofs; d++){
342 resArray_block[nodeList_block[i]*dofs+d] += (*rhsVec)[i*dofs+d+offset];
343 }
344 }
345 }
346}
347*/
348
360
361template <class SC, class LO, class GO, class NO>
363 std::string FEType,
364 int degree,
365 int dofs,
366 MultiVectorPtr_Type d_rep,
367 BlockMatrixPtr_Type &A,
368 BlockMultiVectorPtr_Type &resVec,
369 ParameterListPtr_Type params,
370 bool reAssemble,
371 std::string assembleMode,
372 bool callFillComplete,
373 int FELocExternal){
374
375 ElementsPtr_Type elements = domainVec_.at(0)->getElementsC();
376
377 int dofsElement = elements->getElement(0).getVectorNodeList().size();
379 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(0)->getPointsRepeated();
380
381 MapConstPtr_Type mapVel = domainVec_.at(0)->getMapRepeated();
382
383 vec_dbl_Type solution(0);
384 vec_dbl_Type solution_d;
386 vec_dbl_Type rhsVec;
387
390 int numNodes=6;
391 if(dim==3){
392 numNodes=10;
393 }
394 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
395 tuple_ssii_Type displacement ("Displacement",FEType,dofs,numNodes);
396 problemDisk->push_back(displacement);
397
398 if(assemblyFEElements_.size()== 0)
399 initAssembleFEElements("LinearElasticity",problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
400 else if(assemblyFEElements_.size() != elements->numberElements())
401 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
402
403 MultiVectorPtr_Type resVec_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(0)->getMapVecFieldRepeated(), 1 ) );
404
405 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 1) );
406 resVecRep->addBlock(resVec_d,0);
408 SmallMatrixPtr_Type elementMatrix;
409 for (UN T=0; T<assemblyFEElements_.size(); T++) {
410 vec_dbl_Type solution(0);
411
412 solution_d = getSolution(elements->getElement(T).getVectorNodeList(), d_rep,dofs);
413
414 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
415
416 assemblyFEElements_[T]->updateSolution(solution);
417
418 assemblyFEElements_[T]->assembleJacobian();
419
420 elementMatrix = assemblyFEElements_[T]->getJacobian();
421
422 assemblyFEElements_[T]->advanceNewtonStep();
423
424
425 addFeBlock(A, elementMatrix, elements->getElement(T), mapVel, 0, 0, problemDisk);
426
427 }
428 if (callFillComplete)
429 A->getBlock(0,0)->fillComplete( domainVec_.at(0)->getMapVecFieldUnique(),domainVec_.at(0)->getMapVecFieldUnique());
430
432
433
434}
435
444@param[in] FELocExternal
445
446*/
447
448template <class SC, class LO, class GO, class NO>
450 std::string FEType,
451 int degree,
452 int dofs,
453 MultiVectorPtr_Type d_rep,
454 BlockMatrixPtr_Type &A,
455 BlockMultiVectorPtr_Type &resVec,
456 ParameterListPtr_Type params,
457 bool callFillComplete,
458 int FELocExternal){
459
460 ElementsPtr_Type elements = domainVec_.at(0)->getElementsC();
461
462 int dofsElement = elements->getElement(0).getVectorNodeList().size();
463
464 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(0)->getPointsRepeated();
465
466 MapConstPtr_Type map = domainVec_.at(0)->getMapRepeated();
467
468 vec_dbl_Type solution(0);
469 vec_dbl_Type solution_d;
470
471 vec_dbl_ptr_Type rhsVec;
472
475 int numNodes=6;
476 if(dim==3){
477 numNodes=10;
478 }
479 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
480 tuple_ssii_Type displacement ("Displacement",FEType,dofs,numNodes);
481 problemDisk->push_back(displacement);
482
483 int neoHookeNum = params->sublist("Parameter").get("Neo-Hooke Modell",1);
484
485 std::string nonLinElasModell = "NonLinearElasticity2";
486 if(neoHookeNum == 1)
487 nonLinElasModell = "NonLinearElasticity";
488
489 //std::cout << " ######## Assembly Modell: " << nonLinElasModell << " ############ " << std::endl;
490
491
492 if(assemblyFEElements_.size()== 0)
493 initAssembleFEElements(nonLinElasModell,problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
494 else if(assemblyFEElements_.size() != elements->numberElements())
495 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
496
497
498 SmallMatrixPtr_Type elementMatrix;
499 for (UN T=0; T<assemblyFEElements_.size(); T++) {
500 vec_dbl_Type solution(0);
501
502 solution_d = getSolution(elements->getElement(T).getVectorNodeList(), d_rep,dofs);
503
504 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
505
506 assemblyFEElements_[T]->updateSolution(solution);
507
508 assemblyFEElements_[T]->assembleJacobian();
509 elementMatrix = assemblyFEElements_[T]->getJacobian();
510 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
511
512 assemblyFEElements_[T]->assembleRHS();
513 rhsVec = assemblyFEElements_[T]->getRHS();
514 addFeBlockMv(resVec, rhsVec, elements->getElement(T), dofs);
515
516 assemblyFEElements_[T]->advanceNewtonStep();
517
518
519 }
520 if (callFillComplete)
521 A->getBlock(0,0)->fillComplete( domainVec_.at(0)->getMapVecFieldUnique(),domainVec_.at(0)->getMapVecFieldUnique());
522
523}
524
536
537template <class SC, class LO, class GO, class NO>
539 std::string FEType,
540 int degree,
541 int dofs,
542 MultiVectorPtr_Type d_rep,
543 BlockMatrixPtr_Type &A,
544 BlockMultiVectorPtr_Type &resVec,
545 ParameterListPtr_Type params,
546 DomainConstPtr_Type domain,
547 MultiVectorPtr_Type eModVec,
548 bool callFillComplete,
549 int FELocExternal){
550
551 ElementsPtr_Type elements = domain->getElementsC();
552
553 int dofsElement = elements->getElement(0).getVectorNodeList().size();
554
555 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
556
557 MapConstPtr_Type map = domain->getMapRepeated();
558
559 vec_dbl_Type solution(0);
560 vec_dbl_Type solution_d;
561
562 vec_dbl_ptr_Type rhsVec;
563
566 int numNodes=6;
567 if(dim==3){
568 numNodes=10;
569 }
570 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
571 tuple_ssii_Type displacement ("Displacement",FEType,dofs,numNodes);
572 problemDisk->push_back(displacement);
573
574 int neoHookeNum = params->sublist("Parameter").get("Neo-Hooke Modell",1);
575
576 std::string nonLinElasModell = "NonLinearElasticity2";
577 if(neoHookeNum == 1)
578 nonLinElasModell = "NonLinearElasticity";
579
580 //std::cout << " ######## Assembly Modell: " << nonLinElasModell << " ############ " << std::endl;
581
582 if(assemblyFEElements_.size()== 0)
583 initAssembleFEElements(nonLinElasModell,problemDisk,elements, params,pointsRep,domain->getElementMap());
584 else if(assemblyFEElements_.size() != elements->numberElements())
585 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
586
587 Teuchos::ArrayRCP<SC> eModVecA = eModVec->getDataNonConst(0);
588
589 SmallMatrixPtr_Type elementMatrix;
590 for (UN T=0; T<assemblyFEElements_.size(); T++) {
591 vec_dbl_Type solution(0);
592
593 solution_d = getSolution(elements->getElement(T).getVectorNodeList(), d_rep,dofs);
594
595 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
596
597 assemblyFEElements_[T]->updateSolution(solution);
598 assemblyFEElements_[T]->updateParameter("E",eModVecA[T]);
599 assemblyFEElements_[T]->assembleJacobian();
600 elementMatrix = assemblyFEElements_[T]->getJacobian();
601 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
602
603 assemblyFEElements_[T]->assembleRHS();
604 rhsVec = assemblyFEElements_[T]->getRHS();
605 addFeBlockMv(resVec, rhsVec, elements->getElement(T), dofs);
606
607 assemblyFEElements_[T]->advanceNewtonStep();
608
609
610 }
611 if (callFillComplete)
612 A->getBlock(0,0)->fillComplete( domainVec_.at(0)->getMapVecFieldUnique(),domainVec_.at(0)->getMapVecFieldUnique());
613
614}
615
616
617
628
629template <class SC, class LO, class GO, class NO>
630void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec, FiniteElement elementBlock, int dofs){
631
632 Teuchos::ArrayRCP<SC> resArray_block = res->getBlockNonConst(0)->getDataNonConst(0);
633
634 vec_LO_Type nodeList_block = elementBlock.getVectorNodeList();
635
636 for(int i=0; i< nodeList_block.size() ; i++){
637 for(int d=0; d<dofs; d++)
638 resArray_block[nodeList_block[i]*dofs+d] += (*rhsVec)[i*dofs+d];
639 }
640}
641
642// Check the order of chemistry and solid in system matrix
643template <class SC, class LO, class GO, class NO>
645 std::string FETypeChem,
646 std::string FETypeSolid,
647 int degree,
648 int dofsChem,
649 int dofsSolid,
650 MultiVectorPtr_Type c_rep,
651 MultiVectorPtr_Type d_rep,
652 BlockMatrixPtr_Type &A,
653 BlockMultiVectorPtr_Type &resVec,
654 ParameterListPtr_Type params,
655 std::string assembleMode,
656 bool callFillComplete,
657 int FELocExternal){
658
659 if((FETypeChem != "P2") || (FETypeSolid != "P2") || dim != 3)
660 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No AceGen Implementation available for Discretization and Dimension." );
661
662
663 UN FElocChem = 1; //checkFE(dim,FETypeChem); // Checks for different domains which belongs to a certain fetype
664 UN FElocSolid = 0; //checkFE(dim,FETypeSolid); // Checks for different domains which belongs to a certain fetype
665
666 ElementsPtr_Type elementsChem= domainVec_.at(FElocChem)->getElementsC();
667
668 ElementsPtr_Type elementsSolid = domainVec_.at(FElocSolid)->getElementsC();
669
670 //this->domainVec_.at(FElocChem)->info();
671 //this->domainVec_.at(FElocSolid)->info();
672 //int dofsElement = elements->getElement(0).getVectorNodeList().size();
674 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FElocSolid)->getPointsRepeated();
675
676 MapConstPtr_Type mapChem = domainVec_.at(FElocChem)->getMapRepeated();
677
678 MapConstPtr_Type mapSolid = domainVec_.at(FElocSolid)->getMapRepeated();
679
680 vec_dbl_Type solution_c;
681 vec_dbl_Type solution_d;
682
683 vec_dbl_ptr_Type rhsVec;
684
687 int numChem=3;
688 if(FETypeChem == "P2"){
689 numChem=6;
690 }
691 if(dim==3){
692 numChem=4;
693 if(FETypeChem == "P2")
694 numChem=10;
695 }
696 int numSolid=3;
697 if(FETypeSolid == "P2")
698 numSolid=6;
699
700 if(dim==3){
701 numSolid=4;
702 if(FETypeSolid == "P2")
703 numSolid=10;
704 }
705 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
706 tuple_ssii_Type chem ("Chemistry",FETypeChem,dofsChem,numChem);
707 tuple_ssii_Type solid ("Solid",FETypeSolid,dofsSolid,numSolid);
708 problemDisk->push_back(solid);
709 problemDisk->push_back(chem);
710
711 tuple_disk_vec_ptr_Type problemDiskChem = Teuchos::rcp(new tuple_disk_vec_Type(0));
712 problemDiskChem->push_back(chem);
713
714 std::string SCIModel = params->sublist("Parameter").get("Structure Model","SCI_simple");
715
716 if(assemblyFEElements_.size()== 0){
717 initAssembleFEElements(SCIModel,problemDisk,elementsChem, params,pointsRep,domainVec_.at(FElocSolid)->getElementMap());
718 }
719 else if(assemblyFEElements_.size() != elementsChem->numberElements())
720 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
721
722 //SmallMatrixPtr_Type elementMatrix =Teuchos::rcp( new SmallMatrix_Type( dofsElement));
723
724 MultiVectorPtr_Type resVec_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapRepeated(), 1 ) );
725 MultiVectorPtr_Type resVec_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldRepeated(), 1 ) );
726
727 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 2) );
728 resVecRep->addBlock(resVec_d,0);
729 resVecRep->addBlock(resVec_c,1);
730
731 SC detB;
732 SC absDetB;
733 SmallMatrix<SC> B(dim);
734 SmallMatrix<SC> Binv(dim);
735
736
737 for (UN T=0; T<assemblyFEElements_.size(); T++) {
738 vec_dbl_Type solution(0);
739
740 solution_c = getSolution(elementsChem->getElement(T).getVectorNodeList(), c_rep,dofsChem);
741 solution_d = getSolution(elementsSolid->getElement(T).getVectorNodeList(), d_rep,dofsSolid);
742
743 // First Solid, then Chemistry
744 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
745 solution.insert( solution.end(), solution_c.begin(), solution_c.end() );
746
747 assemblyFEElements_[T]->updateSolution(solution);
748
749 SmallMatrixPtr_Type elementMatrix;
750
751 // ------------------------
752 /*buildTransformation(elementsSolid->getElement(T).getVectorNodeList(), pointsRep, B, FETypeSolid);
753 detB = B.computeInverse(Binv);
754 absDetB = std::fabs(detB);
755 std::cout << " Determinante " << detB << std::endl;*/
756 // ------------------------
757
758
759
760
761 if(assembleMode == "Jacobian"){
762 assemblyFEElements_[T]->assembleJacobian();
763
764 elementMatrix = assemblyFEElements_[T]->getJacobian();
765 // elementMatrix->print();
766 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
767
768 addFeBlockMatrix(A, elementMatrix, elementsSolid->getElement(T), elementsSolid->getElement(T), mapSolid, mapChem, problemDisk);
769
770
771
772 }
773 if(assembleMode == "Rhs"){
774 assemblyFEElements_[T]->assembleRHS();
775 rhsVec = assemblyFEElements_[T]->getRHS();
776 addFeBlockMv(resVecRep, rhsVec, elementsSolid->getElement(T),elementsChem->getElement(T), dofsSolid,dofsChem);
777
778 }
779 if(assembleMode=="MassMatrix"){
780 assemblyFEElements_[T]->assembleJacobian();
781
782 AssembleFE_SCI_SMC_Active_Growth_Reorientation_Ptr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFE_SCI_SMC_Active_Growth_Reorientation_Type>(assemblyFEElements_[T] );
783 elTmp->getMassMatrix(elementMatrix);
784 //elementMatrix->print();
785 addFeBlock(A, elementMatrix, elementsChem->getElement(T), mapChem, 0, 0, problemDiskChem);
786
787
788 }
789
790
791
792
793 }
794 if ( assembleMode == "Jacobian"){
795 A->getBlock(0,0)->fillComplete();
796 A->getBlock(1,0)->fillComplete(domainVec_.at(FElocSolid)->getMapVecFieldUnique(),domainVec_.at(FElocChem)->getMapUnique());
797 A->getBlock(0,1)->fillComplete(domainVec_.at(FElocChem)->getMapUnique(),domainVec_.at(FElocSolid)->getMapVecFieldUnique());
798 A->getBlock(1,1)->fillComplete();
799 }
800 else if(assembleMode == "Rhs"){
801
802 MultiVectorPtr_Type resVecUnique_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldUnique(), 1 ) );
803 MultiVectorPtr_Type resVecUnique_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapUnique(), 1 ) );
804
805 resVecUnique_d->putScalar(0.);
806 resVecUnique_c->putScalar(0.);
807
808 resVecUnique_d->exportFromVector( resVec_d, true, "Add" );
809 resVecUnique_c->exportFromVector( resVec_c, true, "Add" );
810
811 resVec->addBlock(resVecUnique_d,0);
812 resVec->addBlock(resVecUnique_c,1);
813 }
814 else if(assembleMode == "MassMatrix"){
815 A->getBlock(0,0)->fillComplete();
816 }
817
818}
819
820// Check the order of chemistry and solid in system matrix
821template <class SC, class LO, class GO, class NO>
823 std::string FETypeChem,
824 std::string FETypeSolid,
825 int degree,
826 int dofsChem,
827 int dofsSolid,
828 MultiVectorPtr_Type c_rep,
829 MultiVectorPtr_Type d_rep,
830 BlockMatrixPtr_Type &A,
831 int blockRow,
832 int blockCol,
833 BlockMultiVectorPtr_Type &resVec,
834 int block,
835 ParameterListPtr_Type params,
836 std::string assembleMode,
837 bool callFillComplete,
838 int FELocExternal){
839
840 if((FETypeChem != "P2") || (FETypeSolid != "P2") || dim != 3)
841 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No AceGen Implementation available for Discretization and Dimension." );
842 if((blockRow != blockCol) && blockRow != 0)
843 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Block assemblyDeformDiffu AceGEN Version only implemented for 0,0 block right now" );
844
845 //UN FElocChem = 1; //checkFE(dim,FETypeChem); // Checks for different domains which belongs to a certain fetype
846 UN FElocSolid = 0; //checkFE(dim,FETypeSolid); // Checks for different domains which belongs to a certain fetype
847
848 ElementsPtr_Type elementsChem= domainVec_.at(FElocSolid)->getElementsC();
849
850 ElementsPtr_Type elementsSolid = domainVec_.at(FElocSolid)->getElementsC();
851
852 //this->domainVec_.at(FElocChem)->info();
853 //this->domainVec_.at(FElocSolid)->info();
854 //int dofsElement = elements->getElement(0).getVectorNodeList().size();
855
856 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FElocSolid)->getPointsRepeated();
857
858 //MapConstPtr_Type mapChem = domainVec_.at(FElocChem)->getMapRepeated();
859
860 MapConstPtr_Type mapSolid = domainVec_.at(FElocSolid)->getMapRepeated();
861
862 vec_dbl_Type solution_c;
863 vec_dbl_Type solution_d;
864
865 vec_dbl_ptr_Type rhsVec;
866
869 int numChem=3;
870 if(FETypeChem == "P2"){
871 numChem=6;
872 }
873 if(dim==3){
874 numChem=4;
875 if(FETypeChem == "P2")
876 numChem=10;
877 }
878 int numSolid=3;
879 if(FETypeSolid == "P2")
880 numSolid=6;
881
882 if(dim==3){
883 numSolid=4;
884 if(FETypeSolid == "P2")
885 numSolid=10;
886 }
887 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
888 tuple_ssii_Type chem ("Chemistry",FETypeChem,dofsChem,numChem);
889 tuple_ssii_Type solid ("Solid",FETypeSolid,dofsSolid,numSolid);
890 problemDisk->push_back(solid);
891 problemDisk->push_back(chem);
892
893 std::string SCIModel = params->sublist("Parameter").get("Structure Model","SCI_simple");
894
895 if(assemblyFEElements_.size()== 0){
896 initAssembleFEElements(SCIModel,problemDisk,elementsChem, params,pointsRep,domainVec_.at(FElocSolid)->getElementMap());
897 }
898 else if(assemblyFEElements_.size() != elementsChem->numberElements())
899 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
900
901 //SmallMatrixPtr_Type elementMatrix =Teuchos::rcp( new SmallMatrix_Type( dofsElement));
902
903 //MultiVectorPtr_Type resVec_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapRepeated(), 1 ) );
904 MultiVectorPtr_Type resVec_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldRepeated(), 1 ) );
905
906 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 1) );
907 resVecRep->addBlock(resVec_d,0);
908 //resVecRep->addBlock(resVec_c,1);
909
910 for (UN T=0; T<assemblyFEElements_.size(); T++) {
911 vec_dbl_Type solution(0);
912
913 solution_c = getSolution(elementsChem->getElement(T).getVectorNodeList(), c_rep,dofsChem);
914 solution_d = getSolution(elementsSolid->getElement(T).getVectorNodeList(), d_rep,dofsSolid);
915
916 // First Solid, then Chemistry
917 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
918 solution.insert( solution.end(), solution_c.begin(), solution_c.end() );
919
920 assemblyFEElements_[T]->updateSolution(solution);
921
922 SmallMatrixPtr_Type elementMatrix;
923
924 if(assembleMode == "Jacobian"){
925 assemblyFEElements_[T]->assembleJacobian();
926
927 elementMatrix = assemblyFEElements_[T]->getJacobian();
928 // elementMatrix->print();
929 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
930 addFeBlock(A, elementMatrix, elementsSolid->getElement(T), mapSolid, 0, 0, problemDisk);
931 //addFeBlockMatrix(A, elementMatrix, elementsSolid->getElement(T), mapSolid, mapChem, problemDisk);
932 }
933 if(assembleMode == "Rhs"){
934 assemblyFEElements_[T]->assembleRHS();
935 rhsVec = assemblyFEElements_[T]->getRHS();
936 addFeBlockMv(resVecRep, rhsVec, elementsSolid->getElement(T), dofsSolid);
937 }
938 //if(assembleMode=="compute")
939 // assemblyFEElements_[T]->compute();
940
941
942
943
944 }
945 if ( assembleMode != "Rhs"){
946 A->getBlock(0,0)->fillComplete();
947 //A->getBlock(1,0)->fillComplete(domainVec_.at(FElocSolid)->getMapVecFieldUnique(),domainVec_.at(FElocChem)->getMapUnique());
948 //A->getBlock(0,1)->fillComplete(domainVec_.at(FElocChem)->getMapUnique(),domainVec_.at(FElocSolid)->getMapVecFieldUnique());
949 //A->getBlock(1,1)->fillComplete();
950 }
951
952 if(assembleMode == "Rhs"){
953
954 MultiVectorPtr_Type resVecUnique_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldUnique(), 1 ) );
955 //MultiVectorPtr_Type resVecUnique_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapUnique(), 1 ) );
956
957 resVecUnique_d->putScalar(0.);
958 //resVecUnique_c->putScalar(0.);
959
960 resVecUnique_d->exportFromVector( resVec_d, true, "Add" );
961 //resVecUnique_c->exportFromVector( resVec_c, true, "Add" );
962
963 resVec->addBlock(resVecUnique_d,0);
964 //resVec->addBlock(resVecUnique_c,1);
965 }
966
967
968}
969
981template <class SC, class LO, class GO, class NO>
982void FE<SC,LO,GO,NO>::addFeBlockMatrix(BlockMatrixPtr_Type &A, SmallMatrixPtr_Type elementMatrix, FiniteElement element1, FiniteElement element2, MapConstPtr_Type mapFirstRow,MapConstPtr_Type mapSecondRow, tuple_disk_vec_ptr_Type problemDisk){
983
984 int numDisk = problemDisk->size();
985
986 int dofs1 = std::get<2>(problemDisk->at(0));
987 int dofs2 = std::get<2>(problemDisk->at(1));
988
989 int numNodes1 = std::get<3>(problemDisk->at(0));
990 int numNodes2=std::get<3>(problemDisk->at(1));
991
992 int dofsBlock1 = dofs1*numNodes1;
993 int dofsBlock2 = dofs2*numNodes2;
994
995 Teuchos::Array<SC> value1( numNodes1, 0. );
996 Teuchos::Array<GO> columnIndices1( numNodes1, 0 );
997
998 Teuchos::Array<SC> value2( numNodes2, 0. );
999 Teuchos::Array<GO> columnIndices2( numNodes2, 0 );
1000
1001 for (UN i=0; i < numNodes1 ; i++) {
1002 for(int di=0; di<dofs1; di++){
1003 GO row =GO (dofs1* mapFirstRow->getGlobalElement( element1.getNode(i) )+di);
1004 for(int d=0; d<dofs1; d++){
1005 for (UN j=0; j < columnIndices1.size(); j++){
1006 columnIndices1[j] = GO ( dofs1 * mapFirstRow->getGlobalElement( element1.getNode(j) ) + d );
1007 value1[j] = (*elementMatrix)[dofs1*i+di][dofs1*j+d];
1008 }
1009 A->getBlock(0,0)->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
1010 }
1011 }
1012 }
1013 int offset= numNodes1*dofs1;
1014
1015
1016 Teuchos::Array<SC> value( 1, 0. );
1017 Teuchos::Array<GO> columnIndex( 1, 0 );
1018 for (UN i=0; i < numNodes2 ; i++) {
1019 for(int di=0; di<dofs2; di++){
1020 GO row =GO (dofs2* mapSecondRow->getGlobalElement( element2.getNode(i) )+di);
1021 for(int d=0; d<dofs2; d++){
1022 for (UN j=0; j < columnIndices2.size(); j++){
1023 double tmpValue = (*elementMatrix)[offset+dofs2*i+di][offset+dofs2*j+d];
1024 if(std::fabs(tmpValue) > 1.e-13){
1025 columnIndex[0] = GO ( dofs2 * mapSecondRow->getGlobalElement( element2.getNode(j) ) + d );
1026 value[0] = tmpValue;
1027 A->getBlock(1,1)->insertGlobalValues( row, columnIndex(), value() ); // Automatically adds entries if a value already exists
1028
1029 }
1030 }
1031 }
1032 }
1033 }
1034
1035 for (UN i=0; i < numNodes1; i++){
1036 for(int di=0; di<dofs1; di++){
1037 GO row =GO (dofs1* mapFirstRow->getGlobalElement( element1.getNode(i) )+di);
1038 for(int d=0; d<dofs2; d++){
1039 for (UN j=0; j < numNodes2 ; j++) {
1040 value2[j] = (*elementMatrix)[i*dofs1+di][offset+j*dofs2+d];
1041 columnIndices2[j] =GO (dofs2* mapSecondRow->getGlobalElement( element2.getNode(j) )+d);
1042 }
1043 A->getBlock(0,1)->insertGlobalValues( row, columnIndices2(), value2() ); // Automatically adds entries if a value already exists
1044 }
1045 }
1046 }
1047
1048 for (UN j=0; j < numNodes2; j++){
1049 for(int di=0; di<dofs2; di++){
1050 GO row = GO (dofs2* mapSecondRow->getGlobalElement( element2.getNode(j) ) +di );
1051 for(int d=0; d<dofs1; d++){
1052 for (UN i=0; i < numNodes1 ; i++) {
1053 value1[i] = (*elementMatrix)[offset+j*dofs2+di][dofs1*i+d];
1054 columnIndices1[i] =GO (dofs1* mapFirstRow->getGlobalElement( element1.getNode(i) )+d);
1055 }
1056 A->getBlock(1,0)->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
1057 }
1058 }
1059 }
1060
1061
1062}
1063
1064
1076
1077template <class SC, class LO, class GO, class NO>
1079 std::string FETypeVelocity,
1080 std::string FETypePressure,
1081 int degree,
1082 int dofsVelocity,
1083 int dofsPressure,
1084 MultiVectorPtr_Type u_rep,
1085 MultiVectorPtr_Type p_rep,
1086 BlockMatrixPtr_Type &A,
1087 BlockMultiVectorPtr_Type &resVec,
1088 SmallMatrix_Type coeff,
1089 ParameterListPtr_Type params,
1090 bool reAssemble,
1091 std::string assembleMode,
1092 bool callFillComplete,
1093 int FELocExternal){
1094
1095
1096 UN FElocVel = checkFE(dim,FETypeVelocity); // Checks for different domains which belongs to a certain fetype
1097 UN FElocPres = checkFE(dim,FETypePressure); // Checks for different domains which belongs to a certain fetype
1098
1099 ElementsPtr_Type elements = domainVec_.at(FElocVel)->getElementsC();
1100
1101 ElementsPtr_Type elementsPres = domainVec_.at(FElocPres)->getElementsC();
1102
1103 int dofsElement = elements->getElement(0).getVectorNodeList().size();
1104
1105 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FElocVel)->getPointsRepeated();
1106
1107 MapConstPtr_Type mapVel = domainVec_.at(FElocVel)->getMapRepeated();
1108
1109 MapConstPtr_Type mapPres = domainVec_.at(FElocPres)->getMapRepeated();
1110
1111 vec_dbl_Type solution(0);
1112 vec_dbl_Type solution_u;
1113 vec_dbl_Type solution_p;
1114
1115 vec_dbl_ptr_Type rhsVec;
1116
1119 int numVelo=3;
1120 if(FETypeVelocity == "P2")
1121 numVelo=6;
1122
1123 if(dim==3){
1124 numVelo=4;
1125 if(FETypeVelocity == "P2")
1126 numVelo=10;
1127 }
1128 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
1129 tuple_ssii_Type vel ("Velocity",FETypeVelocity,dofsVelocity,numVelo);
1130 tuple_ssii_Type pres ("Pressure",FETypePressure,dofsPressure,dim+1);
1131 problemDisk->push_back(vel);
1132 problemDisk->push_back(pres);
1133
1134 if(assemblyFEElements_.size()== 0){
1135 if(params->sublist("Material").get("Newtonian",true) == false)
1136 initAssembleFEElements("GeneralizedNewtonian",problemDisk,elements, params,pointsRep,domainVec_.at(FElocVel)->getElementMap()); // In cas of non Newtonian Fluid
1137 else
1138 initAssembleFEElements("NavierStokes",problemDisk,elements, params,pointsRep,domainVec_.at(FElocVel)->getElementMap());
1139 }
1140 else if(assemblyFEElements_.size() != elements->numberElements())
1141 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
1142
1143 //SmallMatrixPtr_Type elementMatrix =Teuchos::rcp( new SmallMatrix_Type( dofsElement));
1144
1145 MultiVectorPtr_Type resVec_u = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getMapVecFieldRepeated(), 1 ) );
1146 MultiVectorPtr_Type resVec_p = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocPres)->getMapRepeated(), 1 ) );
1147
1148 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 2) );
1149 resVecRep->addBlock(resVec_u,0);
1150 resVecRep->addBlock(resVec_p,1);
1151
1152
1153 for (UN T=0; T<assemblyFEElements_.size(); T++) {
1154 vec_dbl_Type solution(0);
1155
1156 solution_u = getSolution(elements->getElement(T).getVectorNodeList(), u_rep,dofsVelocity);
1157 solution_p = getSolution(elementsPres->getElement(T).getVectorNodeList(), p_rep,dofsPressure);
1158
1159 solution.insert( solution.end(), solution_u.begin(), solution_u.end() );
1160 solution.insert( solution.end(), solution_p.begin(), solution_p.end() );
1161
1162 assemblyFEElements_[T]->updateSolution(solution);
1163
1164 SmallMatrixPtr_Type elementMatrix;
1165
1166 if(assembleMode == "Jacobian"){
1167 assemblyFEElements_[T]->assembleJacobian();
1168
1169 elementMatrix = assemblyFEElements_[T]->getJacobian();
1170
1171 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
1172
1173 if(reAssemble)
1174 addFeBlock(A, elementMatrix, elements->getElement(T), mapVel, 0, 0, problemDisk);
1175 else
1176 addFeBlockMatrix(A, elementMatrix, elements->getElement(T), elementsPres->getElement(T), mapVel, mapPres, problemDisk);
1177 }
1178 if(assembleMode == "FixedPoint"){
1179
1180 //AssembleFENavierStokesPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFENavierStokes_Type>(assemblyFEElements_[T] ); // Why should we need a pointer we can directly call it using assemblyFEElements_[T]? Because assemblyFixedPoint is not a function of base class
1181
1182 if(params->sublist("Material").get("Newtonian",true) == false)
1183 {
1184 AssembleFEGeneralizedNewtonianPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFEGeneralizedNewtonian_Type>( assemblyFEElements_[T] );
1185 elTmp->assembleFixedPoint();
1186 elementMatrix = elTmp->getFixedPointMatrix();
1187 }
1188 else // Newtonian Case
1189 {
1190 AssembleFENavierStokesPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFENavierStokes_Type>( assemblyFEElements_[T] );
1191 elTmp->assembleFixedPoint();
1192 elementMatrix = elTmp->getFixedPointMatrix();
1193 }
1194
1195
1196 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
1197
1198 if(reAssemble)
1199 addFeBlock(A, elementMatrix, elements->getElement(T), mapVel, 0, 0, problemDisk);
1200 else
1201 addFeBlockMatrix(A, elementMatrix, elements->getElement(T), elementsPres->getElement(T),mapVel, mapPres, problemDisk);
1202
1203 }
1204 if(assembleMode == "Rhs"){
1205 AssembleFENavierStokesPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFENavierStokes_Type>(assemblyFEElements_[T] );
1206 elTmp->setCoeff(coeff);// Coeffs from time discretization. Right now default [1][1] // [0][0]
1207 assemblyFEElements_[T]->assembleRHS();
1208 rhsVec = assemblyFEElements_[T]->getRHS();
1209 addFeBlockMv(resVecRep, rhsVec, elements->getElement(T),elementsPres->getElement(T), dofsVelocity,dofsPressure);
1210 }
1211
1212
1213 }
1214 if (callFillComplete && reAssemble && assembleMode != "Rhs" )
1215 A->getBlock(0,0)->fillComplete( domainVec_.at(FElocVel)->getMapVecFieldUnique(),domainVec_.at(FElocVel)->getMapVecFieldUnique());
1216 else if(callFillComplete && !reAssemble && assembleMode != "Rhs"){
1217 A->getBlock(0,0)->fillComplete();
1218 A->getBlock(1,0)->fillComplete(domainVec_.at(FElocVel)->getMapVecFieldUnique(),domainVec_.at(FElocPres)->getMapUnique());
1219 A->getBlock(0,1)->fillComplete(domainVec_.at(FElocPres)->getMapUnique(),domainVec_.at(FElocVel)->getMapVecFieldUnique());
1220 }
1221
1222 if(assembleMode == "Rhs"){
1223
1224 MultiVectorPtr_Type resVecUnique_u = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getMapVecFieldUnique(), 1 ) );
1225 MultiVectorPtr_Type resVecUnique_p = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocPres)->getMapUnique(), 1 ) );
1226
1227 resVecUnique_u->putScalar(0.);
1228 resVecUnique_p->putScalar(0.);
1229
1230 resVecUnique_u->exportFromVector( resVec_u, true, "Add" );
1231 resVecUnique_p->exportFromVector( resVec_p, true, "Add" );
1232
1233 resVec->addBlock(resVecUnique_u,0);
1234 resVec->addBlock(resVecUnique_p,1);
1235 }
1236
1237
1238}
1239
1240
1245template <class SC, class LO, class GO, class NO>
1246void FE<SC,LO,GO,NO>::changeLinearizationFE(std::string linearization)
1247{
1248 for (UN T=0; T<assemblyFEElements_.size(); T++) // For each assembledFEElement change Linearization
1249 {
1250 assemblyFEElements_[T]->changeLinearization(linearization);
1251 }
1252}
1253
1254
1263
1264
1265template <class SC, class LO, class GO, class NO>
1267 std::string FETypeVelocity,
1268 std::string FETypePressure,
1269 int dofsVelocity,
1270 int dofsPressure,
1271 MultiVectorPtr_Type u_rep,
1272 MultiVectorPtr_Type p_rep,
1273 ParameterListPtr_Type params){
1274
1275
1276 UN FElocVel = checkFE(dim,FETypeVelocity); // Checks for different domains which belongs to a certain fetype
1277 UN FElocPres = checkFE(dim,FETypePressure); // Checks for different domains which belongs to a certain fetype
1278
1279 ElementsPtr_Type elements = domainVec_.at(FElocVel)->getElementsC();
1280 ElementsPtr_Type elementsPres = domainVec_.at(FElocPres)->getElementsC();
1281
1282 vec_dbl_Type solution(0);
1283 vec_dbl_Type solution_u;
1284 vec_dbl_Type solution_p;
1285 vec_dbl_Type solution_viscosity;
1286
1287 // We have to compute viscosity solution in each element
1288 MultiVectorPtr_Type Sol_viscosity = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getElementMap(), 1 ) ); //
1289 BlockMultiVectorPtr_Type visco_output = Teuchos::rcp( new BlockMultiVector_Type(1) );
1290 visco_output->addBlock(Sol_viscosity,0);
1291
1292
1293 for (UN T=0; T<assemblyFEElements_.size(); T++) {
1294
1295 vec_dbl_Type solution(0);
1296 solution_u = getSolution(elements->getElement(T).getVectorNodeList(), u_rep,dofsVelocity); // get the solution inside an element on the nodes
1297 solution_p = getSolution(elementsPres->getElement(T).getVectorNodeList(), p_rep,dofsPressure);
1298
1299 solution.insert( solution.end(), solution_u.begin(), solution_u.end() ); // here we insert the solution
1300 solution.insert( solution.end(), solution_p.begin(), solution_p.end() );
1301
1302 assemblyFEElements_[T]->updateSolution(solution); // here we update the value of the solutions inside an element
1303
1304 assemblyFEElements_[T]->computeLocalconstOutputField(); // we compute the viscosity inside an element
1305 solution_viscosity = assemblyFEElements_[T]->getLocalconstOutputField();
1306
1307 Teuchos::ArrayRCP<SC> resArray_block = visco_output->getBlockNonConst(0)->getDataNonConst(0); // First
1308 resArray_block[T] = solution_viscosity[0]; // although it is a vector it only has one entry because we compute the value in the center of the element
1309
1310 } // end loop over all elements
1311 // We could also instead of just overwrite it add an aditional block such that we could also compute other output fields and save it in there
1312 this->const_output_fields= visco_output;
1313
1314
1315}
1316
1317
1318
1329
1330template <class SC, class LO, class GO, class NO>
1331void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec, FiniteElement elementBlock1,FiniteElement elementBlock2, int dofs1, int dofs2 ){
1332
1333 Teuchos::ArrayRCP<SC> resArray_block1 = res->getBlockNonConst(0)->getDataNonConst(0);
1334
1335 Teuchos::ArrayRCP<SC> resArray_block2 = res->getBlockNonConst(1)->getDataNonConst(0);
1336
1337 vec_LO_Type nodeList_block1 = elementBlock1.getVectorNodeList();
1338
1339 vec_LO_Type nodeList_block2 = elementBlock2.getVectorNodeList();
1340
1341 for(int i=0; i< nodeList_block1.size() ; i++){
1342 for(int d=0; d<dofs1; d++){
1343 resArray_block1[nodeList_block1[i]*dofs1+d] += (*rhsVec)[i*dofs1+d];
1344 }
1345 }
1346 int offset = nodeList_block1.size()*dofs1;
1347
1348 for(int i=0; i < nodeList_block2.size(); i++){
1349 for(int d=0; d<dofs2; d++)
1350 resArray_block2[nodeList_block2[i]*dofs2+d] += (*rhsVec)[i*dofs2+d+offset];
1351 }
1352
1353}
1354
1355
1368template <class SC, class LO, class GO, class NO>
1369void FE<SC,LO,GO,NO>::addFeBlock(BlockMatrixPtr_Type &A, SmallMatrixPtr_Type elementMatrix, FiniteElement element, MapConstPtr_Type mapRow, int row, int column, tuple_disk_vec_ptr_Type problemDisk){
1370
1371 int dofs1 = std::get<2>(problemDisk->at(row));
1372
1373 int numNodes1 = std::get<3>(problemDisk->at(row));
1374
1375 int dofsBlock1 = dofs1*numNodes1;
1376
1377 Teuchos::Array<SC> value( numNodes1, 0. );
1378 Teuchos::Array<GO> columnIndices( numNodes1, 0 );
1379
1380 for (UN i=0; i < numNodes1 ; i++) {
1381 for(int di=0; di<dofs1; di++){
1382 GO rowID =GO (dofs1* mapRow->getGlobalElement( element.getNode(i) )+di);
1383 for(int d=0; d<dofs1; d++){
1384 for (UN j=0; j < columnIndices.size(); j++){
1385 columnIndices[j] = GO ( dofs1 * mapRow->getGlobalElement( element.getNode(j) ) + d );
1386 value[j] = (*elementMatrix)[dofs1*i+di][dofs1*j+d];
1387 }
1388 A->getBlock(row,column)->insertGlobalValues( rowID, columnIndices(), value() ); // Automatically adds entries if a value already exists
1389 }
1390 }
1391 }
1392}
1393
1404template <class SC, class LO, class GO, class NO>
1405void FE<SC,LO,GO,NO>::initAssembleFEElements(std::string elementType,tuple_disk_vec_ptr_Type problemDisk,ElementsPtr_Type elements, ParameterListPtr_Type params,vec2D_dbl_ptr_Type pointsRep, MapConstPtr_Type elementMap){
1406
1407 vec2D_dbl_Type nodes;
1408 for (UN T=0; T<elements->numberElements(); T++) {
1409
1410 nodes = getCoordinates(elements->getElement(T).getVectorNodeList(), pointsRep);
1411
1412 AssembleFEFactory<SC,LO,GO,NO> assembleFEFactory;
1413
1414 AssembleFEPtr_Type assemblyFE = assembleFEFactory.build(elementType,elements->getElement(T).getFlag(),nodes, params,problemDisk);
1415 //
1416 assemblyFE->setGlobalElementID(elementMap->getGlobalElement(T));
1417
1418 assemblyFEElements_.push_back(assemblyFE);
1419
1420 }
1421
1422}
1423
1433
1434template <class SC, class LO, class GO, class NO>
1435vec2D_dbl_Type FE<SC,LO,GO,NO>::getCoordinates(vec_LO_Type localIDs, vec2D_dbl_ptr_Type points){
1436
1437 vec2D_dbl_Type coordinates(0,vec_dbl_Type( points->at(0).size()));
1438 for(int i=0; i < localIDs.size() ; i++){
1439 coordinates.push_back(points->at(localIDs[i]));
1440 }
1441
1442 return coordinates;
1443}
1444
1454
1455template <class SC, class LO, class GO, class NO>
1456vec_dbl_Type FE<SC,LO,GO,NO>::getSolution(vec_LO_Type localIDs, MultiVectorPtr_Type u_rep, int dofsVelocity){
1457
1458 Teuchos::ArrayRCP<SC> uArray = u_rep->getDataNonConst(0);
1459
1460 vec_dbl_Type solution(0);
1461 for(int i=0; i < localIDs.size() ; i++){
1462 for(int d=0; d<dofsVelocity; d++)
1463 solution.push_back(uArray[localIDs[i]*dofsVelocity+d]);
1464 }
1465
1466 return solution;
1467}
1468
1469
1470template <class SC, class LO, class GO, class NO>
1471void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
1472 vec3D_dbl_Type& dPhiOut,
1473 const SmallMatrix<SC>& Binv){
1474 UN dim = Binv.size();
1475 for (UN w=0; w<dPhiIn->size(); w++){
1476 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
1477 for (UN d1=0; d1<dim; d1++) {
1478 for (UN d2=0; d2<dim; d2++) {
1479 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
1480 }
1481 }
1482 }
1483 }
1484}
1485
1486template <class SC, class LO, class GO, class NO>
1487void FE<SC,LO,GO,NO>::assemblyEmptyMatrix(MatrixPtr_Type &A){
1488 A->fillComplete();
1489}
1490template <class SC, class LO, class GO, class NO>
1491void FE<SC,LO,GO,NO>::assemblyIdentity(MatrixPtr_Type &A){
1492 Teuchos::Array<SC> value(1, Teuchos::ScalarTraits<SC>::one() );
1493 Teuchos::Array<GO> index(1);
1494 MapConstPtr_Type map = A->getMap();
1495 for (int i=0; i<A->getNodeNumRows(); i++) {
1496 index[0] = map->getGlobalElement( i );
1497 A->insertGlobalValues( index[0], index(), value() );
1498 }
1499 A->fillComplete();
1500}
1501
1502
1503template <class SC, class LO, class GO, class NO>
1504void FE<SC,LO,GO,NO>::assemblySurfaceRobinBC(int dim,
1505 std::string FETypeP,
1506 std::string FETypeV,
1507 MultiVectorPtr_Type u,
1508 MatrixPtr_Type A,
1509 std::vector<SC>& funcParameter,
1510 RhsFunc_Type func,
1511 ParameterListPtr_Type parameters){
1512
1513 ElementsPtr_Type elements = domainVec_.at(1)->getElementsC();
1514 ElementsPtr_Type elementsV = domainVec_.at(0)->getElementsC();
1515
1516 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(1)->getPointsRepeated();
1517
1518 MapConstPtr_Type map = domainVec_.at(1)->getMapRepeated();
1519
1520 vec2D_dbl_ptr_Type phi,phiV;
1521 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1522
1523
1524 UN extraDeg = Helper::determineDegree( dim-1, FETypeV, Helper::Deriv0);
1525 UN deg = Helper::determineDegree( dim-1, FETypeP, Helper::Deriv0)*2 + extraDeg;
1526
1527
1528 Helper::getPhi(phi, weights, dim-1, FETypeP, deg);
1529 Helper::getPhi(phiV, weights, dim-1, FETypeV, deg);
1530
1531 SC detB;
1532 SC absDetB;
1533 SmallMatrix<SC> B(dim);
1534
1535
1536 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
1537 vec_dbl_Type uLocN( weights->size() , -1. );
1538
1539 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1540
1541
1542 SC elScaling;
1543 vec_dbl_Type b(dim);
1544
1545 std::vector<double> valueFunc(dim);
1546 // The second last entry is a placeholder for the surface element flag. It will be set below
1547 SC* paramsFunc = &(funcParameter[0]);
1548 for (UN T=0; T<elements->numberElements(); T++) {
1549 FiniteElement fe = elementsV->getElement( T );
1550 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
1551 for (int surface=0; surface<fe.numSubElements(); surface++) {
1552 FiniteElement feSub = subEl->getElement( surface );
1553 if(subEl->getDimension() == dim-1){
1554 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
1555
1556 vec_int_Type nodeList = feSub.getVectorNodeListNonConst();
1557 vec_int_Type nodeListP = elements->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
1558
1559 vec_dbl_Type v_E(dim,1.);
1560 double norm_v_E=1.;
1561 vec_dbl_Type x(dim,0.); //dummy
1562 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
1563
1564 func( &x[0], &valueFunc[0], paramsFunc);
1565 if(valueFunc[0] > 0.){
1566 Helper::computeSurfaceNormal(dim, pointsRep,nodeListP,v_E,norm_v_E);
1567
1568 Helper::buildTransformationSurface( nodeListP, pointsRep, B, b, FETypeP);
1569
1570 elScaling = B.computeScaling( );
1571 for (int w=0; w<phiV->size(); w++){ //quads points
1572 for (int d=0; d<dim; d++) {
1573 uLoc[d][w] = 0.;
1574 for (int i=0; i < phiV->at(0).size(); i++) {
1575 LO index = dim * nodeList[i] + d;
1576 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
1577 }
1578 }
1579 }
1580 for (int w=0; w<phiV->size(); w++){ //quads points
1581 uLocN[w] = 0.;
1582 for (int d=0; d<dim; d++) {
1583 uLocN[w] += uLoc[d][w] *v_E[d] / norm_v_E;
1584 }
1585 }
1586 for (UN i=0; i < phi->at(0).size(); i++) {
1587 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1588 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1589 for (UN j=0; j < value.size(); j++) {
1590 for (UN w=0; w<phi->size(); w++) {
1591 value[j] += weights->at(w) * uLocN[w]* (*phi)[w][j] * (*phi)[w][i] ;
1592 }
1593 value[j] *= elScaling;
1594 indices[j] = GO ( map->getGlobalElement( nodeListP[j] ) );
1595 }
1596
1597 GO row = GO ( map->getGlobalElement( nodeListP[i] ) );
1598 A->insertGlobalValues( row, indices(), value() );
1599 }
1600
1601 }
1602 }
1603 }
1604 }
1605 A->fillComplete();
1606}
1607
1608// Assembling the nonlinear reaction part of Reaction-Diffusion equation
1609// Gerneral function in case of nonlinear reaction function
1610// template <class SC, class LO, class GO, class NO>
1611// void FE<SC,LO,GO,NO>::assemblyReactionTerm(int dim,
1612// std::string FEType,
1613// MatrixPtr_Type &A,
1614// MultiVectorPtr_Type u,
1615// bool callFillComplete,
1616// std::vector<SC>& funcParameter,
1617// RhsFunc_Type reactionFunc){
1618
1619// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1620// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1621
1622// UN FEloc = checkFE(dim,FEType);
1623
1624// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1625
1626// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1627
1628// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1629
1630// vec2D_dbl_ptr_Type phi;
1631// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1632
1633// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1634
1635// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1636// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1637// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1638// extraDeg;
1639
1640// Helper::getPhi(phi, weights, dim, FEType, deg);
1641
1642// // We have a scalar value of concentration in each point
1643// vec_dbl_Type uLoc( weights->size() , -1. );
1644// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1645
1646// std::vector<double> valueFunc(1);
1647
1648// SC* paras = &(funcParameter[0]);
1649
1650// SC detB;
1651// SC absDetB;
1652// SmallMatrix<SC> B(dim);
1653// SmallMatrix<SC> Binv(dim);
1654
1655// for (UN T=0; T<elements->numberElements(); T++) {
1656// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1657// detB = B.computeInverse(Binv);
1658// absDetB = std::fabs(detB);
1659
1660// // Building u
1661// for (int w=0; w<phi->size(); w++){ //quadpoints
1662// uLoc[w] = 0.;
1663// for (int i=0; i < phi->at(0).size(); i++) { // points of element
1664// LO index = elements->getElement(T).getNode(i);
1665// uLoc[w] += uArray[index] * phi->at(w).at(i);
1666// }
1667// }
1668
1669// for (UN i=0; i < phi->at(0).size(); i++) {
1670// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1671// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1672// for (UN j=0; j < value.size(); j++) {
1673// for (UN w=0; w<phi->size(); w++) {
1674// value[j] += weights->at(w) * uLoc[w] * (*phi)[w][i] ;
1675// }
1676// reactionFunc(&value[j], &valueFunc[0] ,paras);
1677
1678// value[j] *= valueFunc[0] * absDetB;
1679// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1680// value[j] = 0.;
1681// }
1682// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1683
1684// }
1685// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1686
1687
1688// A->insertGlobalValues( row, indices(), value() );
1689
1690// }
1691// }
1692
1693// if (callFillComplete)
1694// A->fillComplete();
1695// }
1696
1697
1698// // Assembling the nonlinear reaction part of Reaction-Diffusion equation
1699// template <class SC, class LO, class GO, class NO>
1700// void FE<SC,LO,GO,NO>::assemblyLinearReactionTerm(int dim,
1701// std::string FEType,
1702// MatrixPtr_Type &A,
1703// bool callFillComplete,
1704// std::vector<SC>& funcParameter,
1705// RhsFunc_Type reactionFunc){
1706
1707// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1708// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1709
1710// UN FEloc = checkFE(dim,FEType);
1711
1712// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1713
1714// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1715
1716// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1717
1718// vec2D_dbl_ptr_Type phi;
1719// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1720
1721// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1722// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1723// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1724// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1725// extraDeg;
1726
1727// Helper::getPhi(phi, weights, dim, FEType, deg);
1728
1729// std::vector<double> valueFunc(1);
1730
1731// SC* paras = &(funcParameter[0]);
1732
1733// SC detB;
1734// SC absDetB;
1735// SmallMatrix<SC> B(dim);
1736// SmallMatrix<SC> Binv(dim);
1737
1738// for (UN T=0; T<elements->numberElements(); T++) {
1739// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1740// detB = B.computeInverse(Binv);
1741// absDetB = std::fabs(detB);
1742
1743// for (UN i=0; i < phi->at(0).size(); i++) {
1744// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1745// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1746// for (UN j=0; j < value.size(); j++) {
1747// for (UN w=0; w<phi->size(); w++) {
1748// value[j] += weights->at(w) * (*phi)[w][j] * (*phi)[w][i] ;
1749// }
1750// reactionFunc(&value[j], &valueFunc[0] ,paras);
1751
1752// value[j] *= valueFunc[0] * absDetB;
1753// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1754// value[j] = 0.;
1755// }
1756// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1757
1758// }
1759// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1760
1761// A->insertGlobalValues( row, indices(), value() );
1762
1763// }
1764// }
1765// if (callFillComplete)
1766// A->fillComplete();
1767
1768// A->print();
1769
1770// }
1771
1772// Assembling the nonlinear reaction part of Reaction-Diffusion equation
1773// template <class SC, class LO, class GO, class NO>
1774// void FE<SC,LO,GO,NO>::assemblyDReactionTerm(int dim,
1775// std::string FEType,
1776// MatrixPtr_Type &A,
1777// MultiVectorPtr_Type u,
1778// bool callFillComplete,
1779// std::vector<SC>& funcParameter,
1780// RhsFunc_Type reactionFunc){
1781
1782// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1783// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1784
1785// UN FEloc = checkFE(dim,FEType);
1786
1787// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1788
1789// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1790
1791// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1792
1793// vec2D_dbl_ptr_Type phi;
1794// vec3D_dbl_ptr_Type dPhi;
1795// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1796
1797// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1798// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1799// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1800// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1801// extraDeg;
1802
1803// Helper::getPhi(phi, weights, dim, FEType, deg);
1804
1805// Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1806
1807// // We have a scalar value of concentration in each point
1808// vec2D_dbl_Type duLoc( weights->size() ,vec_dbl_Type(dim ,-1. ));
1809// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1810
1811// std::vector<double> valueFunc(1);
1812
1813// SC* paras = &(funcParameter[0]);
1814
1815// SC detB;
1816// SC absDetB;
1817// SmallMatrix<SC> B(dim);
1818// SmallMatrix<SC> Binv(dim);
1819
1820// for (UN T=0; T<elements->numberElements(); T++) {
1821
1822
1823// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1824// detB = B.computeInverse(Binv);
1825// absDetB = std::fabs(detB);
1826
1827// vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1828// applyBTinv( dPhi, dPhiTrans, Binv );
1829
1830// for (int w=0; w<dPhiTrans.size(); w++){ //quads points
1831// for (int i=0; i < dPhiTrans[0].size(); i++) {
1832// LO index = elements->getElement(T).getNode(i) ;
1833// for (int d2=0; d2<dim; d2++)
1834// duLoc[w][d2] += uArray[index] * dPhiTrans[w][i][d2];
1835// }
1836
1837// }
1838
1839
1840// for (UN i=0; i < phi->at(0).size(); i++) {
1841// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1842// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1843// for (UN j=0; j < value.size(); j++) {
1844// for (UN d2=0; d2<dim; d2++){
1845// for (UN w=0; w<phi->size(); w++) {
1846// value[j] += weights->at(w) * duLoc[w][d2] * (*phi)[w][i] ;
1847// }
1848// }
1849// reactionFunc(&value[j], &valueFunc[0] ,paras);
1850
1851// value[j] *= valueFunc[0] * absDetB;
1852// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1853// value[j] = 0.;
1854// }
1855// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1856
1857// }
1858// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1859// A->insertGlobalValues( row, indices(), value() );
1860// }
1861// }
1862
1863// if (callFillComplete)
1864// A->fillComplete();
1865// }
1866
1876template <class SC, class LO, class GO, class NO>
1878 std::string FEType,
1879 int degree,
1880 int dofs,
1881 BlockMatrixPtr_Type &A,
1882 bool callFillComplete,
1883 int FELocExternal){
1884 ParameterListPtr_Type params = Teuchos::getParametersFromXmlFile("parametersProblemLaplace.xml");
1885
1886 UN FEloc = checkFE(dim,FEType);
1887 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1888 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1889 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1890 vec2D_dbl_Type nodes;
1891 int numNodes=dim+1;
1892 if(FEType == "P2"){
1893 numNodes= 6;
1894 if(dim==3)
1895 numNodes=10;
1896 }
1897 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
1898 tuple_ssii_Type vel ("Laplace",FEType,dofs,numNodes);
1899 problemDisk->push_back(vel);
1900 if(assemblyFEElements_.size()== 0)
1901 initAssembleFEElements("Laplace",problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
1902 else if(assemblyFEElements_.size() != elements->numberElements())
1903 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
1904 for (UN T=0; T<elements->numberElements(); T++) {
1905 assemblyFEElements_[T]->assembleJacobian();
1906 SmallMatrixPtr_Type elementMatrix = assemblyFEElements_[T]->getJacobian();
1907 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
1908
1909 }
1910 if(callFillComplete)
1911 A->getBlock(0,0)->fillComplete();
1912}
1913
1914
1915template <class SC, class LO, class GO, class NO>
1916void FE<SC,LO,GO,NO>::assemblyLaplaceDiffusion(int dim,
1917 std::string FEType,
1918 int degree,
1919 MatrixPtr_Type &A,
1920 vec2D_dbl_Type diffusionTensor,
1921 bool callFillComplete,
1922 int FELocExternal){
1923 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1924 UN FEloc;
1925 if (FELocExternal<0)
1926 FEloc = checkFE(dim,FEType);
1927 else
1928 FEloc = FELocExternal;
1929
1930 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1931
1932 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1933
1934 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1935
1936 vec3D_dbl_ptr_Type dPhi;
1937 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1938
1939 // inner( grad(u) , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
1940 // The diffusion tensor is constant and, thus, does not require a higher-order quadrature rule.
1941 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);//+1;
1942 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1943
1944 SC detB;
1945 SC absDetB;
1946 SmallMatrix<SC> B(dim);
1947 SmallMatrix<SC> Binv(dim);
1948 GO glob_i, glob_j;
1949 vec_dbl_Type v_i(dim);
1950 vec_dbl_Type v_j(dim);
1951
1952
1953 SmallMatrix<SC> diffusionT(dim);
1954 // Linear Diffusion Tensor
1955 if(diffusionTensor.size()==0 || diffusionTensor.size() < dim ){
1956 vec2D_dbl_Type diffusionTensor(3,vec_dbl_Type(3,0));
1957 for(int i=0; i< dim; i++){
1958 diffusionTensor[i][i]=1.;
1959 }
1960 }
1961
1962 for(int i=0; i< dim; i++){
1963 for(int j=0; j<dim; j++){
1964 diffusionT[i][j]=diffusionTensor[i][j];
1965 }
1966 }
1967 //Teuchos::ArrayRCP< SC > linearDiff = diffusionTensor->getDataNonConst( 0 );
1968 //std::cout << "Assembly Info " << "num Elements " << elements->numberElements() << " num Nodes " << pointsRep->size() << std::endl;
1969 for (UN T=0; T<elements->numberElements(); T++) {
1970
1971 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1972 detB = B.computeInverse(Binv);
1973 absDetB = std::fabs(detB);
1974
1975 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1976 applyBTinv( dPhi, dPhiTrans, Binv );
1977
1978 vec3D_dbl_Type dPhiTransDiff( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1979 applyDiff( dPhiTrans, dPhiTransDiff, diffusionT );
1980
1981 for (UN i=0; i < dPhiTrans[0].size(); i++) {
1982 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
1983 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
1984
1985 for (UN j=0; j < value.size(); j++) {
1986 for (UN w=0; w<dPhiTrans.size(); w++) {
1987 for (UN d=0; d<dim; d++){
1988 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTransDiff[w][j][d];
1989 }
1990 }
1991 value[j] *= absDetB;
1992 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
1993 if (setZeros_ && std::fabs(value[j]) < myeps_) {
1994 value[j] = 0.;
1995 }
1996 }
1997 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
1998
1999 A->insertGlobalValues( row, indices(), value() );
2000 }
2001
2002
2003 }
2004 if (callFillComplete)
2005 A->fillComplete();
2006
2007}
2008
2009template <class SC, class LO, class GO, class NO>
2010void FE<SC,LO,GO,NO>::applyDiff( vec3D_dbl_Type& dPhiIn,
2011 vec3D_dbl_Type& dPhiOut,
2012 SmallMatrix<SC>& diffT){
2013 UN dim = diffT.size();
2014 for (UN w=0; w<dPhiIn.size(); w++){
2015 for (UN i=0; i < dPhiIn[w].size(); i++) {
2016 for (UN d1=0; d1<dim; d1++) {
2017 for (UN d2=0; d2<dim; d2++) {
2018 dPhiOut[w][i][d1] += dPhiIn[w][i][d2]* diffT[d2][d1];
2019 }
2020 }
2021 }
2022 }
2023}
2024
2025// template <class SC, class LO, class GO, class NO>
2026// void FE<SC,LO,GO,NO>::assemblyAceGenTPM( MatrixPtr_Type &A00,
2027// MatrixPtr_Type &A01,
2028// MatrixPtr_Type &A10,
2029// MatrixPtr_Type &A11,
2030// MultiVectorPtr_Type &F0,
2031// MultiVectorPtr_Type &F1,
2032// MapPtr_Type &mapRepeated1,
2033// MapPtr_Type &mapRepeated2,
2034// ParameterListPtr_Type parameterList,
2035// MultiVectorPtr_Type u_repeatedNewton,
2036// MultiVectorPtr_Type p_repeatedNewton,
2037// MultiVectorPtr_Type u_repeatedTime,
2038// MultiVectorPtr_Type p_repeatedTime,
2039// bool update,
2040// bool updateHistory)
2041// {
2042
2043
2044// std::string tpmType = parameterList->sublist("Parameter").get("TPM Type","Biot");
2045
2046// int dim = domainVec_[0]->getDimension();
2047// int idata = 1; //= we should init this
2048// int ic = -1; int ng = -1;
2049
2050// //ed.hp:history previous (timestep); previous solution (velocity and acceleration)
2051// //ed.ht:? same length as hp
2052// ElementsPtr_Type elements1 = domainVec_[0]->getElementsC();
2053// ElementsPtr_Type elements2 = domainVec_[1]->getElementsC();
2054
2055// int sizeED = 24; /* 2D case for P2 elements:
2056// 12 velocities, 12 accelerations (2 dof per P2 node)
2057// */
2058// if (dim==3)
2059// sizeED = 60;/* 3D case for P2 elements:
2060// 30 velocities, 30 accelerations (3 dof per P2 node)
2061// */
2062// if (ed_.size()==0){
2063// for (UN T=0; T<elements1->numberElements(); T++)
2064// ed_.push_back( Teuchos::rcp(new DataElement( sizeED )) );
2065// }
2066
2067// std::vector<ElementSpec> es_vec( parameterList->sublist("Parameter").get("Number of materials",1) , ElementSpec());
2068// vec2D_dbl_Type dataVec( parameterList->sublist("Parameter").get("Number of materials",1), vec_dbl_Type(6,0.) );
2069
2070// for (int i=0; i<dataVec.size(); i++) {
2071// if (tpmType == "Biot") {
2072// if (dim==2) {
2073// dataVec[i][0] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2074// dataVec[i][1] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2075// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
2076// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
2077// dataVec[i][4] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
2078// dataVec[i][5] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2079// }
2080// else if (dim==3) {
2081// dataVec[i].resize(12);
2082// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),2.e5);
2083// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2084// dataVec[i][2] = 0.; //body force x
2085// dataVec[i][3] = 0.; //body force y
2086// dataVec[i][4] = parameterList->sublist("Parameter").get("body force z"+std::to_string(i+1),0.);; //body force z
2087// dataVec[i][5] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.67);
2088// dataVec[i][6] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),0.01);
2089// dataVec[i][7] = 2000.; //effective density solid
2090// dataVec[i][8] = 1000.; //effective density fluid?
2091// dataVec[i][9] = 9.81; // gravity
2092// dataVec[i][10] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2093// dataVec[i][11] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2094// }
2095// }
2096
2097
2098// else if (tpmType == "Biot-StVK") {
2099// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
2100// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2101// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
2102// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
2103// dataVec[i][4] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2104// dataVec[i][5] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2105// }
2106// }
2107
2108// for (int i=0; i<es_vec.size(); i++){
2109// if(tpmType == "Biot"){
2110// if (dim==2)
2111// this->SMTSetElSpecBiot(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2112// else if(dim==3)
2113// this->SMTSetElSpecBiot3D(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2114// }
2115// else if(tpmType == "Biot-StVK")
2116// this->SMTSetElSpecBiotStVK(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2117// }
2118// LO elementSizePhase = elements1->nodesPerElement();
2119// LO sizePhase = dim * elementSizePhase;
2120// LO sizePressure = elements2->nodesPerElement();
2121// GO sizePhaseGlobal = A00->getMap()->getMaxAllGlobalIndex()+1;
2122// int workingVectorSize;
2123// if(tpmType == "Biot"){
2124// if (dim==2)
2125// workingVectorSize = 5523;
2126// else if(dim==3)
2127// workingVectorSize = 1817;
2128// }
2129// else if(tpmType == "Biot-StVK")
2130// workingVectorSize = 5223;
2131
2132// double* v = new double [workingVectorSize];
2133
2134// // nd sind Nodalwerte, Anzahl an structs in nd sollte den Knoten entsprechen, bei P2-P1 in 2D also 9
2135// // In X stehen die Koordinaten, X[0] ist x-Koordinate, X[1] ist y-Koordinate, etc.
2136// // nd->X[0]
2137// // at ist die Loesung im letzten Newtonschritt.
2138// // nd[0]->at[0];
2139// // ap ist die Loesung im letzten Zeitschritt.
2140// // nd[0]->ap[0]
2141// // 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.
2142
2143// std::vector<double> rdata(RD_TimeIncrement+1, 0.);
2144
2145// rdata[RD_TimeIncrement] = parameterList->sublist("Timestepping Parameter").get("dt",0.01);
2146
2147// NodeSpec *ns=NULL;//dummy not need in SKR
2148
2149// NodeData** nd = new NodeData*[ elementSizePhase + sizePressure ];
2150
2151// for (int i=0; i<elementSizePhase + sizePressure; i++){
2152// nd[i] = new NodeData();
2153// }
2154
2155// int numNodes = elementSizePhase + sizePressure;
2156
2157// vec2D_dbl_Type xFull( numNodes, vec_dbl_Type(dim,0.) );
2158// vec2D_dbl_Type atFull( numNodes, vec_dbl_Type(dim,0.) );
2159// vec2D_dbl_Type apFull( numNodes, vec_dbl_Type(dim,0.) );
2160
2161// for (int i=0; i<elementSizePhase + sizePressure; i++) {
2162// nd[i]->X = &(xFull[i][0]);
2163// nd[i]->at = &(atFull[i][0]);
2164// nd[i]->ap = &(apFull[i][0]);
2165// }
2166
2167// GO offsetMap1 = dim * mapRepeated1->getMaxAllGlobalIndex()+1;
2168// vec2D_dbl_ptr_Type pointsRepU = domainVec_.at(0)->getPointsRepeated();
2169// vec2D_dbl_ptr_Type pointsRepP = domainVec_.at(1)->getPointsRepeated();
2170
2171// Teuchos::ArrayRCP< const SC > uArrayNewton = u_repeatedNewton->getData(0);
2172// Teuchos::ArrayRCP< const SC > pArrayNewton = p_repeatedNewton->getData(0);
2173// Teuchos::ArrayRCP< const SC > uArrayTime = u_repeatedTime->getData(0);
2174// Teuchos::ArrayRCP< const SC > pArrayTime = p_repeatedTime->getData(0);
2175
2176// double** mat = new double*[sizePhase+sizePressure];
2177// for (int i=0; i<sizePhase+sizePressure; i++){
2178// mat[i] = new double[sizePhase+sizePressure];
2179// }
2180
2181// Teuchos::ArrayRCP<SC> fValues0 = F0->getDataNonConst(0);
2182// Teuchos::ArrayRCP<SC> fValues1 = F1->getDataNonConst(0);
2183
2184// // Element loop
2185
2186// ElementData ed = ElementData();
2187// for (UN T=0; T<elements1->numberElements(); T++) {
2188
2189// std::vector<double> tmpHp = ed_[T]->getHp(); // Dies sind die alten Daten
2190// 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.
2191// ed.hp = &tmpHp[0];
2192// ed.ht = &tmpHt[0];
2193
2194// int materialFlag = elements1->getElement(T).getFlag();
2195// TEUCHOS_TEST_FOR_EXCEPTION( materialFlag>es_vec.size()-1, std::runtime_error, "There are not enought material parameters initialized." ) ;
2196// int counter=0;
2197// //Newtonloesung at und Zeitschrittloesung ap
2198// for (int j=0; j<elementSizePhase; j++) {
2199// for (int d=0; d<dim; d++) {
2200// LO index = dim * elements1->getElement(T).getNode(j)+d;//dim * elements1->at(T).at( j ) + d;
2201// atFull[j][d] = uArrayNewton[index];
2202// apFull[j][d] = uArrayTime[index];
2203// }
2204// }
2205// for (int j=0; j<sizePressure; j++) {
2206// LO index = elements2->getElement(T).getNode(j);//elements2->at(T).at( j );
2207// atFull[elementSizePhase+j][0] = pArrayNewton[index];
2208// apFull[elementSizePhase+j][0] = pArrayTime[index];
2209// }
2210
2211// //Nodes
2212// for (int j=0; j<elementSizePhase; j++ ) {
2213// LO index = elements1->getElement(T).getNode(j);
2214// for (int d=0; d<dim; d++) {
2215// xFull[j][d] = (*pointsRepU)[index][d];
2216// }
2217// }
2218// for (int j=0; j<sizePressure; j++ ) {
2219// LO index = elements2->getElement(T).getNode(j);
2220// for (int d=0; d<dim; d++) {
2221// xFull[elementSizePhase+j][d] = (*pointsRepP)[index][d];
2222// }
2223// }
2224// vec_dbl_Type p( sizePhase+sizePressure , 0. );
2225
2226// for (int i=0; i<sizePhase+sizePressure; i++){
2227// for (int j=0; j<sizePhase+sizePressure; j++)
2228// mat[i][j] = 0.;
2229// }
2230// // element assembly
2231// if(tpmType == "Biot"){
2232// if(dim==2)
2233// this->SKR_Biot( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2234// else if (dim==3)
2235// this->SKR_Biot3D( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2236// }
2237// else if(tpmType == "Biot-StVK")
2238// this->SKR_Biot_StVK( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2239
2240// if (updateHistory)
2241// ed_[T]->setHp( ed.ht );
2242
2243// if (update) {
2244
2245// // A00 & A01
2246// for (UN i=0; i < sizePhase; i++) {
2247// Teuchos::Array<SC> value00( sizePhase, 0. );
2248// Teuchos::Array<GO> indices00( sizePhase, 0 );
2249// for (UN j=0; j < value00.size(); j++) {
2250
2251// value00[j] = mat[i][j];
2252
2253// LO tmpJ = j/dim;
2254// LO index = elements1->getElement(T).getNode(tmpJ);
2255// if (j%dim==0)
2256// indices00[j] = dim * mapRepeated1->getGlobalElement( index );
2257// else if (j%dim==1)
2258// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
2259// else if (j%dim==2)
2260// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
2261// }
2262
2263// Teuchos::Array<SC> value01( sizePressure, 0. );
2264// Teuchos::Array<GO> indices01( sizePressure, 0 );
2265
2266// for (UN j=0; j < value01.size(); j++) {
2267// value01[j] = mat[i][sizePhase+j];
2268// LO index = elements2->getElement(T).getNode(j);
2269// indices01[j] = mapRepeated2->getGlobalElement( index );
2270// }
2271
2272// GO row;
2273// LO tmpI = i/dim;
2274// LO index = elements1->getElement(T).getNode(tmpI);
2275// if (i%dim==0)
2276// row = dim * mapRepeated1->getGlobalElement( index );
2277// else if (i%dim==1)
2278// row = dim * mapRepeated1->getGlobalElement( index ) + 1;
2279// else if (i%dim==2)
2280// row = dim * mapRepeated1->getGlobalElement( index ) + 2;
2281
2282// A00->insertGlobalValues( row, indices00(), value00() );
2283// A01->insertGlobalValues( row, indices01(), value01() );
2284
2285// if (i%dim==0)
2286// fValues0[ dim*index ] += p[ i ];
2287// else if (i%dim==1)
2288// fValues0[ dim*index+1 ] += p[ i ];
2289// else if (i%dim==2)
2290// fValues0[ dim*index+2 ] += p[ i ];
2291// }
2292// // A10 & A11
2293// for (UN i=0; i < sizePressure; i++) {
2294// Teuchos::Array<SC> value10( sizePhase , 0. );
2295// Teuchos::Array<GO> indices10( sizePhase , 0 );
2296// for (UN j=0; j < value10.size(); j++) {
2297// value10[j] = mat[sizePhase+i][j];
2298
2299// LO tmpJ = j/dim;
2300// LO index = elements1->getElement(T).getNode(tmpJ);
2301// if (j%dim==0)
2302// indices10[j] = dim * mapRepeated1->getGlobalElement( index );
2303// else if (j%dim==1)
2304// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
2305// else if (j%dim==2)
2306// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
2307// }
2308
2309// Teuchos::Array<SC> value11( sizePressure, 0. );
2310// Teuchos::Array<GO> indices11( sizePressure, 0 );
2311// for (UN j=0; j < value11.size(); j++) {
2312// value11[j] = mat[sizePhase+i][sizePhase+j];
2313
2314// LO index = elements2->getElement(T).getNode(j);
2315// indices11[j] = mapRepeated2->getGlobalElement( index );
2316// }
2317
2318
2319// LO index2 = elements2->getElement(T).getNode(i);
2320// GO row = mapRepeated2->getGlobalElement( index2 );
2321// A10->insertGlobalValues( row, indices10(), value10() );
2322// A11->insertGlobalValues( row, indices11(), value11() );
2323
2324// fValues1[ index2 ] += p[ sizePhase + i ];
2325// }
2326// }
2327// }
2328
2329// for (int i=0; i<sizePhase+sizePressure; i++)
2330// delete [] mat[i];
2331// delete [] mat;
2332
2333// delete [] v;
2334
2335// for (int i=0; i<elementSizePhase+sizePressure; i++)
2336// delete nd[i];
2337
2338// delete [] nd;
2339
2340
2341// A00->fillComplete( A00->getMap("row"), A00->getMap("row") );
2342// A01->fillComplete( A10->getMap("row"), A00->getMap("row") );
2343// A10->fillComplete( A00->getMap("row"), A10->getMap("row") );
2344// A11->fillComplete( A10->getMap("row"), A10->getMap("row") );
2345
2346// }
2347
2348template <class SC, class LO, class GO, class NO>
2349void FE<SC,LO,GO,NO>::assemblyMass(int dim,
2350 std::string FEType,
2351 std::string fieldType,
2352 MatrixPtr_Type &A,
2353 bool callFillComplete){
2354
2355 TEUCHOS_TEST_FOR_EXCEPTION( FEType == "P0", std::logic_error, "Not implemented for P0" );
2356 UN FEloc = checkFE(dim,FEType);
2357 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2358
2359 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2360
2361 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2362
2363 vec2D_dbl_ptr_Type phi;
2364 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2365
2366 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
2367 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2368
2369 Helper::getPhi( phi, weights, dim, FEType, deg );
2370
2371 SC detB;
2372 SC absDetB;
2373 SmallMatrix<SC> B(dim);
2374 GO glob_i, glob_j;
2375 vec_dbl_Type v_i(dim);
2376 vec_dbl_Type v_j(dim);
2377
2378 for (UN T=0; T<elements->numberElements(); T++) {
2379
2380 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2381 detB = B.computeDet( );
2382 absDetB = std::fabs(detB);
2383
2384 for (UN i=0; i < phi->at(0).size(); i++) {
2385 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2386 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2387 for (UN j=0; j < value.size(); j++) {
2388 for (UN w=0; w<phi->size(); w++) {
2389 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2390
2391 }
2392 value[j] *= absDetB;
2393 if (!fieldType.compare("Scalar")) {
2394 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2395 }
2396
2397 }
2398 if (!fieldType.compare("Scalar")) {
2399 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2400 A->insertGlobalValues( row, indices(), value() );
2401 }
2402 else if (!fieldType.compare("Vector")) {
2403 for (UN d=0; d<dim; d++) {
2404 for (int j=0; j<indices.size(); j++) {
2405 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2406 }
2407 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2408 A->insertGlobalValues( row, indices(), value() );
2409 }
2410 }
2411 else
2412 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
2413 }
2414
2415 }
2416
2417 if (callFillComplete)
2418 A->fillComplete();
2419}
2420
2421
2422// Ueberladung der Assemblierung der Massematrix fuer FSI, da
2423// checkFE sonst auch fuer das Strukturproblem FEloc = 1 liefert (= Fluid)
2424// und somit die welche domain und Map in der Assemblierung genutzt wird.
2425template <class SC, class LO, class GO, class NO>
2426void FE<SC,LO,GO,NO>::assemblyMass(int dim,
2427 std::string FEType,
2428 std::string fieldType,
2429 MatrixPtr_Type &A,
2430 int FEloc, // 0 = Fluid, 2 = Struktur
2431 bool callFillComplete){
2432
2433 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2434
2435 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2436
2437 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2438
2439 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2440
2441 vec2D_dbl_ptr_Type phi;
2442 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2443
2444 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
2445 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2446
2447 Helper::getPhi( phi, weights, dim, FEType, deg );
2448
2449 SC detB;
2450 SC absDetB;
2451 SmallMatrix<SC> B(dim);
2452 GO glob_i, glob_j;
2453 vec_dbl_Type v_i(dim);
2454 vec_dbl_Type v_j(dim);
2455
2456 for (UN T=0; T<elements->numberElements(); T++) {
2457
2458 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2459 detB = B.computeDet( );
2460 absDetB = std::fabs(detB);
2461
2462 for (UN i=0; i < phi->at(0).size(); i++) {
2463 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2464 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2465 for (UN j=0; j < value.size(); j++) {
2466 for (UN w=0; w<phi->size(); w++) {
2467 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2468 }
2469 value[j] *= absDetB;
2470 if (!fieldType.compare("Scalar")) {
2471 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2472 }
2473
2474 }
2475 if (!fieldType.compare("Scalar")) {
2476 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2477 A->insertGlobalValues( row, indices(), value() );
2478 }
2479 else if (!fieldType.compare("Vector")) {
2480 for (UN d=0; d<dim; d++) {
2481 for (int j=0; j<indices.size(); j++) {
2482 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2483 }
2484 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2485 A->insertGlobalValues( row, indices(), value() );
2486 }
2487 }
2488 else
2489 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
2490 }
2491
2492
2493 }
2494 if (callFillComplete)
2495 A->fillComplete();
2496}
2497
2498
2499template <class SC, class LO, class GO, class NO>
2500void FE<SC,LO,GO,NO>::assemblyLaplace(int dim,
2501 std::string FEType,
2502 int degree,
2503 MatrixPtr_Type &A,
2504 bool callFillComplete,
2505 int FELocExternal){
2506 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2507 UN FEloc;
2508 if (FELocExternal<0)
2509 FEloc = checkFE(dim,FEType);
2510 else
2511 FEloc = FELocExternal;
2512
2513 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2514
2515 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2516
2517 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2518
2519 vec3D_dbl_ptr_Type dPhi;
2520 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2521
2522 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2523 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2524
2525 SC detB;
2526 SC absDetB;
2527 SmallMatrix<SC> B(dim);
2528 SmallMatrix<SC> Binv(dim);
2529 GO glob_i, glob_j;
2530 vec_dbl_Type v_i(dim);
2531 vec_dbl_Type v_j(dim);
2532
2533 for (UN T=0; T<elements->numberElements(); T++) {
2534
2535 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2536 detB = B.computeInverse(Binv);
2537 absDetB = std::fabs(detB);
2538
2539 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2540 applyBTinv( dPhi, dPhiTrans, Binv );
2541 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2542 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2543 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2544 for (UN j=0; j < value.size(); j++) {
2545 for (UN w=0; w<dPhiTrans.size(); w++) {
2546 for (UN d=0; d<dim; d++){
2547 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
2548 }
2549 }
2550 value[j] *= absDetB;
2551 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2552 }
2553 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2554
2555 A->insertGlobalValues( row, indices(), value() );
2556 }
2557
2558
2559 }
2560 if (callFillComplete)
2561 A->fillComplete();
2562
2563}
2564
2565template <class SC, class LO, class GO, class NO>
2566void FE<SC,LO,GO,NO>::assemblyLaplaceVecField(int dim,
2567 std::string FEType,
2568 int degree,
2569 MatrixPtr_Type &A,
2570 bool callFillComplete){
2571
2572 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P1-disc" || FEType == "P0",std::logic_error, "Not implemented for P0 or P1-disc");
2573 UN FEloc = checkFE(dim,FEType);
2574
2575 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2576
2577 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2578
2579 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2580
2581 vec3D_dbl_ptr_Type dPhi;
2582 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2583
2584 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2585
2586 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2587
2588 SC detB;
2589 SC absDetB;
2590 SmallMatrix<SC> B(dim);
2591 SmallMatrix<SC> Binv(dim);
2592 GO glob_i, glob_j;
2593 vec_dbl_Type v_i(dim);
2594 vec_dbl_Type v_j(dim);
2595
2596
2597 for (UN T=0; T<elements->numberElements(); T++) {
2598
2599 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2600 detB = B.computeInverse(Binv);
2601 absDetB = std::fabs(detB);
2602
2603 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2604 applyBTinv( dPhi, dPhiTrans, Binv );
2605
2606 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2607 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2608 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2609 for (UN j=0; j < value.size(); j++) {
2610 for (UN w=0; w<dPhiTrans.size(); w++) {
2611 for (UN d=0; d<dim; d++)
2612 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
2613 }
2614 value[j] *= absDetB;
2615 if (setZeros_ && std::fabs(value[j]) < myeps_) {
2616 value[j] = 0.;
2617 }
2618 }
2619 for (UN d=0; d<dim; d++) {
2620 for (UN j=0; j < indices.size(); j++)
2621 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2622
2623 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2624 A->insertGlobalValues( row, indices(), value() );
2625 }
2626 }
2627 }
2628 if (callFillComplete)
2629 A->fillComplete();
2630}
2631//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.
2632template <class SC, class LO, class GO, class NO>
2633void FE<SC,LO,GO,NO>::assemblyLaplaceVecFieldV2(int dim,
2634 std::string FEType,
2635 int degree,
2636 MatrixPtr_Type &A,
2637 bool callFillComplete){
2638
2639 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2640 UN FEloc = checkFE(dim,FEType);
2641
2642 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2643
2644 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2645
2646 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2647
2648 vec3D_dbl_ptr_Type dPhi;
2649 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2650
2651 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2652
2653 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2654
2655 Teuchos::BLAS<int, SC> teuchosBLAS;
2656
2657 int nmbQuadPoints = dPhi->size();
2658 int nmbScalarDPhi = dPhi->at(0).size();
2659 int nmbAllDPhi = nmbScalarDPhi * dim;
2660 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2661 int sizeLocStiff = dim*dim;
2662 Teuchos::Array<SmallMatrix<double> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<double>(dim) );
2663 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2664
2665
2666 SC detB;
2667 SC absDetB;
2668 SmallMatrix<SC> B(dim);
2669 SmallMatrix<SC> Binv(dim);
2670 GO glob_i, glob_j;
2671 vec_dbl_Type v_i(dim);
2672 vec_dbl_Type v_j(dim);
2673
2674 for (UN T=0; T<elements->numberElements(); T++) {
2675
2676 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2677 detB = B.computeInverse(Binv);
2678 absDetB = std::fabs(detB);
2679
2680 Teuchos::Array<SmallMatrix<double> > allDPhiMatTrans( dPhiMat.size(), SmallMatrix<double>() );
2681
2682 for (int i=0; i<allDPhiMatTrans.size(); i++) {
2683 SmallMatrix<double> res = dPhiMat[i] * Binv;
2684 allDPhiMatTrans[i] = res;
2685 }
2686
2687 SmallMatrix<double> locStiffMat( nmbAllDPhi, 0. );
2688
2689 for (int p=0; p<nmbQuadPoints; p++){
2690
2691 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
2692
2693 int offset = p * nmbAllDPhi;
2694 int offsetInArray = 0;
2695 for (int i=0; i<nmbAllDPhi; i++) {
2696 fillMatrixArray( allDPhiMatTrans[ offset + i ], allDPhiBlas, "rows",offsetInArray );
2697 offsetInArray += sizeLocStiff;
2698 }
2699
2700 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
2701
2702 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);
2703
2704 for (int i=0; i<nmbAllDPhi; i++) {
2705 for (int j=0; j<nmbAllDPhi; j++) {
2706 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
2707 }
2708 }
2709
2710 delete [] allDPhiBlas;
2711 delete [] locStiffMatBlas;
2712
2713 }
2714
2715 for (UN i=0; i < nmbScalarDPhi; i++) {
2716 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
2717 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
2718 for (UN d=0; d<dim; d++) {
2719 for (UN j=0; j < nmbScalarDPhi; j++){
2720 value[ j * dim + d ] = absDetB * locStiffMat[dim * i + d][j];
2721 indices[ j * dim + d ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2722 }
2723 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2724 A->insertGlobalValues( row, indices(), value() );
2725 }
2726 }
2727 }
2728 if (callFillComplete)
2729 A->fillComplete();
2730}
2731
2747
2748template <class SC, class LO, class GO, class NO>
2750 int dim, std::string FEType, int degree, MultiVectorPtr_Type u_rep,
2751 BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec,
2752 ParameterListPtr_Type params, std::string assembleMode, bool callFillComplete,
2753 int FELocExternal) {
2754
2755 ElementsPtr_Type elements = this->domainVec_.at(0)->getElementsC();
2756
2757 // Only scalar laplace
2758 int dofs = 1;
2759
2760 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(0)->getPointsRepeated();
2761 MapConstPtr_Type map = this->domainVec_.at(0)->getMapRepeated();
2762
2763 vec_dbl_Type solution_u;
2764 vec_dbl_ptr_Type rhsVec;
2765
2766 int numNodes = 3;
2767 if (FEType == "P2") {
2768 numNodes = 6;
2769 }
2770 if (dim == 3) {
2771 numNodes = 4;
2772 if (FEType == "P2") {
2773 numNodes = 10;
2774 }
2775 }
2776
2777 // Tupel construction follows follwing pattern:
2778 // std::string: Physical Entity (i.e. Velocity) , std::string: Discretisation (i.e.
2779 // "P2"), int: Degrees of Freedom per Node, int: Number of Nodes per
2780 // element)
2781 tuple_disk_vec_ptr_Type problemDisk =
2782 Teuchos::rcp(new tuple_disk_vec_Type(0));
2783 tuple_ssii_Type temp("Solution", FEType, dofs, numNodes);
2784 problemDisk->push_back(temp);
2785
2786 // Construct an assembler for each element if not already done
2787 if (assemblyFEElements_.size() == 0) {
2788 initAssembleFEElements("NonLinearLaplace", problemDisk, elements, params, pointsRep, domainVec_.at(0)->getElementMap());
2789 } else if (assemblyFEElements_.size() != elements->numberElements()) {
2790 TEUCHOS_TEST_FOR_EXCEPTION(
2791 true, std::logic_error,
2792 "Number Elements not the same as number assembleFE elements.");
2793 }
2794
2795 MultiVectorPtr_Type resVec_u;
2796 BlockMultiVectorPtr_Type resVecRep;
2797
2798 if (assembleMode != "Rhs") {
2799 // add new or overwrite existing block (0,0) of system matrix
2800 // This is done in specific problem class for most other problems
2801 // Placing it here instead as more fitting
2802 auto A_block_zero_zero = Teuchos::rcp(
2803 new Matrix_Type(this->domainVec_.at(0)->getMapUnique(), this->domainVec_.at(0)->getApproxEntriesPerRow()));
2804
2805 A->addBlock(A_block_zero_zero, 0, 0);
2806 } else {
2807 // Or same for the residual vector
2808 resVec_u = Teuchos::rcp(new MultiVector_Type(map, 1));
2809 resVecRep = Teuchos::rcp(new BlockMultiVector_Type(1));
2810 resVecRep->addBlock(resVec_u, 0);
2811 }
2812 // Call assembly routines on each element
2813 for (UN T = 0; T < assemblyFEElements_.size(); T++) {
2814 vec_dbl_Type solution(0);
2815
2816 // Update solution on the element
2817 solution_u = getSolution(elements->getElement(T).getVectorNodeList(),
2818 u_rep, dofs);
2819 solution.insert(solution.end(), solution_u.begin(), solution_u.end());
2820 assemblyFEElements_[T]->updateSolution(solution);
2821
2822 if (assembleMode == "Jacobian") {
2823 SmallMatrixPtr_Type elementMatrix;
2824 assemblyFEElements_[T]->assembleJacobian();
2825 elementMatrix = assemblyFEElements_[T]->getJacobian();
2826 // Insert (additive) the local element Jacobian into the global
2827 // matrix
2828 assemblyFEElements_[T]
2829 ->advanceNewtonStep(); // n genereal non linear solver step
2830 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0,
2831 problemDisk);
2832 }
2833
2834 if (assembleMode == "Rhs") {
2835 assemblyFEElements_[T]->assembleRHS();
2836 rhsVec = assemblyFEElements_[T]->getRHS();
2837 // Name RHS comes from solving linear systems
2838 // For nonlinear systems RHS synonymous to residual
2839 // Insert (additive) the updated residual into the global residual
2840 // vector
2841 addFeBlockMv(resVecRep, rhsVec, elements->getElement(T), dofs);
2842 }
2843 }
2844 if (callFillComplete && assembleMode != "Rhs") {
2845 // Signal that editing A has finished. This causes the entries of A to
2846 // be redistributed across the MPI ranks
2847 A->getBlock(0, 0)->fillComplete(domainVec_.at(0)->getMapUnique(),
2848 domainVec_.at(0)->getMapUnique());
2849 }
2850 if (assembleMode == "Rhs") {
2851 // Export from overlapping residual to unique residual
2852 MultiVectorPtr_Type resVecUnique = Teuchos::rcp(
2853 new MultiVector_Type(domainVec_.at(0)->getMapUnique(), 1));
2854 resVecUnique->putScalar(0.);
2855 resVecUnique->exportFromVector(resVec_u, true, "Add");
2856 resVec->addBlock(resVecUnique, 0);
2857 }
2858}
2859
2860
2861template <class SC, class LO, class GO, class NO>
2862void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAndStressAceFEM(int dim,
2863 std::string FEType,
2864 MatrixPtr_Type &A,
2865 MultiVectorPtr_Type &f,
2866 MultiVectorPtr_Type u,
2867 ParameterListPtr_Type pList,
2868 double C,
2869 bool callFillComplete){
2870 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::runtime_error, "Not implemented for P0");
2871 UN FEloc = checkFE(dim,FEType);
2872
2873
2874 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2875 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2876
2877 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2878 vec3D_dbl_ptr_Type dPhi;
2879 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2880
2881 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2882
2883 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2884
2885 SC detB;
2886 SC absDetB;
2887 SmallMatrix<SC> B(dim);
2888 SmallMatrix<SC> Binv(dim);
2889
2890 Teuchos::BLAS<int,SC> teuchosBLAS;
2891
2892 int nmbQuadPoints = dPhi->size();
2893 int nmbScalarDPhi = dPhi->at(0).size();
2894 int nmbAllDPhi = nmbScalarDPhi * dim;
2895 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2896 int sizeLocStiff = dim*dim;
2897 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
2898
2899 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2900
2901 std::string material_model = pList->sublist("Parameter").get("Material model","Neo-Hooke");
2902
2903 double poissonRatio = pList->sublist("Parameter").get("Poisson Ratio",0.4);
2904 double mue = pList->sublist("Parameter").get("Mu",2.0e+6);
2905 double mue1 = pList->sublist("Parameter").get("Mu1",2.0e+6);
2906 double mue2 = pList->sublist("Parameter").get("Mu2",2.0e+6);
2907 // Berechne daraus nun E (Youngsches Modul) und die erste Lamé-Konstante \lambda
2908 double E = pList->sublist("Parameter").get("E",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2909 double E1 = pList->sublist("Parameter").get("E1",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2910 double E2 = pList->sublist("Parameter").get("E2",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2911
2912 if (material_model=="Saint Venant-Kirchhoff") {
2913 E = mue*2.*(1. + poissonRatio);
2914 E1 = mue1*2.*(1. + poissonRatio);
2915 E2 = mue2*2.*(1. + poissonRatio);
2916 }
2917
2918 // For StVK (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2919 double lambda = (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2920 double lambda1 = (poissonRatio*E1)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2921 double lambda2 = (poissonRatio*E2)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2922
2923 if (dim == 2){
2924 double* v;
2925 if(!material_model.compare("Saint Venant-Kirchhoff"))
2926 v = new double[154];
2927 else
2928 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Saint Venant-Kirchhoff in 2D.");
2929
2930 double** Pmat = new double*[2];
2931 for (int i=0; i<2; i++)
2932 Pmat[i] = new double[2];
2933
2934 double** F = new double*[2];
2935 for (int i=0; i<2; i++)
2936 F[i] = new double[2];
2937
2938 double**** Amat = new double***[2];
2939 for (int i=0; i<2; i++){
2940 Amat[i] = new double**[2];
2941 for (int j=0; j<2; j++) {
2942 Amat[i][j] = new double*[2];
2943 for (int k=0; k<2; k++)
2944 Amat[i][j][k] = new double[2];
2945 }
2946 }
2947
2948 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2949
2950 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
2951
2952 Teuchos::Array<int> indices(2);
2953 for (int T=0; T<elements->numberElements(); T++) {
2954
2955 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2956 detB = B.computeInverse(Binv);
2957 absDetB = std::fabs(detB);
2958
2959 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
2960
2961 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
2962 SmallMatrix<SC> res = dPhiMat[i] * Binv;
2963 all_dPhiMat_Binv[i] = res;
2964 }
2965
2966 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
2967 std::vector<SC> locStresses( nmbAllDPhi, 0. );
2968 int elementFlag = 0;
2969 for (int p=0; p<nmbQuadPoints; p++){
2970
2971 SmallMatrix<SC> Fmat( dim, 0. );
2972 SmallMatrix<SC> tmpForScaling( dim, 0. );
2973 Fmat[0][0] = 1.; Fmat[1][1] = 1.;
2974
2975 for (int i=0; i<nmbScalarDPhi; i++) {
2976 indices.at(0) = dim * elements->getElement(T).getNode(i);
2977 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
2978
2979 for (int j=0; j<dim; j++) {
2980 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
2981 SC v = uArray[indices.at(j)];
2982 tmpForScaling.scale( v );
2983 Fmat += tmpForScaling;
2984 }
2985 }
2986
2987 for (int i=0; i<Fmat.size(); i++) {
2988 for (int j=0; j<Fmat.size(); j++) {
2989 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
2990 }
2991 }
2992
2993 elementFlag = elements->getElement(T).getFlag();
2994 if (elementFlag == 1){
2995 lambda = lambda1;
2996 mue = mue1;
2997 E = E1;
2998 }
2999 else if (elementFlag == 2){
3000 lambda = lambda2;
3001 mue = mue2;
3002 E = E2;
3003 }
3004
3005 if ( !material_model.compare("Saint Venant-Kirchhoff") )
3006 stvk2d(v, &lambda, &mue, F, Pmat, Amat);
3007
3008 SmallMatrix<SC> Aloc(dim*dim);
3009 for (int i=0; i<2; i++) {
3010 for (int j=0; j<2; j++) {
3011 for (int k=0; k<2; k++) {
3012 for (int l=0; l<2; l++) {
3013 Aloc[ 2 * i + j ][ 2 * k + l ] = Amat[i][j][k][l];
3014 }
3015 }
3016 }
3017 }
3018
3019 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3020 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3021
3022 //jacobian
3023 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3024 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3025 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3026
3027 int offset = p * nmbAllDPhi;
3028 int offsetInArray = 0;
3029 for (int i=0; i<nmbAllDPhi; i++) {
3030 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3031 offsetInArray += sizeLocStiff;
3032 }
3033
3034 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3035
3036
3037 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3038
3039 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);
3040
3041 for (int i=0; i<nmbAllDPhi; i++) {
3042 for (int j=0; j<nmbAllDPhi; j++)
3043 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3044 }
3045
3046 delete [] resTmp;
3047 delete [] locStiffMatBlas;
3048
3049
3050 //stress
3051 double* fArray = new double[ sizeLocStiff ];
3052 for (int i=0; i<dim; i++) {
3053 for (int j=0; j<dim; j++) {
3054 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3055 }
3056 }
3057
3058 double* res = new double[ nmbAllDPhi ];
3059 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3060 for (int i=0; i<locStresses.size(); i++) {
3061 locStresses[i] += weights->at(p) * res[i];
3062 }
3063
3064 delete [] res;
3065 delete [] aceFEMFunc;
3066 delete [] allDPhiBlas;
3067 delete [] fArray;
3068 }
3069
3070 for (int i=0; i<nmbScalarDPhi; i++) {
3071 for (int d1=0; d1<dim; d1++) {
3072
3073 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
3074 SC v = absDetB * locStresses[ dim * i + d1 ];
3075 fValues[rowLO] += v;
3076
3077 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3078 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3079 LO counter = 0;
3080 for (UN j=0; j < nmbScalarDPhi; j++){
3081 for (UN d2=0; d2<dim; d2++) {
3082 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3083 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3084 counter++;
3085 }
3086 }
3087 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3088 A->insertGlobalValues( row, indices(), value() );
3089 }
3090 }
3091 }
3092
3093 delete [] v;
3094 for (int i=0; i<2; i++)
3095 delete [] Pmat[i];
3096 delete [] Pmat;
3097 for (int i=0; i<2; i++)
3098 delete [] F[i];
3099 delete [] F;
3100
3101 for (int i=0; i<2; i++){
3102 for (int j=0; j<2; j++) {
3103 for (int k=0; k<2; k++)
3104 delete [] Amat[i][j][k];
3105 delete [] Amat[i][j];
3106 }
3107 delete [] Amat[i];
3108 }
3109 delete [] Amat;
3110
3111
3112 }
3113 else if (dim == 3) {
3114 double* v;
3115 if (!material_model.compare("Neo-Hooke"))
3116 v = new double[466];
3117 else if(!material_model.compare("Mooney-Rivlin"))
3118 v = new double[476];
3119 else if(!material_model.compare("Saint Venant-Kirchhoff"))
3120 v = new double[279];
3121 else{
3122 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke, Mooney-Rivlin and Saint Venant-Kirchhoff.");
3123 }
3124
3125 double** Pmat = new double*[3];
3126 for (int i=0; i<3; i++)
3127 Pmat[i] = new double[3];
3128
3129 double** F = new double*[3];
3130 for (int i=0; i<3; i++)
3131 F[i] = new double[3];
3132
3133 double**** Amat = new double***[3];
3134 for (int i=0; i<3; i++){
3135 Amat[i] = new double**[3];
3136 for (int j=0; j<3; j++) {
3137 Amat[i][j] = new double*[3];
3138 for (int k=0; k<3; k++)
3139 Amat[i][j][k] = new double[3];
3140 }
3141 }
3142
3143 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3144
3145 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
3146
3147 Teuchos::Array<int> indices(3);
3148 for (int T=0; T<elements->numberElements(); T++) {
3149
3150 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
3151 detB = B.computeInverse(Binv);
3152 absDetB = std::fabs(detB);
3153
3154 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3155
3156 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3157 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3158 all_dPhiMat_Binv[i] = res;
3159 }
3160
3161 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
3162 std::vector<SC> locStresses( nmbAllDPhi, 0. );
3163 int elementFlag = 0;
3164 for (int p=0; p<nmbQuadPoints; p++){
3165
3166 SmallMatrix<SC> Fmat( dim, 0. );
3167 SmallMatrix<SC> tmpForScaling( dim, 0. );
3168 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3169
3170 for (int i=0; i<nmbScalarDPhi; i++) {
3171 indices.at(0) = dim * elements->getElement(T).getNode(i);
3172 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
3173 indices.at(2) = dim * elements->getElement(T).getNode(i) + 2;
3174
3175 for (int j=0; j<dim; j++) {
3176 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3177 SC v = uArray[indices.at(j)];
3178 tmpForScaling.scale( v );
3179 Fmat += tmpForScaling;
3180 }
3181 }
3182
3183 for (int i=0; i<Fmat.size(); i++) {
3184 for (int j=0; j<Fmat.size(); j++) {
3185 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3186 }
3187 }
3188
3189 elementFlag = elements->getElement(T).getFlag();
3190 if (elementFlag == 1){
3191 lambda = lambda1;
3192 mue = mue1;
3193 E = E1;
3194 }
3195 else if (elementFlag == 2){
3196 lambda = lambda2;
3197 mue = mue2;
3198 E = E2;
3199 }
3200
3201 if ( !material_model.compare("Neo-Hooke") )
3202 nh3d(v, &E, &poissonRatio, F, Pmat, Amat);
3203 else if ( !material_model.compare("Mooney-Rivlin") )
3204 mr3d(v, &E, &poissonRatio, &C, F, Pmat, Amat);
3205 else if ( !material_model.compare("Saint Venant-Kirchhoff") )
3206 stvk3d(v, &lambda, &mue, F, Pmat, Amat);
3207
3208 SmallMatrix<SC> Aloc(dim*dim);
3209 for (int i=0; i<3; i++) {
3210 for (int j=0; j<3; j++) {
3211 for (int k=0; k<3; k++) {
3212 for (int l=0; l<3; l++) {
3213 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
3214 }
3215 }
3216 }
3217 }
3218
3219 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3220 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3221
3222 //jacobian
3223 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3224 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3225 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3226
3227 int offset = p * nmbAllDPhi;
3228 int offsetInArray = 0;
3229 for (int i=0; i<nmbAllDPhi; i++) {
3230 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3231 offsetInArray += sizeLocStiff;
3232 }
3233
3234 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3235
3236
3237 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3238
3239 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);
3240
3241 for (int i=0; i<nmbAllDPhi; i++) {
3242 for (int j=0; j<nmbAllDPhi; j++)
3243 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3244 }
3245
3246 delete [] resTmp;
3247 delete [] locStiffMatBlas;
3248
3249
3250 //stress
3251 double* fArray = new double[ sizeLocStiff ];
3252 for (int i=0; i<dim; i++) {
3253 for (int j=0; j<dim; j++) {
3254 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3255 }
3256 }
3257
3258 double* res = new double[ nmbAllDPhi ];
3259 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3260 for (int i=0; i<locStresses.size(); i++) {
3261 locStresses[i] += weights->at(p) * res[i];
3262 }
3263
3264 delete [] res;
3265 delete [] aceFEMFunc;
3266 delete [] allDPhiBlas;
3267 delete [] fArray;
3268 }
3269
3270 for (int i=0; i<nmbScalarDPhi; i++) {
3271 for (int d1=0; d1<dim; d1++) {
3272
3273 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
3274 SC v = absDetB * locStresses[ dim * i + d1 ];
3275 fValues[rowLO] += v;
3276
3277 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3278 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3279 LO counter = 0;
3280 for (UN j=0; j < nmbScalarDPhi; j++){
3281 for (UN d2=0; d2<dim; d2++) {
3282 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3283 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3284
3285 counter++;
3286 }
3287 }
3288 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3289 A->insertGlobalValues( row, indices(), value() );
3290 }
3291 }
3292 }
3293
3294 delete [] v;
3295 for (int i=0; i<3; i++)
3296 delete [] Pmat[i];
3297 delete [] Pmat;
3298 for (int i=0; i<3; i++)
3299 delete [] F[i];
3300 delete [] F;
3301
3302 for (int i=0; i<3; i++){
3303 for (int j=0; j<3; j++) {
3304 for (int k=0; k<3; k++)
3305 delete [] Amat[i][j][k];
3306 delete [] Amat[i][j];
3307 }
3308 delete [] Amat[i];
3309 }
3310 delete [] Amat;
3311
3312 }
3313 if (callFillComplete)
3314 A->fillComplete();
3315
3316}
3317
3318
3319template <class SC, class LO, class GO, class NO>
3320void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAceFEM(int dim,
3321 std::string FEType,
3322 MatrixPtr_Type &A,
3323 MultiVectorPtr_Type u,
3324 std::string material_model,
3325 double E,
3326 double nu,
3327 double C,
3328 bool callFillComplete){
3329 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3330 UN FEloc = checkFE(dim,FEType);
3331
3332 vec2D_int_ptr_Type elements = domainVec_.at(FEloc)->getElements();
3333
3334 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3335
3336 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3337 vec3D_dbl_ptr_Type dPhi;
3338 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3339
3340 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
3341
3342 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3343
3344 SC detB;
3345 SC absDetB;
3346 SmallMatrix<SC> B(dim);
3347 SmallMatrix<SC> Binv(dim);
3348
3349 Teuchos::BLAS<int, SC> teuchosBLAS;
3350
3351 int nmbQuadPoints = dPhi->size();
3352 int nmbScalarDPhi = dPhi->at(0).size();
3353 int nmbAllDPhi = nmbScalarDPhi * dim;
3354 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
3355 int sizeLocStiff = dim*dim;
3356 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
3357
3358 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
3359
3360 if (dim == 2){
3361 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
3362 }
3363 else if (dim == 3) {
3364
3365 double* v;
3366 if (!material_model.compare("Neo-Hooke"))
3367 v = new double[466];
3368 else if(!material_model.compare("Mooney-Rivlin"))
3369 v = new double[476];
3370 else{
3371 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
3372 }
3373
3374
3375 double** Pmat = new double*[3];
3376 for (int i=0; i<3; i++)
3377 Pmat[i] = new double[3];
3378
3379 double** F = new double*[3];
3380 for (int i=0; i<3; i++)
3381 F[i] = new double[3];
3382
3383 double**** Amat = new double***[3];
3384 for (int i=0; i<3; i++){
3385 Amat[i] = new double**[3];
3386 for (int j=0; j<3; j++) {
3387 Amat[i][j] = new double*[3];
3388 for (int k=0; k<3; k++)
3389 Amat[i][j][k] = new double[3];
3390 }
3391 }
3392
3393 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3394
3395 Teuchos::Array<int> indices(3);
3396 for (int T=0; T<elements->size(); T++) {
3397
3398 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
3399 detB = B.computeInverse(Binv);
3400 absDetB = std::fabs(detB);
3401
3402 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3403
3404 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3405 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3406 all_dPhiMat_Binv[i] = res;
3407 }
3408
3409 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
3410
3411 for (int p=0; p<nmbQuadPoints; p++){
3412
3413 SmallMatrix<SC> Fmat( dim, 0. );
3414 SmallMatrix<SC> tmpForScaling( dim, 0. );
3415 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3416
3417 for (int i=0; i<nmbScalarDPhi; i++) {
3418 indices.at(0) = dim * elements->at(T).at(i);
3419 indices.at(1) = dim * elements->at(T).at(i) + 1;
3420 indices.at(2) = dim * elements->at(T).at(i) + 2;
3421
3422 for (int j=0; j<dim; j++) {
3423 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3424 SC v = uArray[indices.at(j)];
3425 tmpForScaling.scale( v );
3426 Fmat += tmpForScaling;
3427 }
3428 }
3429
3430 for (int i=0; i<Fmat.size(); i++) {
3431 for (int j=0; j<Fmat.size(); j++) {
3432 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3433 }
3434 }
3435 if ( !material_model.compare("Neo-Hooke") )
3436 nh3d(v, &E, &nu, F, Pmat, Amat);
3437 else if ( !material_model.compare("Mooney-Rivlin") )
3438 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
3439
3440 SmallMatrix<SC> Aloc(dim*dim);
3441 for (int i=0; i<3; i++) {
3442 for (int j=0; j<3; j++) {
3443 for (int k=0; k<3; k++) {
3444 for (int l=0; l<3; l++) {
3445 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
3446 }
3447 }
3448 }
3449 }
3450
3451 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3452 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3453 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3454 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3455 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3456
3457 int offset = p * nmbAllDPhi;
3458 int offsetInArray = 0;
3459 for (int i=0; i<nmbAllDPhi; i++) {
3460 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3461 offsetInArray += sizeLocStiff;
3462 }
3463
3464 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3465
3466 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3467
3468 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);
3469
3470 for (int i=0; i<nmbAllDPhi; i++) {
3471 for (int j=0; j<nmbAllDPhi; j++)
3472 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3473 }
3474
3475 delete [] aceFEMFunc;
3476 delete [] allDPhiBlas;
3477 delete [] resTmp;
3478 delete [] locStiffMatBlas;
3479
3480 }
3481 for (int i=0; i<nmbScalarDPhi; i++) {
3482 for (int d1=0; d1<dim; d1++) {
3483 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3484 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3485 LO counter = 0;
3486 for (UN j=0; j < nmbScalarDPhi; j++){
3487 for (UN d2=0; d2<dim; d2++) {
3488 indices[counter] = GO ( dim * map->getGlobalElement( elements->at(T).at(j) ) + d2 );
3489 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3490 counter++;
3491 }
3492 }
3493 GO row = GO ( dim * map->getGlobalElement( elements->at(T).at(i) ) + d1 );
3494 A->insertGlobalValues( row, indices(), value() );
3495 }
3496 }
3497 }
3498
3499 delete [] v;
3500 for (int i=0; i<3; i++)
3501 delete [] Pmat[i];
3502 delete [] Pmat;
3503 for (int i=0; i<3; i++)
3504 delete [] F[i];
3505 delete [] F;
3506
3507 for (int i=0; i<3; i++){
3508 for (int j=0; j<3; j++) {
3509 for (int k=0; k<3; k++)
3510 delete [] Amat[i][j][k];
3511 delete [] Amat[i][j];
3512 }
3513 delete [] Amat[i];
3514 }
3515 delete [] Amat;
3516
3517 }
3518 if (callFillComplete)
3519 A->fillComplete();
3520
3521}
3522
3523template <class SC, class LO, class GO, class NO>
3524void FE<SC,LO,GO,NO>::assemblyElasticityStressesAceFEM(int dim,
3525 std::string FEType,
3526 MultiVectorPtr_Type &f,
3527 MultiVectorPtr_Type u,
3528 std::string material_model,
3529 double E,
3530 double nu,
3531 double C,
3532 bool callFillComplete){
3533 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3534 UN FEloc = checkFE(dim,FEType);
3535
3536 vec2D_int_ptr_Type elements = domainVec_.at(FEloc)->getElements();
3537
3538 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3539
3540 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3541
3542 vec3D_dbl_ptr_Type dPhi;
3543 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3544
3545 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
3546
3547 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3548
3549 SC detB;
3550 SC absDetB;
3551 SmallMatrix<SC> B(dim);
3552 SmallMatrix<SC> Binv(dim);
3553
3554 Teuchos::BLAS<int, SC> teuchosBLAS;
3555
3556 int nmbQuadPoints = dPhi->size();
3557 int nmbScalarDPhi = dPhi->at(0).size();
3558 int nmbAllDPhi = nmbScalarDPhi * dim;
3559 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
3560 int sizeLocStiff = dim*dim;
3561 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
3562
3563 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
3564
3565 if (dim == 2){
3566 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
3567 }
3568 else if (dim == 3) {
3569
3570 double* v;
3571 if (!material_model.compare("Neo-Hooke"))
3572 v = new double[466];
3573 else if(!material_model.compare("Mooney-Rivlin"))
3574 v = new double[476];
3575 else{
3576 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
3577 }
3578
3579
3580 double** Pmat = new double*[3];
3581 for (int i=0; i<3; i++)
3582 Pmat[i] = new double[3];
3583
3584 double** F = new double*[3];
3585 for (int i=0; i<3; i++)
3586 F[i] = new double[3];
3587
3588 double**** Amat = new double***[3];
3589 for (int i=0; i<3; i++){
3590 Amat[i] = new double**[3];
3591 for (int j=0; j<3; j++) {
3592 Amat[i][j] = new double*[3];
3593 for (int k=0; k<3; k++)
3594 Amat[i][j][k] = new double[3];
3595 }
3596 }
3597
3598 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3599
3600 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
3601
3602 Teuchos::Array<int> indices(3);
3603 for (int T=0; T<elements->size(); T++) {
3604
3605 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
3606 detB = B.computeInverse(Binv);
3607 absDetB = std::fabs(detB);
3608
3609 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3610
3611 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3612 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3613 all_dPhiMat_Binv[i] = res;
3614 }
3615 std::vector<double> locStresses( nmbAllDPhi, 0. );
3616
3617 for (int p=0; p<nmbQuadPoints; p++){
3618
3619 SmallMatrix<SC> Fmat( dim, 0. );
3620 SmallMatrix<SC> tmpForScaling( dim, 0. );
3621 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3622
3623 for (int i=0; i<nmbScalarDPhi; i++) {
3624 indices.at(0) = dim * elements->at(T).at(i);
3625 indices.at(1) = dim * elements->at(T).at(i) + 1;
3626 indices.at(2) = dim * elements->at(T).at(i) + 2;
3627
3628 for (int j=0; j<dim; j++) {
3629 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3630 SC v = uArray[indices.at(j)];
3631 tmpForScaling.scale( v );
3632 Fmat += tmpForScaling;
3633 }
3634 }
3635
3636 for (int i=0; i<Fmat.size(); i++) {
3637 for (int j=0; j<Fmat.size(); j++) {
3638 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3639 }
3640 }
3641 if ( !material_model.compare("Neo-Hooke") )
3642 nh3d(v, &E, &nu, F, Pmat, Amat);
3643 else if ( !material_model.compare("Mooney-Rivlin") )
3644 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
3645
3646 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3647 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3648
3649 int offset = p * nmbAllDPhi;
3650 int offsetInArray = 0;
3651 for (int i=0; i<nmbAllDPhi; i++) {
3652 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3653 offsetInArray += sizeLocStiff;
3654 }
3655
3656
3657 double* fArray = new double[ sizeLocStiff ];
3658 for (int i=0; i<dim; i++) {
3659 for (int j=0; j<dim; j++) {
3660 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3661 }
3662 }
3663
3664 double* res = new double[ nmbAllDPhi ];
3665 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3666 for (int i=0; i<locStresses.size(); i++) {
3667 locStresses[i] += weights->at(p) * res[i];
3668 }
3669
3670 delete [] aceFEMFunc;
3671 delete [] allDPhiBlas;
3672 delete [] fArray;
3673 }
3674
3675
3676
3677 for (int i=0; i<nmbScalarDPhi; i++) {
3678 for (int d1=0; d1<dim; d1++) {
3679 LO row = dim * elements->at(T).at(i) + d1;
3680 SC v = absDetB * locStresses[ dim * i + d1 ];
3681 fValues[row] = v;
3682 }
3683 }
3684 }
3685
3686
3687 delete [] v;
3688 for (int i=0; i<3; i++)
3689 delete [] Pmat[i];
3690 delete [] Pmat;
3691 for (int i=0; i<3; i++)
3692 delete [] F[i];
3693 delete [] F;
3694
3695 for (int i=0; i<3; i++){
3696 for (int j=0; j<3; j++) {
3697 for (int k=0; k<3; k++)
3698 delete [] Amat[i][j][k];
3699 delete [] Amat[i][j];
3700 }
3701 delete [] Amat[i];
3702 }
3703 delete [] Amat;
3704
3705 }
3706}
3707
3709template <class SC, class LO, class GO, class NO>
3711 std::string FEType,
3712 MatrixPtr_Type &A,
3713 MultiVectorPtr_Type u,
3714 bool callFillComplete){
3715
3716 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3717 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3718
3719 UN FEloc = checkFE(dim,FEType);
3720
3721 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
3722
3723 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3724
3725 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3726
3727 vec3D_dbl_ptr_Type dPhi;
3728 vec2D_dbl_ptr_Type phi;
3729 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3730
3731 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
3732
3733 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1 ) +
3734 Helper::determineDegree( dim, FEType, Helper::Deriv0) +
3735 extraDeg;
3736
3737 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3738 Helper::getPhi(phi, weights, dim, FEType, deg);
3739 SC detB;
3740 SC absDetB;
3741 SmallMatrix<SC> B(dim);
3742 SmallMatrix<SC> Binv(dim);
3743 GO glob_i, glob_j;
3744 vec_dbl_Type v_i(dim);
3745 vec_dbl_Type v_j(dim);
3746
3747 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
3748 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3749
3750 for (UN T=0; T<elements->numberElements(); T++) {
3751
3752 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3753 detB = B.computeInverse(Binv);
3754 absDetB = std::fabs(detB);
3755
3756 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3757 applyBTinv( dPhi, dPhiTrans, Binv );
3758
3759 for (int w=0; w<phi->size(); w++){ //quads points
3760 for (int d=0; d<dim; d++) {
3761 uLoc[d][w] = 0.;
3762 for (int i=0; i < phi->at(0).size(); i++) {
3763 LO index = dim * elements->getElement(T).getNode(i) + d;
3764 uLoc[d][w] += uArray[index] * phi->at(w).at(i);
3765 }
3766 }
3767 }
3768
3769 for (UN i=0; i < phi->at(0).size(); i++) {
3770 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
3771 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
3772 for (UN j=0; j < value.size(); j++) {
3773 for (UN w=0; w<dPhiTrans.size(); w++) {
3774 for (UN d=0; d<dim; d++){
3775 value[j] += weights->at(w) * uLoc[d][w] * (*phi)[w][i] * dPhiTrans[w][j][d];
3776 }
3777
3778 }
3779 value[j] *= absDetB;
3780 if (setZeros_ && std::fabs(value[j]) < myeps_) {
3781 value[j] = 0.;
3782 }
3783
3784 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) );
3785 GO glob_j = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) );
3786 }
3787 for (UN d=0; d<dim; d++) {
3788 for (UN j=0; j < indices.size(); j++)
3789 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
3790
3791 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
3792 A->insertGlobalValues( row, indices(), value() );
3793 }
3794 }
3795 }
3796
3797
3798 if (callFillComplete)
3799 A->fillComplete();
3800}
3801
3803template <class SC, class LO, class GO, class NO>
3805 std::string FEType,
3806 MatrixPtr_Type &A,
3807 MultiVectorPtr_Type u,
3808 bool callFillComplete){
3809
3810 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3811 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3812 UN FEloc = checkFE(dim,FEType);
3813
3814 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
3815
3816 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3817
3818 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3819
3820 vec3D_dbl_ptr_Type dPhi;
3821 vec2D_dbl_ptr_Type phi;
3822 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3823
3824 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); //Elementwise assembly of u
3825
3826 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
3827
3828 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3829 Helper::getPhi(phi, weights, dim, FEType, deg);
3830
3831 SC detB;
3832 SC absDetB;
3833 SmallMatrix<SC> B(dim);
3834 SmallMatrix<SC> Binv(dim);
3835 GO glob_i, glob_j;
3836 vec_dbl_Type v_i(dim);
3837 vec_dbl_Type v_j(dim);
3838
3839 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3840
3841 for (UN T=0; T<elements->numberElements(); T++) {
3842
3843 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3844 detB = B.computeInverse(Binv);
3845 absDetB = std::fabs(detB);
3846
3847 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3848 applyBTinv( dPhi, dPhiTrans, Binv );
3849
3850 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)
3851
3852 for (int w=0; w<dPhiTrans.size(); w++){ //quads points
3853 for (int d1=0; d1<dim; d1++) {
3854 for (int i=0; i < dPhiTrans[0].size(); i++) {
3855 LO index = dim * elements->getElement(T).getNode(i) + d1;
3856 for (int d2=0; d2<dim; d2++)
3857 duLoc[w][d2][d1] += uArray[index] * dPhiTrans[w][i][d2];
3858 }
3859 }
3860 }
3861
3862 for (UN i=0; i < phi->at(0).size(); i++) {
3863 for (UN d1=0; d1<dim; d1++) {
3864 Teuchos::Array<SC> value( dim*phi->at(0).size(), 0. ); //These are value (W_ix,W_iy,W_iz)
3865 Teuchos::Array<GO> indices( dim*phi->at(0).size(), 0 );
3866 for (UN j=0; j < phi->at(0).size(); j++) {
3867 for (UN d2=0; d2<dim; d2++){
3868 for (UN w=0; w<phi->size(); w++) {
3869 value[ dim * j + d2 ] += weights->at(w) * duLoc[w][d2][d1] * (*phi)[w][i] * (*phi)[w][j];
3870 }
3871 value[ dim * j + d2 ] *= absDetB;
3872
3873 if (setZeros_ && std::fabs(value[ dim * j + d2 ]) < myeps_) {
3874 value[ dim * j + d2 ] = 0.;
3875 }
3876 }
3877 }
3878 for (UN j=0; j < phi->at(0).size(); j++){
3879 for (UN d2=0; d2<dim; d2++){
3880 indices[ dim * j + d2 ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3881 }
3882 }
3883
3884 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3885 A->insertGlobalValues( row, indices(), value() );
3886 }
3887 }
3888 }
3889 if (callFillComplete)
3890 A->fillComplete();
3891}
3892
3894template <class SC, class LO, class GO, class NO>
3896 std::string FEType,
3897 std::string FETypeV,
3898 MatrixPtr_Type &A,
3899 MultiVectorPtr_Type u,
3900 bool callFillComplete){
3901
3902 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3903 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3904
3905 UN FEloc = checkFE(dim,FEType);
3906
3907 ElementsPtr_Type elements = domainVec_.at(1)->getElementsC();
3908 ElementsPtr_Type elementsVel = domainVec_.at(0)->getElementsC();
3909
3910 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(1)->getPointsRepeated();
3911
3912 MapConstPtr_Type map = domainVec_.at(1)->getMapRepeated();
3913
3914 vec3D_dbl_ptr_Type dPhi;
3915 vec2D_dbl_ptr_Type phi,phiV;
3916 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3917
3918 UN degV = Helper::determineDegree( dim, FETypeV, Helper::Deriv0); //Elementwise assembly of u
3919 UN degP = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of p
3920 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) + degV + degP;
3921
3922 Helper::getDPhi(dPhi, weights, dim, FEType, deg); // Dphi for \nabla p
3923 Helper::getPhi(phi, weights, dim, FEType, deg); // phi for u
3924 Helper::getPhi(phiV, weights, dim, FETypeV, deg); // phi for p
3925
3926 SC detB;
3927 SC absDetB;
3928 SmallMatrix<SC> B(dim);
3929 SmallMatrix<SC> Binv(dim);
3930 GO glob_i, glob_j;
3931 vec_dbl_Type v_i(dim);
3932 vec_dbl_Type v_j(dim);
3933
3934 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
3935 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3936
3937 for (UN T=0; T<elements->numberElements(); T++) {
3938
3939 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3940 detB = B.computeInverse(Binv);
3941 absDetB = std::fabs(detB);
3942
3943 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3944 applyBTinv( dPhi, dPhiTrans, Binv );
3945
3946 for (int w=0; w<phiV->size(); w++){ //quads points
3947 for (int d=0; d<dim; d++) {
3948 uLoc[d][w] = 0.;
3949 for (int i=0; i < phiV->at(0).size(); i++) {
3950 LO index = dim * elementsVel->getElement(T).getNode(i) + d;
3951 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
3952 }
3953 }
3954 }
3955
3956 for (UN i=0; i < phi->at(0).size(); i++) {
3957 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
3958 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
3959 for (UN j=0; j < value.size(); j++) {
3960 for (UN w=0; w<dPhiTrans.size(); w++) {
3961 for (UN d=0; d<dim; d++){
3962 value[j] += weights->at(w) * uLoc[d][w]* dPhiTrans[w][j][d] * (*phi)[w][i] ;
3963 }
3964 }
3965 value[j] *= absDetB;
3966 indices[j] = GO ( map->getGlobalElement( elements->getElement(T).getNode(j) ) );
3967 }
3968
3969 GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
3970 A->insertGlobalValues( row, indices(), value() );
3971
3972 }
3973 }
3974
3975
3976 if (callFillComplete)
3977 A->fillComplete();
3978}
3979
3981template <class SC, class LO, class GO, class NO>
3983 std::string FEType1,
3984 std::string FEType2,
3985 int degree,
3986 MatrixPtr_Type &Bmat,
3987 MatrixPtr_Type &BTmat,
3988 MapConstPtr_Type map1,
3989 MapConstPtr_Type map2,
3990 bool callFillComplete) {
3991
3992
3993 UN FEloc1 = checkFE(dim,FEType1);
3994 UN FEloc2 = checkFE(dim,FEType2);
3995
3996 ElementsPtr_Type elements1 = domainVec_.at(FEloc1)->getElementsC();
3997 ElementsPtr_Type elements2 = domainVec_.at(FEloc2)->getElementsC();
3998
3999 vec2D_dbl_ptr_Type pointsRep1 = domainVec_.at(FEloc1)->getPointsRepeated();
4000
4001 MapConstPtr_Type mapping1 = domainVec_.at(FEloc1)->getMapRepeated();
4002 MapConstPtr_Type mapping2;
4003
4004 if (FEType2 == "P0")
4005 mapping2 = domainVec_.at(FEloc2)->getElementMap();
4006 else
4007 mapping2 = domainVec_.at(FEloc2)->getMapRepeated();
4008
4009 vec3D_dbl_ptr_Type dPhi;
4010 vec2D_dbl_ptr_Type phi;
4011 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4012
4013 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
4015
4016 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
4017
4018 // if (FEType2=="P1-disc-global")
4019 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
4020 if (FEType2=="P1-disc" && FEType1=="Q2" )
4021 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
4022 else
4023 Helper::getPhi(phi, weights, dim, FEType2, deg);
4024
4025 SC detB;
4026 SC absDetB;
4027 SmallMatrix<SC> B(dim);
4028 SmallMatrix<SC> Binv(dim);
4029 GO glob_i, glob_j;
4030 vec_dbl_Type v_i(dim);
4031 vec_dbl_Type v_j(dim);
4032
4033 for (UN T=0; T<elements1->numberElements(); T++) {
4034
4035 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
4036 detB = B.computeInverse(Binv);
4037 absDetB = std::fabs(detB);
4038
4039 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4040 applyBTinv( dPhi, dPhiTrans, Binv );
4041
4042 for (UN i=0; i < phi->at(0).size(); i++) {
4043 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( dPhiTrans[0].size(), 0. ) );
4044 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
4045
4046 for (UN j=0; j < valueVec[0].size(); j++) {
4047 for (UN w=0; w<dPhiTrans.size(); w++) {
4048 for (UN d=0; d<dim; d++)
4049 valueVec[d][j] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
4050 }
4051 for (UN d=0; d<dim; d++){
4052 valueVec[d][j] *= absDetB;
4053 if (setZeros_ && std::fabs(valueVec[d][j]) < myeps_) {
4054 valueVec[d][j] = 0.;
4055 }
4056 }
4057 }
4058 for (UN d=0; d<dim; d++) {
4059 for (UN j=0; j < indices.size(); j++)
4060 indices[j] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
4061
4062 GO row;
4063 if (FEType2=="P0")
4064 row = GO ( mapping2->getGlobalElement( T ) );
4065 else
4066 row = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
4067 Bmat->insertGlobalValues( row, indices(), valueVec[d]() );
4068 }
4069 }
4070
4071 // We compute value twice, maybe we should change this
4072 for (UN i=0; i < dPhiTrans[0].size(); i++) {
4073
4074 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( phi->at(0).size(), 0. ) );
4075 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
4076 for (UN j=0; j < valueVec[0].size(); j++) {
4077 for (UN w=0; w<dPhiTrans.size(); w++) {
4078 for (UN d=0; d<dim; d++)
4079 valueVec[d][j] += weights->at(w) * phi->at(w)[j] * dPhiTrans[w][i][d];
4080 }
4081 for (UN d=0; d<dim; d++){
4082 valueVec[d][j] *= absDetB;
4083 if (setZeros_ && std::fabs(valueVec[d][j]) < myeps_) {
4084 valueVec[d][j] = 0.;
4085 }
4086 }
4087 }
4088
4089 for (UN j=0; j < indices.size(); j++){
4090 if (FEType2=="P0")
4091 indices[j] = GO ( mapping2->getGlobalElement( T ) );
4092 else
4093 indices[j] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(j) ) );
4094 }
4095 for (UN d=0; d<dim; d++) {
4096 GO row = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(i) ) + d );
4097 BTmat->insertGlobalValues( row, indices(), valueVec[d]() );
4098 }
4099
4100 }
4101
4102 }
4103 if (callFillComplete) {
4104 Bmat->fillComplete( map1, map2 );
4105 BTmat->fillComplete( map2, map1 );
4106 }
4107
4108}
4109
4111template <class SC, class LO, class GO, class NO>
4113 std::string FEType1,
4114 std::string FEType2,
4115 int degree,
4116 MatrixPtr_Type &Bmat,
4117 MatrixPtr_Type &BTmat,
4118 MapConstPtr_Type map1,
4119 MapConstPtr_Type map2,
4120 bool callFillComplete) {
4121
4122
4123 UN FEloc1 = checkFE(dim,FEType1);
4124 UN FEloc2 = checkFE(dim,FEType2);
4125
4126 ElementsPtr_Type elements1 = domainVec_.at(FEloc1)->getElementsC();
4127 ElementsPtr_Type elements2 = domainVec_.at(FEloc2)->getElementsC();
4128
4129 vec2D_dbl_ptr_Type pointsRep1 = domainVec_.at(FEloc1)->getPointsRepeated();
4130
4131 MapConstPtr_Type mapping1 = domainVec_.at(FEloc1)->getMapRepeated();
4132 MapConstPtr_Type mapping2;
4133
4134 if (FEType2 == "P0")
4135 mapping2 = domainVec_.at(FEloc2)->getElementMap();
4136 else
4137 mapping2 = domainVec_.at(FEloc2)->getMapRepeated();
4138
4139 vec3D_dbl_ptr_Type dPhi;
4140 vec2D_dbl_ptr_Type phi;
4141 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4142
4143 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
4145
4146 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
4147
4148 // if (FEType2=="P1-disc-global")
4149 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
4150 if (FEType2=="P1-disc" && FEType1=="Q2" )
4151 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
4152 else
4153 Helper::getPhi(phi, weights, dim, FEType2, deg);
4154
4155 SC detB;
4156 SC absDetB;
4157 SmallMatrix<SC> B(dim);
4158 SmallMatrix<SC> Binv(dim);
4159 GO glob_i, glob_j;
4160 vec_dbl_Type v_i(dim);
4161 vec_dbl_Type v_j(dim);
4162
4163 Teuchos::Array<GO> colIndex( 1, 0 );
4164 Teuchos::Array<GO> rowIndex( 1, 0 );
4165 Teuchos::Array<SC> value(1, 0.);
4166
4167 for (UN T=0; T<elements1->numberElements(); T++) {
4168
4169 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
4170 detB = B.computeInverse(Binv);
4171 absDetB = std::fabs(detB);
4172
4173 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4174 applyBTinv( dPhi, dPhiTrans, Binv );
4175
4176 for (UN i=0; i < phi->at(0).size(); i++) {
4177 if (FEType2=="P0")
4178 rowIndex[0] = GO ( mapping2->getGlobalElement( T ) );
4179 else
4180 rowIndex[0] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
4181
4182 for (UN j=0; j < dPhiTrans[0].size(); j++) {
4183 for (UN d=0; d<dim; d++){
4184 value[0] = 0.;
4185 for (UN w=0; w<dPhiTrans.size(); w++)
4186 value[0] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
4187 value[0] *= absDetB;
4188 colIndex[0] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
4189 Bmat->insertGlobalValues( rowIndex[0], colIndex(), value() );
4190 BTmat->insertGlobalValues( colIndex[0], rowIndex(), value() );
4191
4192 }
4193 }
4194 }
4195
4196 }
4197 if (callFillComplete) {
4198 Bmat->fillComplete( map1, map2 );
4199 BTmat->fillComplete( map2, map1 );
4200 }
4201
4202}
4203
4205template <class SC, class LO, class GO, class NO>
4207 std::string FEType,
4208 MatrixPtr_Type &A,
4209 bool callFillComplete){
4210
4211 TEUCHOS_TEST_FOR_EXCEPTION(FEType != "P1" && FEType != "Q1",std::logic_error, "Only implemented for P1, Q1.");
4212 UN FEloc = checkFE(dim,FEType);
4213
4214 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4215
4216 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4217
4218 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4219
4220 vec2D_dbl_ptr_Type phi;
4221
4222 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4223
4224 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
4225
4226 Helper::getPhi( phi, weights, dim, FEType, deg );
4227
4228 SC detB;
4229 SC absDetB;
4230 SmallMatrix<SC> B(dim);
4231 GO glob_i, glob_j;
4232 vec_dbl_Type v_i(dim);
4233 vec_dbl_Type v_j(dim);
4234
4235 SC refElementSize;
4236 SC refElementScale;
4237 if(FEType=="P1"){
4238 if (dim==2) {
4239 refElementSize = 0.5;
4240 refElementScale = 1./9.;
4241 }
4242 else if(dim==3){
4243 refElementSize = 1./6.;
4244 refElementScale = 1./16.;
4245 }
4246 }
4247 else if(FEType=="Q1"){
4248 if(dim==3){
4249 refElementScale=1./64;
4250 refElementSize=8.;
4251 }
4252 else{
4253 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Q1 Only implemented for 3D.");
4254 }
4255 }
4256
4257 for (UN T=0; T<elements->numberElements(); T++) {
4258
4259 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4260 detB = B.computeDet( );
4261 absDetB = std::fabs(detB);
4262
4263 for (UN i=0; i < phi->at(0).size(); i++) {
4264 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
4265 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
4266 for (UN j=0; j < value.size(); j++) {
4267 for (UN w=0; w<phi->size(); w++) {
4268 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
4269 }
4270 value[j] *= absDetB;
4271 value[j] -= refElementSize * absDetB * refElementScale;
4272
4273 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
4274 }
4275
4276 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
4277 A->insertGlobalValues( row, indices(), value() );
4278 }
4279
4280 }
4281
4282 if (callFillComplete)
4283 A->fillComplete();
4284}
4285
4286
4287
4288template <class SC, class LO, class GO, class NO>
4290 std::string FEType,
4291 MatrixPtr_Type &A,
4292 CoeffFuncDbl_Type func,
4293 double* parameters,
4294 bool callFillComplete)
4295{
4296 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4297 int FEloc = this->checkFE(dim,FEType);
4298
4299 DomainConstPtr_Type domain = domainVec_.at(FEloc);
4300 ElementsPtr_Type elements = domain->getElementsC();
4301 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
4302 MapConstPtr_Type map = domain->getMapRepeated();
4303
4304 vec3D_dbl_ptr_Type dPhi;
4305 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4306 vec2D_dbl_ptr_Type quadPts;
4307
4308 // double val, value1_j, value2_j , value1_i, value2_i;
4309
4310 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4311
4312 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4313 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi, FEType);
4314
4315 // SC = double, GO = long, UN = int
4316 SC detB;
4317 SC absDetB;
4318 SmallMatrix<SC> B(dim);
4319 SmallMatrix<SC> Binv(dim);
4320 GO glob_i, glob_j;
4321
4322
4323 vec_dbl_ptr_Type dist = domain->getDistancesToInterface();
4324 if (dim == 2)
4325 {
4326 double val, value1_j, value2_j , value1_i, value2_i;
4327 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
4328
4329 double distance1, distance2, distance3;
4330 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
4331 for (int T = 0; T < elements->numberElements(); T++)
4332 {
4333 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4334 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4335 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4336
4337 distance1 = dist->at(elements->getElement(T).getNode(0));
4338 distance2 = dist->at(elements->getElement(T).getNode(1));
4339 distance3 = dist->at(elements->getElement(T).getNode(2));
4340
4341 distance_mean.at(0) = (distance1 + distance2 + distance3)/3.0; // Mittelwert
4342 double funcvalue = func(&distance_mean.at(0),parameters);
4343
4344 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4345 detB = B.computeInverse(Binv);
4346 absDetB = std::fabs(detB);
4347
4348 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4349 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4350 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4351
4352 for (int i = 0; i < dPhi->at(0).size(); i++)
4353 {
4354 Teuchos::Array<SC> value( 1, 0. );
4355 Teuchos::Array<GO> indices( 1, 0 );
4356
4357 for (int j = 0; j < dPhi->at(0).size(); j++)
4358 {
4359 val = 0.0;
4360 for (int k = 0; k < dPhi->size(); k++)
4361 {
4362
4363 value1_j = dPhiTrans.at(k).at(j).at(0);
4364 value2_j = dPhiTrans.at(k).at(j).at(1);
4365
4366 value1_i = dPhiTrans.at(k).at(i).at(0);
4367 value2_i = dPhiTrans.at(k).at(i).at(1);
4368
4369 val = val + funcvalue * weightsDPhi->at(k) * ( value1_j*value1_i + value2_j*value2_i );
4370 }
4371 val = absDetB * val;
4372 value[0] = val;
4373
4374 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4375 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4376 indices[0] = glob_j;
4377
4378
4379 A->insertGlobalValues(glob_i, indices(), value());
4380 glob_j++;
4381 indices[0] = glob_j;
4382 A->insertGlobalValues(glob_i+1, indices(), value());
4383 }
4384 }
4385 }
4386 if (callFillComplete)
4387 {
4388 A->fillComplete();
4389 }
4390 }
4391 else if(dim == 3)
4392 {
4393 double val, value1_j, value2_j ,value3_j, value1_i, value2_i ,value3_i;
4394
4395 long long glob_i, glob_j;
4396 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4397
4398 double distance1, distance2, distance3, distance4;
4399 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
4400 for (int T = 0; T < elements->numberElements(); T++)
4401 {
4402 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4403 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4404 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4405 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4406
4407 distance1 = dist->at(elements->getElement(T).getNode(0));
4408 distance2 = dist->at(elements->getElement(T).getNode(1));
4409 distance3 = dist->at(elements->getElement(T).getNode(2));
4410 distance4 = dist->at(elements->getElement(T).getNode(3));
4411
4412 distance_mean.at(0) = (distance1 + distance2 + distance3 + distance4)/4.0; //Mittelwert
4413 double funcvalue = func(&distance_mean.at(0),parameters);
4414
4415 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4416 detB = B.computeInverse(Binv);
4417 absDetB = std::fabs(detB);
4418
4419 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4420 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4421 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4422
4423 for (int i = 0; i < dPhi->at(0).size(); i++)
4424 {
4425 Teuchos::Array<SC> value( 1, 0. );
4426 Teuchos::Array<GO> indices( 1, 0 );
4427
4428 for (int j = 0; j < dPhi->at(0).size(); j++)
4429 {
4430 val = 0.0;
4431 for (int k = 0; k < dPhi->size(); k++)
4432 {
4433 value1_j = dPhiTrans.at(k).at(j).at(0);
4434 value2_j = dPhiTrans.at(k).at(j).at(1);
4435 value3_j = dPhiTrans.at(k).at(j).at(2);
4436
4437 value1_i = dPhiTrans.at(k).at(i).at(0);
4438 value2_i = dPhiTrans.at(k).at(i).at(1);
4439 value3_i = dPhiTrans.at(k).at(i).at(2);
4440
4441 val = val + funcvalue * weightsDPhi->at(k) * (value1_j*value1_i + value2_j*value2_i + value3_j*value3_i);
4442 }
4443 val = absDetB * val;
4444 value[0] = val;
4445
4446 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4447 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4448 indices[0] = glob_j;
4449 A->insertGlobalValues(glob_i, indices(), value());
4450 glob_j++;
4451 indices[0] = glob_j;
4452 A->insertGlobalValues(glob_i+1, indices(), value());
4453 glob_j++;
4454 indices[0] = glob_j;
4455 A->insertGlobalValues(glob_i+2, indices(), value());
4456
4457 }
4458 }
4459 }
4460 if (callFillComplete)
4461 {
4462 A->fillComplete();
4463 }
4464 }
4465
4466}
4467
4468
4469
4470template <class SC, class LO, class GO, class NO>
4472 std::string FEType,
4473 MatrixPtr_Type &A,
4474 CoeffFunc_Type func,
4475 int* parameters,
4476 bool callFillComplete)
4477{
4478 // 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.
4479 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4480 int FEloc = this->checkFE(dim,FEType);
4481
4482 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4483 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4484 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4485
4486 vec3D_dbl_ptr_Type dPhi;
4487 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4488 vec2D_dbl_ptr_Type quadPts;
4489
4490 // double value, value1_j, value2_j , value1_i, value2_i;
4491
4492 // inner( grad(u) + grad(u)^T , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
4493 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4494 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4495 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4496
4497 // SC = double, GO = long, UN = int
4498 SC detB;
4499 SC absDetB;
4500 SmallMatrix<SC> B(dim);
4501 SmallMatrix<SC> Binv(dim);
4502 GO glob_i, glob_j;
4503
4504 if (dim == 2)
4505 {
4506 double v11, v12, v21, v22, value1_j, value2_j , value1_i, value2_i;
4507 double e_11_j_1,e_12_j_1,e_21_j_1,e_22_j_1;
4508 double e_11_j_2,e_12_j_2,e_21_j_2,e_22_j_2;
4509 double e_11_i_1,e_12_i_1,e_21_i_1,e_22_i_1;
4510 double e_11_i_2,e_12_i_2,e_21_i_2,e_22_i_2;
4511
4512 SmallMatrix<double> tmpRes1(dim);
4513 SmallMatrix<double> tmpRes2(dim);
4514 SmallMatrix<double> e1i(dim);
4515 SmallMatrix<double> e2i(dim);
4516 SmallMatrix<double> e1j(dim);
4517 SmallMatrix<double> e2j(dim);
4518
4519 long long glob_i, glob_j;
4520 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
4521
4522 vec_dbl_Type xy(2);
4523 for (int T = 0; T < elements->numberElements(); T++)
4524 {
4525 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4526 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4527 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4528
4529 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
4530 detB = B.computeInverse(Binv);
4531 absDetB = std::fabs(detB);
4532
4533 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1)
4534 // Also \hat{grad_phi}.
4535 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4536 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4537
4538 for (int i = 0; i < dPhi->at(0).size(); i++)
4539 {
4540 Teuchos::Array<SC> value11( 1, 0. );
4541 Teuchos::Array<SC> value12( 1, 0. );
4542 Teuchos::Array<SC> value21( 1, 0. );
4543 Teuchos::Array<SC> value22( 1, 0. );
4544 Teuchos::Array<GO> indices( 1, 0 );
4545
4546 for (int j=0; j < dPhi->at(0).size(); j++)
4547 {
4548 v11 = 0.0;v12 = 0.0;v21 = 0.0;v22 = 0.0;
4549 for (int k = 0; k < dPhi->size(); k++)
4550 {
4551 // Mappen der Gausspunkte (definiert auf T_ref) auf T (bzw. \Omega)
4552 // xy = F(quadPts) = B*quadPts + b, mit b = p1 (affin lineare Transformation)
4553 xy[0]=0.; xy[1]=0.;
4554 for (int r=0; r<2; r++) {
4555 xy[0] += B[0][r]*quadPts->at(k).at(r);
4556 xy[1] += B[1][r]*quadPts->at(k).at(r);
4557 }
4558 xy[0] += p1[0];
4559 xy[1] += p1[1];
4560
4561 value1_j = dPhiTrans.at(k).at(j).at(0);
4562 value2_j = dPhiTrans.at(k).at(j).at(1);
4563
4564 value1_i = dPhiTrans.at(k).at(i).at(0);
4565 value2_i = dPhiTrans.at(k).at(i).at(1);
4566
4567 tmpRes1[0][0] = value1_j;
4568 tmpRes1[0][1] = value2_j;
4569 tmpRes1[1][0] = 0.;
4570 tmpRes1[1][1] = 0.;
4571
4572 tmpRes2[0][0] = value1_j;
4573 tmpRes2[0][1] = 0.;
4574 tmpRes2[1][0] = value2_j;
4575 tmpRes2[1][1] = 0.;
4576
4577 tmpRes1.add(tmpRes2,e1j/*result*/);
4578
4579 e1i[0][0] = value1_i;
4580 e1i[0][1] = value2_i;
4581
4582
4583 tmpRes1[0][0] = 0.;
4584 tmpRes1[0][1] = 0.;
4585 tmpRes1[1][0] = value1_j;
4586 tmpRes1[1][1] = value2_j;
4587
4588 tmpRes2[0][0] = 0.;
4589 tmpRes2[0][1] = value1_j;
4590 tmpRes2[1][0] = 0.;
4591 tmpRes2[1][1] = value2_j;
4592
4593 tmpRes1.add(tmpRes2,e2j/*result*/);
4594
4595 e2i[1][0] = value1_i;
4596 e2i[1][1] = value2_i;
4597
4598 double funcvalue = func(&xy.at(0),parameters);
4599 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
4600 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
4601 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
4602 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
4603
4604 }
4605
4606 v11 = absDetB * v11;
4607 v12 = absDetB * v12;
4608 v21 = absDetB * v21;
4609 v22 = absDetB * v22;
4610
4611 value11[0] = v11;
4612 value12[0] = v12;
4613 value21[0] = v21;
4614 value22[0] = v22;
4615
4616 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4617 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4618 indices[0] = glob_j;
4619
4620 A->insertGlobalValues(glob_i, indices(), value11());
4621 A->insertGlobalValues(glob_i+1, indices(), value21());
4622 glob_j++;
4623 indices[0] = glob_j;
4624 A->insertGlobalValues(glob_i, indices(), value12());
4625 A->insertGlobalValues(glob_i+1, indices(), value22());
4626 }
4627 }
4628 }
4629 if (callFillComplete)
4630 {
4631 A->fillComplete();
4632 }
4633 }
4634 else if(dim == 3)
4635 {
4636 double v11, v12, v13, v21, v22, v23, v31, v32, v33, value1_j, value2_j, value3_j , value1_i, value2_i, value3_i;
4637
4638 SmallMatrix<double> e1i(dim);
4639 SmallMatrix<double> e2i(dim);
4640 SmallMatrix<double> e3i(dim);
4641 SmallMatrix<double> e1j(dim);
4642 SmallMatrix<double> e2j(dim);
4643 SmallMatrix<double> e3j(dim);
4644
4645 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4646 vec_dbl_Type xyz(3);
4647
4648 for (int T = 0; T < elements->numberElements(); T++)
4649 {
4650 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4651 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4652 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4653 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4654
4655 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4656 detB = B.computeInverse(Binv);
4657 absDetB = std::fabs(detB);
4658
4659 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4660 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4661 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4662
4663 for (int i = 0; i < dPhi->at(0).size(); i++)
4664 {
4665 Teuchos::Array<SC> value11( 1, 0. );
4666 Teuchos::Array<SC> value12( 1, 0. );
4667 Teuchos::Array<SC> value13( 1, 0. );
4668 Teuchos::Array<SC> value21( 1, 0. );
4669 Teuchos::Array<SC> value22( 1, 0. );
4670 Teuchos::Array<SC> value23( 1, 0. );
4671 Teuchos::Array<SC> value31( 1, 0. );
4672 Teuchos::Array<SC> value32( 1, 0. );
4673 Teuchos::Array<SC> value33( 1, 0. );
4674 Teuchos::Array<GO> indices( 1, 0 );
4675
4676 for (int j = 0; j < dPhi->at(0).size(); j++)
4677 {
4678 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;
4679 for (int k = 0; k < dPhi->size(); k++)
4680 {
4681
4682 xyz[0]=0.; xyz[1]=0.; xyz[2]=0.;
4683 for (int r = 0; r < 3; r++)
4684 {
4685 xyz[0] += B[0][r]*quadPts->at(k).at(r);
4686 xyz[1] += B[1][r]*quadPts->at(k).at(r);
4687 xyz[2] += B[2][r]*quadPts->at(k).at(r);
4688 }
4689 xyz[0] += p1[0];
4690 xyz[1] += p1[1];
4691 xyz[2] += p1[2];
4692
4693
4694
4695 value1_j = dPhiTrans.at(k).at(j).at(0);
4696 value2_j = dPhiTrans.at(k).at(j).at(1);
4697 value3_j = dPhiTrans.at(k).at(j).at(2);
4698
4699
4700 value1_i = dPhiTrans.at(k).at(i).at(0);
4701 value2_i = dPhiTrans.at(k).at(i).at(1);
4702 value3_i = dPhiTrans.at(k).at(i).at(2);
4703
4704
4705 e1j[0][0] = 2.*value1_j;
4706 e1j[0][1] = value2_j;
4707 e1j[0][2] = value3_j;
4708 e1j[1][0] = value2_j;
4709 e1j[2][0] = value3_j;
4710
4711 e1i[0][0] = value1_i;
4712 e1i[0][1] = value2_i;
4713 e1i[0][2] = value3_i;
4714
4715
4716 e2j[1][0] = value1_j;
4717 e2j[1][1] = 2.*value2_j;
4718 e2j[1][2] = value3_j;
4719 e2j[0][1] = value1_j;
4720 e2j[2][1] = value3_j;
4721
4722 e2i[1][0] = value1_i;
4723 e2i[1][1] = value2_i;
4724 e2i[1][2] = value3_i;
4725
4726
4727 e3j[2][0] = value1_j;
4728 e3j[2][1] = value2_j;
4729 e3j[2][2] = 2.*value3_j;
4730 e3j[0][2] = value1_j;
4731 e3j[1][2] = value2_j;
4732
4733 e3i[2][0] = value1_i;
4734 e3i[2][1] = value2_i;
4735 e3i[2][2] = value3_i;
4736
4737 double funcvalue = func(&xyz.at(0),parameters);
4738
4739 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
4740 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
4741 v13 = v13 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e3j);
4742
4743 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
4744 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
4745 v23 = v23 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e3j);
4746
4747 v31 = v31 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e1j);
4748 v32 = v32 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e2j);
4749 v33 = v33 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e3j);
4750
4751
4752 }
4753 v11 = absDetB * v11;
4754 v12 = absDetB * v12;
4755 v13 = absDetB * v13;
4756 v21 = absDetB * v21;
4757 v22 = absDetB * v22;
4758 v23 = absDetB * v23;
4759 v31 = absDetB * v31;
4760 v32 = absDetB * v32;
4761 v33 = absDetB * v33;
4762
4763 value11[0] = v11;
4764 value12[0] = v12;
4765 value13[0] = v13;
4766 value21[0] = v21;
4767 value22[0] = v22;
4768 value23[0] = v23;
4769 value31[0] = v31;
4770 value32[0] = v32;
4771 value33[0] = v33;
4772
4773 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4774 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4775 indices[0] = glob_j;
4776 A->insertGlobalValues(glob_i, indices(), value11());
4777 A->insertGlobalValues(glob_i+1, indices(), value21());
4778 A->insertGlobalValues(glob_i+2, indices(), value31());
4779
4780 glob_j++;
4781 indices[0] = glob_j;
4782 A->insertGlobalValues(glob_i, indices(), value12());
4783 A->insertGlobalValues(glob_i+1, indices(), value22());
4784 A->insertGlobalValues(glob_i+2, indices(), value32());
4785
4786 glob_j++;
4787 indices[0] = glob_j;
4788 A->insertGlobalValues(glob_i, indices(), value13());
4789 A->insertGlobalValues(glob_i+1, indices(), value23());
4790 A->insertGlobalValues(glob_i+2, indices(), value33());
4791 }
4792 }
4793 }
4794 if (callFillComplete)
4795 {
4796 A->fillComplete();
4797 }
4798 }
4799
4800}
4801
4802
4803template <class SC, class LO, class GO, class NO>
4804double FE<SC,LO,GO,NO>::assemblyAbsorbingBoundaryPaper(int dim,
4805 std::string FEType,
4806 MultiVectorPtr_Type f,
4807 MultiVectorPtr_Type u_rep,
4808 vec_dbl_Type flowRate_vec,
4809 std::vector<SC>& funcParameter,
4810 RhsFunc_Type func,
4811 double areaOutlet_init,
4812 double areaOutlet_T,
4813 ParameterListPtr_Type params,
4814 int FEloc) {
4815
4816 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4817
4818 ElementsPtr_Type elementsPressure = domainVec_.at(FEloc+1)->getElementsC();
4819
4820 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4821
4822 vec2D_dbl_ptr_Type phi;
4823
4824
4825 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4826
4827 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
4828 Helper::getPhi(phi, weights, dim-1, FEType, deg);
4829
4830 vec2D_dbl_ptr_Type quadPoints;
4831 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
4832 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
4833 w.reset();
4834
4835 double poissonRatio=params->sublist("Parameter Fluid").get("Poisson Ratio",0.49);
4836 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
4837 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
4838
4839 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
4840 double E = params->sublist("Parameter Fluid").get("E",12.0);
4841 double wallThickness = params->sublist("Parameter Fluid").get("Wall thickness",0.0006);
4842 double density = params->sublist("Parameter Fluid").get("Density",1000.0);
4843 double p_ref_input = params->sublist("Parameter Fluid").get("Reference fluid pressure",10666.);
4844
4845 double rampTime = params->sublist("Parameter Fluid").get("Max Ramp Time",0.1);
4846 double unsteadyStart = params->sublist("Parameter Fluid").get("Unsteady Start",0.2);
4847 double flowRateInput = params->sublist("Parameter Fluid").get("Flowrate",3.0);
4848
4849 double bcRamp = params->sublist("Parameter Fluid").get("BC Ramp",0.1);
4850
4851
4852 SC elScaling;
4853 SmallMatrix<SC> B(dim);
4854 SmallMatrix<SC> Binv(dim);
4855 SC detB;
4856 SC absDetB;
4857 vec_dbl_Type b(dim);
4858 f->putScalar(0.);
4859 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
4860
4861 std::vector<double> valueFunc(dim);
4862
4863 double flowRateOutlet=0.;
4864 double flowRateInlet=0.;
4865
4866 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
4867
4868 int isNeg = this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
4869
4870 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
4871
4872 double areaOutlet = 0.;
4873 this->assemblyArea(dim, areaOutlet, flagOutlet);
4874
4875 double areaInlet =0.;
4876 this->assemblyArea(dim, areaInlet, flagInlet);
4877
4878 double beta=0.;
4879 if(funcParameter[0] < unsteadyStart)
4880 beta = ((wallThickness* E)/(1.-pow(poissonRatio,2))) * (M_PI/areaOutlet_init ) ;
4881 else
4882 beta = ((wallThickness* E)/(1.-pow(poissonRatio,2))) * (M_PI/areaOutlet_T ) ;
4883
4884 // We determine p_ref via a ramp
4885 funcParameter.push_back(p_ref_input);
4886 funcParameter.push_back(bcRamp);
4887 funcParameter.push_back(flagOutlet);
4888 SC* paramsFunc = &(funcParameter[0]);
4889 vec_dbl_Type x_tmp(dim,0.); //dummy
4890 paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
4891 paramsFunc[ 1 ] = p_ref_input;
4892 func( &x_tmp[0], &valueFunc[0], paramsFunc);
4893 double p_ref = valueFunc[0];
4894 if(funcParameter[0]+1e-12 >= unsteadyStart){
4895 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);
4896
4897 if(domainVec_.at(0)->getComm()->getRank()==0){
4898 std::cout << " ---------------------------------------------------------- " <<std::endl;
4899 std::cout << " ---------------- Start of unsteady phase ---------------- " <<std::endl;
4900 std::cout << " Reference pressure adjusted from " << p_ref_input << " to " << p_ref <<std::endl;
4901 }
4902
4903 }
4904 // Value of h_x for this timestep
4905 double flowRateUse = flowRateOutlet;
4906 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
4907 flowRateUse = flowRateOutletAveraged;
4908
4909 if(isNeg==1)
4910 flowRateUse = 0.;
4911
4912 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));
4913 double h_x = 0.;
4914
4915 if(funcParameter[0] < unsteadyStart)
4916 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);
4917 else
4918 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;
4919
4920 // h_x= pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta*sqrt(areaOutlet_init))),2) - beta*sqrt(areaOutlet_init) + p_ref;
4921
4922 if(domainVec_.at(0)->getComm()->getRank()==0){
4923 std::cout << " ---------------------------------------------------------- " <<std::endl;
4924 std::cout << " ---------------------------------------------------------- " <<std::endl;
4925 std::cout << " Absorbing Boundary Condition " <<std::endl;
4926 std::cout << " Input p_ref: " << p_ref_input <<std::endl;
4927 std::cout << " Adjusted p_ref: " << p_ref <<std::endl;
4928 std::cout << " Unsteady start time_ " << unsteadyStart <<std::endl;
4929 std::cout << " Volmetric flow Inlet: " << flowRateInlet <<std::endl;
4930 std::cout << " Volmetric flow Outlet: " << flowRateOutlet <<std::endl;
4931 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged <<std::endl;
4932 std::cout << " beta per Input: " << beta <<std::endl;
4933 std::cout << " Area_init outlet: " << areaOutlet_init <<std::endl;
4934 std::cout << " Area_init outlet_T: " << areaOutlet_T <<std::endl;
4935 std::cout << " Area inlet: " << areaInlet <<std::endl;
4936 std::cout << " Area outlet: " << areaOutlet <<std::endl;
4937 std::cout << " A_bar: " << A_bar <<std::endl;
4938 std::cout << " Flowrate was negative: " << isNeg <<std::endl;
4939 std::cout << " Value h_x at outlet: " << h_x <<std::endl;
4940 std::cout << " --------------------------------------------------------- " <<std::endl;
4941 std::cout << " --------------------------------------------------------- " <<std::endl;
4942
4943 }
4944 // Second step: use flow rate to determine pressure with resistance
4945 for (UN T=0; T<elements->numberElements(); T++) {
4946 FiniteElement fe = elements->getElement( T );
4947 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
4948 for (int surface=0; surface<fe.numSubElements(); surface++) {
4949 FiniteElement feSub = subEl->getElement( surface );
4950 if(subEl->getDimension() == dim-1 ){
4951 if(feSub.getFlag() == flagOutlet){
4952 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
4953 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
4954 int numNodes_T = nodeList.size();
4955 vec_dbl_Type solution_u = getSolution(nodeList, u_rep,dim);
4956 vec2D_dbl_Type nodes;
4957 nodes = getCoordinates(nodeList, pointsRep);
4958
4959 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
4960
4961 double norm_v_E = 1.;
4962 if(dim==2){
4963 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
4964 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
4965 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
4966
4967 }
4968 else if(dim==3){
4969
4970 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
4971 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
4972 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
4973
4974 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
4975 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
4976 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
4977
4978 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
4979 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
4980 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
4981
4982 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
4983
4984
4985 }
4986
4987 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
4988 // Step 1: Quadrature Points on physical surface:
4989 // Resulting Quad Points allways (0.5,0,0) (0.5,0.5,0) (0,0.5,0)
4990 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
4991 elScaling = B.computeScaling( );
4992
4993 //cout <<std::endl;
4994
4995 for (UN i=0; i < numNodes_T; i++) {
4996
4997 // 2.
4998 Teuchos::Array<SC> value(0);
4999 value.resize( dim, 0. );
5000 // loop over basis functions quadrature points
5001 for (UN w=0; w<phi->size(); w++) {
5002 for (int j=0; j<dim; j++){
5003 value[j] += weights->at(w) *normalScale*v_E[j]/norm_v_E *h_x*(*phi)[w][i];//valueFunc[0]
5004 }
5005 }
5006
5007 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
5008 for (int j=0; j<value.size(); j++)
5009 valuesF[ dim * nodeList[ i ] + j ] += value[j] * elScaling;
5010 }
5011
5012 }
5013
5014 }
5015 }
5016 }
5017 double p_out = h_x;
5018 return p_out;
5019}
5020
5021template <class SC, class LO, class GO, class NO>
5022double FE<SC,LO,GO,NO>::assemblyAbsorbingBoundary(int dim,
5023 std::string FEType,
5024 MultiVectorPtr_Type f,
5025 MultiVectorPtr_Type u_rep,
5026 vec_dbl_Type flowRate_vec,
5027 std::vector<SC>& funcParameter,
5028 RhsFunc_Type func,
5029 double areaOutlet_init,
5030 double areaOutlet_T,
5031 ParameterListPtr_Type params,
5032 int FEloc) {
5033
5034 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5035
5036 ElementsPtr_Type elementsPressure = domainVec_.at(FEloc+1)->getElementsC();
5037
5038 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5039
5040 vec2D_dbl_ptr_Type phi;
5041
5042
5043 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5044
5045 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
5046 Helper::getPhi(phi, weights, dim-1, FEType, deg);
5047
5048 vec2D_dbl_ptr_Type quadPoints;
5049 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
5050 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
5051 w.reset();
5052
5053 double poissonRatio=params->sublist("Parameter Fluid").get("Poisson Ratio",0.49);
5054 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
5055 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
5056
5057 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
5058
5059 double density = params->sublist("Parameter Fluid").get("Density",1.0);
5060 double p_ref_input = params->sublist("Parameter Fluid").get("Reference fluid pressure",10666.);
5061
5062 double rampTime = params->sublist("Parameter Fluid").get("Max Ramp Time",0.1);
5063 double unsteadyStart = params->sublist("Parameter Fluid").get("Heart Beat Start",0.2);
5064 double flowRateInput = params->sublist("Parameter Fluid").get("Flowrate",3.0e-06);
5065
5066 double bcRamp = params->sublist("Parameter Fluid").get("BC Ramp",0.1);
5067
5068
5069 SC elScaling;
5070 SmallMatrix<SC> B(dim);
5071 SmallMatrix<SC> Binv(dim);
5072 SC detB;
5073 SC absDetB;
5074 vec_dbl_Type b(dim);
5075 f->putScalar(0.);
5076 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
5077
5078 std::vector<double> valueFunc(dim);
5079
5080 double flowRateOutlet=0.;
5081 double flowRateInlet=0.;
5082
5083 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
5084 int isNeg = this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
5085
5086 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
5087
5088 double areaOutlet = 0.;
5089 this->assemblyArea(dim, areaOutlet, flagOutlet);
5090
5091 double areaInlet =0.;
5092 this->assemblyArea(dim, areaInlet, flagInlet);
5093
5094 double beta=0.;
5095
5096 double E = params->sublist("Parameter Fluid").get("E",12.0);
5097 double wallThickness = params->sublist("Parameter Fluid").get("Wall thickness",0.0006);
5098
5099 beta = ((wallThickness* E)/(1.-pow(poissonRatio,2))) * (M_PI/areaOutlet_init ) ;
5100
5101
5102 funcParameter.push_back(p_ref_input);
5103 funcParameter.push_back(bcRamp);
5104 funcParameter.push_back(flagOutlet);
5105 // We determine p_ref via a ramp
5106 SC* paramsFunc = &(funcParameter[0]);
5107 vec_dbl_Type x_tmp(dim,0.); //dummy
5108 // Adding parameters
5109
5110 // paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
5111 // paramsFunc[ 1 ] = p_ref_input;
5112 func( &x_tmp[0], &valueFunc[0], paramsFunc);
5113 double p_ref = valueFunc[0];
5114 //if(funcParameter[0]+1e-12 >= unsteadyStart){
5115
5116
5117 //}
5118 // Value of h_x for this timestep
5119 double flowRateUse = flowRateOutlet;
5120 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
5121 flowRateUse = flowRateOutletAveraged;
5122
5123 if(isNeg==1)
5124 flowRateUse = 0.;
5125
5126 if(domainVec_.at(0)->getComm()->getRank()==0){
5127 std::cout << " ---------------------------------------------------------- " <<std::endl;
5128 std::cout << " ---------------- computing p_ref ---------------- " <<std::endl;
5129 std::cout << " Reference pressure adjusted from " << p_ref_input << " to " << p_ref <<std::endl;
5130 }
5131 //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));
5132
5133 double h_x = pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta*sqrt(areaOutlet_init))),2) - beta*sqrt(areaOutlet_init)+p_ref;
5134
5135 // h_x= pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta*sqrt(areaOutlet_init))),2) - beta*sqrt(areaOutlet_init) + p_ref;
5136
5137 if(domainVec_.at(0)->getComm()->getRank()==0){
5138 std::cout << " ---------------------------------------------------------- " <<std::endl;
5139 std::cout << " ---------------------------------------------------------- " <<std::endl;
5140 std::cout << " Absorbing Boundary Condition " <<std::endl;
5141 std::cout << " Input p_ref: " << p_ref_input <<std::endl;
5142 std::cout << " Adjusted p_ref: " << p_ref <<std::endl;
5143 std::cout << " Volmetric flow Inlet: " << flowRateInlet <<std::endl;
5144 std::cout << " Volmetric flow Outlet: " << flowRateOutlet <<std::endl;
5145 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged <<std::endl;
5146 std::cout << " beta per Input: " << beta <<std::endl;
5147 std::cout << " Area_init outlet: " << areaOutlet_init <<std::endl;
5148 std::cout << " Area inlet: " << areaInlet <<std::endl;
5149 std::cout << " Area outlet: " << areaOutlet <<std::endl;
5150 std::cout << " Value h_x at outlet: " << h_x <<std::endl;
5151 std::cout << " --------------------------------------------------------- " <<std::endl;
5152 std::cout << " --------------------------------------------------------- " <<std::endl;
5153
5154 }
5155 // Second step: use flow rate to determine pressure with resistance
5156 for (UN T=0; T<elements->numberElements(); T++) {
5157 FiniteElement fe = elements->getElement( T );
5158 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
5159 for (int surface=0; surface<fe.numSubElements(); surface++) {
5160 FiniteElement feSub = subEl->getElement( surface );
5161 if(subEl->getDimension() == dim-1 ){
5162 if(feSub.getFlag() == flagOutlet){
5163 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
5164 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
5165 int numNodes_T = nodeList.size();
5166 vec_dbl_Type solution_u = getSolution(nodeList, u_rep,dim);
5167 vec2D_dbl_Type nodes;
5168 nodes = getCoordinates(nodeList, pointsRep);
5169
5170 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
5171
5172 double norm_v_E = 1.;
5173 if(dim==2){
5174 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5175 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
5176 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
5177
5178 }
5179 else if(dim==3){
5180
5181 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
5182 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5183 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
5184
5185 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
5186 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
5187 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
5188
5189 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
5190 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
5191 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
5192
5193 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
5194
5195
5196 }
5197
5198 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
5199 elScaling = B.computeScaling( );
5200
5201 for (UN i=0; i < numNodes_T; i++) {
5202
5203 // 2.
5204 Teuchos::Array<SC> value(0);
5205 value.resize( dim, 0. );
5206 // loop over basis functions quadrature points
5207 for (UN w=0; w<phi->size(); w++) {
5208 for (int j=0; j<dim; j++){
5209 value[j] += weights->at(w) *normalScale*v_E[j]/norm_v_E *h_x*(*phi)[w][i];//valueFunc[0]
5210 }
5211 }
5212
5213 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
5214 for (int j=0; j<value.size(); j++)
5215 valuesF[ dim * nodeList[ i ] + j ] += value[j] * elScaling;
5216 }
5217
5218 }
5219
5220 }
5221 }
5222 }
5223 double p_out = h_x;
5224 return p_out;
5225}
5226
5227
5228template <class SC, class LO, class GO, class NO>
5229double FE<SC,LO,GO,NO>::assemblyAbsorbingResistanceBoundary(int dim,
5230 std::string FEType,
5231 MultiVectorPtr_Type f,
5232 MultiVectorPtr_Type u_rep,
5233 vec_dbl_Type flowRate_vec,
5234 std::vector<SC>& funcParameter,
5235 RhsFunc_Type func,
5236 double areaOutlet_init,
5237 ParameterListPtr_Type params,
5238 int FEloc) {
5239
5240 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5241
5242 ElementsPtr_Type elementsPressure = domainVec_.at(FEloc+1)->getElementsC();
5243
5244 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5245
5246 vec2D_dbl_ptr_Type phi;
5247
5248
5249 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5250
5251 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
5252 Helper::getPhi(phi, weights, dim-1, FEType, deg);
5253
5254 vec2D_dbl_ptr_Type quadPoints;
5255 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
5256 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
5257 w.reset();
5258
5259 double poissonRatio=params->sublist("Parameter Fluid").get("Poisson Ratio",0.49);
5260 double viscosity=params->sublist("Parameter Fluid").get("Viscosity",1.0e-06);
5261 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
5262 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
5263
5264 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
5265 double E = params->sublist("Parameter Fluid").get("E",12.0);
5266 double wallThickness = params->sublist("Parameter Fluid").get("Wall thickness",0.001);
5267 double density = params->sublist("Parameter Fluid").get("Density",1000.0);
5268 double p_ref_input = params->sublist("Parameter Fluid").get("Reference fluid pressure",8000.);
5269 double resistanceRamp = params->sublist("Parameter Fluid").get("Resistance Ramp",2.); // Ramp time of fluid
5270 double resistance = params->sublist("Parameter Fluid").get("Resistance",1.0);
5271
5272 SC elScaling;
5273 SmallMatrix<SC> B(dim);
5274 SmallMatrix<SC> Binv(dim);
5275 SC detB;
5276 SC absDetB;
5277 vec_dbl_Type b(dim);
5278 f->putScalar(0.);
5279 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
5280
5281 std::vector<double> valueFunc(dim);
5282
5283 double flowRateOutlet=0.;
5284 double flowRateInlet=0.;
5285
5286 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
5287 this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
5288
5289 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
5290
5291 double areaOutlet = 0.;
5292 this->assemblyArea(dim, areaOutlet, flagOutlet);
5293
5294 double areaInlet =0.;
5295 this->assemblyArea(dim, areaInlet, flagInlet);
5296
5297 double beta = (((wallThickness* E)/(1-pow(poissonRatio,2))) * M_PI/areaOutlet_init ) *sqrt(areaOutlet_init);
5298 // We determine p_ref via a ramp
5299 SC* paramsFunc = &(funcParameter[0]);
5300 vec_dbl_Type x_tmp(dim,0.); //dummy
5301 paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
5302 //paramsFunc[ 1 ] = p_ref;
5303 //p_ref = valueFunc[0];
5304 // Value of h_x for this timestep
5305 double flowRateUse = flowRateOutlet;
5306 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
5307 flowRateUse = flowRateOutletAveraged;
5308
5309 double p_ref = 0.;
5310 if(paramsFunc[0] < resistanceRamp){
5311 //func( &x_tmp[0], &valueFunc[0], paramsFunc);
5312 p_ref = flowRateUse*resistance;
5313
5314 }
5315 else{
5316 paramsFunc[ 1 ] = p_ref_input;
5317 func( &x_tmp[0], &valueFunc[0], paramsFunc);
5318 //p_ref = valueFunc[0];
5319 p_ref = valueFunc[0];
5320
5321 }
5322
5323 double h_x = pow( (sqrt(density)/(2*sqrt(2)) * flowRateUse/areaOutlet + sqrt(beta)),2) - beta + p_ref;
5324
5325
5326 if(domainVec_.at(0)->getComm()->getRank()==0){
5327 std::cout << " ---------------------------------------------------------- " <<std::endl;
5328 std::cout << " ---------------------------------------------------------- " <<std::endl;
5329 std::cout << " Absorbing Boundary Condition " <<std::endl;
5330 std::cout << " p_ref: " << p_ref <<std::endl;
5331 std::cout << " Volmetric flow Inlet: " << flowRateInlet <<std::endl;
5332 std::cout << " Volmetric flow Outlet: " << flowRateOutlet <<std::endl;
5333 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged <<std::endl;
5334 std::cout << " beta*sqrt(A_0) per Input: " << beta <<std::endl;
5335 std::cout << " Area_init outlet: " << areaOutlet_init <<std::endl;
5336 std::cout << " Area inlet: " << areaInlet <<std::endl;
5337 std::cout << " Area outlet: " << areaOutlet <<std::endl;
5338 std::cout << " Value h_x at outlet: " << h_x <<std::endl;
5339 std::cout << " --------------------------------------------------------- " <<std::endl;
5340 std::cout << " --------------------------------------------------------- " <<std::endl;
5341
5342 }
5343 // Second step: use flow rate to determine pressure with resistance
5344 for (UN T=0; T<elements->numberElements(); T++) {
5345 FiniteElement fe = elements->getElement( T );
5346 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
5347 for (int surface=0; surface<fe.numSubElements(); surface++) {
5348 FiniteElement feSub = subEl->getElement( surface );
5349 if(subEl->getDimension() == dim-1 ){
5350 if(feSub.getFlag() == flagOutlet){
5351 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
5352 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
5353 int numNodes_T = nodeList.size();
5354 vec_dbl_Type solution_u = getSolution(nodeList, u_rep,dim);
5355 vec2D_dbl_Type nodes;
5356 nodes = getCoordinates(nodeList, pointsRep);
5357
5358 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
5359
5360 double norm_v_E = 1.;
5361 if(dim==2){
5362 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5363 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
5364 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
5365
5366 }
5367 else if(dim==3){
5368
5369 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
5370 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5371 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
5372
5373 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
5374 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
5375 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
5376
5377 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
5378 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
5379 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
5380
5381 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
5382
5383
5384 }
5385
5386 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
5387 // Step 1: Quadrature Points on physical surface:
5388 // Resulting Quad Points allways (0.5,0,0) (0.5,0.5,0) (0,0.5,0)
5389 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
5390 elScaling = B.computeScaling( );
5391
5392 //cout <<std::endl;
5393
5394 for (UN i=0; i < numNodes_T; i++) {
5395
5396 // 2.
5397 Teuchos::Array<SC> value(0);
5398 value.resize( dim, 0. );
5399 // loop over basis functions quadrature points
5400 for (UN w=0; w<phi->size(); w++) {
5401 for (int j=0; j<dim; j++){
5402 value[j] += weights->at(w) *normalScale*v_E[j]/norm_v_E *h_x*(*phi)[w][i];//valueFunc[0]
5403 }
5404 }
5405
5406 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
5407 for (int j=0; j<value.size(); j++)
5408 valuesF[ dim * nodeList[ i ] + j ] += value[j] * elScaling;
5409 }
5410
5411 }
5412
5413 }
5414 }
5415 }
5416 double p_out = h_x;
5417 return p_out;
5418}
5419
5420
5421template <class SC, class LO, class GO, class NO>
5422double FE<SC,LO,GO,NO>::assemblyResistanceBoundary(int dim,
5423 std::string FEType,
5424 MultiVectorPtr_Type f,
5425 MultiVectorPtr_Type u_rep,
5426 vec_dbl_Type flowRate_vec,
5427 std::vector<SC>& funcParameter,
5428 RhsFunc_Type func,
5429 ParameterListPtr_Type params,
5430 int FEloc) {
5431
5432 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5433
5434 ElementsPtr_Type elementsPressure = domainVec_.at(FEloc+1)->getElementsC();
5435
5436 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5437
5438 vec2D_dbl_ptr_Type phi;
5439 vec2D_dbl_ptr_Type phi1;
5440
5441 vec3D_dbl_ptr_Type dPhi;
5442
5443 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5444 vec_dbl_ptr_Type weights1 = Teuchos::rcp(new vec_dbl_Type(0));
5445
5446 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0);// + 1.0;
5447 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
5448 Helper::getPhi(phi, weights, dim-1, FEType, deg);
5449 Helper::getPhi(phi1, weights1, dim-1, FEType, 2);
5450
5451 vec2D_dbl_ptr_Type quadPoints;
5452 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
5453 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
5454 w.reset();
5455
5456 double viscosity=params->sublist("Parameter").get("Viscosity",0.49);
5457 int flagInlet = params->sublist("General").get("Flag Inlet Fluid", 4);
5458 int flagOutlet = params->sublist("General").get("Flag Outlet Fluid", 5);
5459
5460 double normalScale = params->sublist("Parameter Fluid").get("Normal Scale",1.0);
5461 double resistance = params->sublist("Parameter Fluid").get("Resistance",1.0);
5462 double bcRamp = params->sublist("Parameter Fluid").get("BC Ramp",0.1);
5463
5464 double referencePressure = params->sublist("Parameter Fluid").get("Reference fluid pressure",11.99e1);
5465
5466
5467 SC elScaling;
5468 SmallMatrix<SC> B(dim);
5469 SmallMatrix<SC> Binv(dim);
5470 SC detB;
5471 SC absDetB;
5472 vec_dbl_Type b(dim);
5473 f->putScalar(0.);
5474 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
5475
5476 std::vector<double> valueFunc(dim);
5477
5478 // Adding parameters
5479 funcParameter.push_back(resistance);
5480 funcParameter.push_back(bcRamp);
5481 funcParameter.push_back(flagOutlet);
5482
5483 SC* paramsFunc = &(funcParameter[0]);
5484 double flowRateInlet=0.;
5485 double flowRateOutlet=0.;
5486 this->assemblyFlowRate(dim, flowRateInlet, FEType , dim, flagInlet , u_rep);
5487 int isNeg = this->assemblyFlowRate(dim, flowRateOutlet, FEType , dim, flagOutlet , u_rep);
5488
5489 double resistanceRef = referencePressure/flowRateInlet; // The resistance based on a reference pressure value and the current inlet flow rate
5490
5491 double flowRateOutletAveraged = (flowRate_vec[0] + flowRate_vec[1]) / 2.;
5492
5493 vec_dbl_Type x_tmp(dim,0.); //dummy
5494 // paramsFunc[ funcParameter.size() - 1 ] =flagOutlet;
5495
5496 func( &x_tmp[0], &valueFunc[0], paramsFunc);
5497
5498 if(domainVec_.at(0)->getComm()->getRank()==0){
5499 std::cout << " ---------------------------------------------------------- " << std::endl;
5500 std::cout << " ---------------------------------------------------------- " << std::endl;
5501 std::cout << " Resistance Boundary Condition " << std::endl;
5502 std::cout << " Volmetric flow Inlet: " << flowRateInlet << std::endl;
5503 std::cout << " Volmetric flow Outlet: " << flowRateOutlet << std::endl;
5504 std::cout << " Averaged volmetric flow Outlet: " << flowRateOutletAveraged << std::endl;
5505 std::cout << " Resistance per Input: " << valueFunc[0] << std::endl;
5506 std::cout << " Assumed reference pressure at outlet " << referencePressure<< std::endl;
5507 std::cout << " Implicit pressure at outlet with p=R*Q: " << flowRateOutlet*valueFunc[0] << std::endl;
5508 std::cout << " Resistance based on (referencePressure)/flowRateInlet at this point would be: " << resistanceRef << std::endl;
5509 std::cout << " --------------------------------------------------------- " << std::endl;
5510 std::cout << " --------------------------------------------------------- " << std::endl;
5511
5512 }
5513
5514 double flowRateUse = flowRateOutlet;
5515 if(params->sublist("Parameter Fluid").get("Average Flowrate",false) )
5516 flowRateUse = flowRateOutletAveraged;
5517
5518 if(isNeg==1)
5519 flowRateUse = 0.;
5520
5521 double p_out = flowRateUse*valueFunc[0];
5522
5523 // Second step: use flow rate to determine pressure with resistance
5524 for (UN T=0; T<elements->numberElements(); T++) {
5525 FiniteElement fe = elements->getElement( T );
5526 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
5527 for (int surface=0; surface<fe.numSubElements(); surface++) {
5528 FiniteElement feSub = subEl->getElement( surface );
5529 if(subEl->getDimension() == dim-1 ){
5530
5531 // We only need to compute it on the outlet of the geometry
5532 if(feSub.getFlag() == flagOutlet){
5533 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
5534 vec_int_Type nodeListP = elementsPressure->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
5535 int numNodes_T = nodeList.size();
5536 vec_dbl_Type solution_u = getSolution(nodeList, u_rep,dim);
5537 vec2D_dbl_Type nodes;
5538 nodes = getCoordinates(nodeList, pointsRep);
5539
5540 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
5541
5542 double norm_v_E = 1.;
5543 if(dim==2){
5544 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5545 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
5546 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
5547
5548 }
5549 else if(dim==3){
5550
5551 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
5552 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5553 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
5554
5555 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
5556 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
5557 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
5558
5559 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
5560 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
5561 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
5562
5563 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
5564 }
5565
5566 // vec_dbl_Type x(dim,0.); //dummy
5567 // paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
5568
5569 // func( &x[0], &valueFunc[0], paramsFunc);
5570 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
5571 // Step 1: Quadrature Points on physical surface:
5572 vec_dbl_Type quadWeights(dim);
5573 quadWeights[0] = 1/6.;
5574 quadWeights[1] = 1/6.;
5575 quadWeights[2] = 1/6.;
5576 vec2D_dbl_Type quadPoints(quadWeights.size(), vec_dbl_Type(dim));
5577
5578 vec_int_Type kn1= elements->getElement(T).getVectorNodeListNonConst();
5579
5580 vec2D_dbl_Type quadPointsT1(quadWeights.size(),vec_dbl_Type(dim));
5581 quadPointsT1.push_back({0.5,0.5,0.0});
5582 quadPointsT1.push_back({0.0,0.5,0.0});
5583 quadPointsT1.push_back({0.5,0.0,0.0});
5584
5585 SC detB1;
5586 SC absDetB1;
5587 SmallMatrix<SC> B1(dim);
5588 SmallMatrix<SC> Binv1(dim);
5589 int index0,index;
5590
5591 index0 = kn1[0];
5592 for (int s=0; s<dim; s++) {
5593 index = kn1[s+1];
5594 for (int t=0; t<dim; t++) {
5595 B1[t][s] = pointsRep->at(index).at(t) -pointsRep->at(index0).at(t);
5596 }
5597 }
5598
5599 detB1 = B1.computeInverse(Binv1);
5600 detB1 = std::fabs(detB1);
5601
5602 // Resulting Quad Points allways (0.5,0,0) (0.5,0.5,0) (0,0.5,0)
5603 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
5604 elScaling = B.computeScaling( );
5605
5606 //cout <<std::endl;
5607
5608 for (UN i=0; i < numNodes_T; i++) {
5609
5610 // 2.
5611 Teuchos::Array<SC> value(0);
5612 value.resize( dim, 0. );
5613 // loop over basis functions quadrature points
5614 for (UN w=0; w<phi->size(); w++) {
5615 for (int d=0; d<dim; d++){
5616 value[d] += weights->at(w) *normalScale*v_E[d]/norm_v_E *flowRateUse*valueFunc[0]*(*phi)[w][i];//valueFunc[0]
5617 }
5618 }
5619
5620 //cout << " Value First component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
5621 for (int d=0; d<dim; d++)
5622 valuesF[ dim * nodeList[ i ] + d ] += value[d] * elScaling;
5623 }
5624
5625 // We make the distinction between a gradient jump calculation or a simple jump calculation
5626 vec_dbl_Type valueSecondComp(dim,0.);
5627
5628 for (UN t=0; t < numNodes_T; t++) {
5629 Teuchos::Array<SC> value( dim, 0. ); //These are value (W_ix,W_iy,W_iz)
5630 for(int l=0; l< quadWeights.size(); l++){
5631 vec_dbl_Type deriPhi1( dim,0.0) ;
5632 vec_dbl_ptr_Type valuePhi(new vec_dbl_Type(dim,0.0));
5633
5634 auto it1 = find( kn1.begin(), kn1.end() ,nodeList[t] );
5635 int id_in_element = distance( kn1.begin() , it1 );
5636
5637 Helper::gradPhi(dim,2,id_in_element,quadPointsT1[l],valuePhi);
5638 for (int j=0; j<3; j++) {
5639 deriPhi1[j] = valuePhi->at(j);
5640 }
5641
5642 vec_dbl_Type deriPhiT1(dim,0.);
5643 for(int q=0; q<dim; q++){
5644 for(int s=0; s< dim ; s++)
5645 deriPhiT1[q] += (deriPhi1[s]*Binv1[s][q]);
5646
5647 }
5648 // Phi might have other quad points
5649 for (UN d=0; d<dim; d++) {
5650 value[d] += quadWeights[l] *solution_u[t*dim+d] * deriPhi1[d]* v_E[d]/norm_v_E * (*phi)[l][t];
5651 }
5652 }
5653 // cout << " Value Second component " << value[0] << " " << value[1] << " " << value[2] <<std::endl;
5654 for (int j=0; j<value.size(); j++)
5655 valuesF[ dim * nodeList[ t ] + j ] -= normalScale*value[j] *elScaling*viscosity;
5656
5657 }
5658
5659
5660 }
5661
5662 }
5663 }
5664 }
5665 return p_out;
5666}
5667
5668
5669template <class SC, class LO, class GO, class NO>
5670void FE<SC,LO,GO,NO>::assemblyArea(int dim,
5671 double &area,
5672 int inflowFlag,
5673 int FEloc){
5674
5675 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5676
5677 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5678
5679 int inletFlag=inflowFlag; //params->sublist("Parameter Fluid").get("Fluid Flag",4);
5680
5681 double areaSurface=0.;
5682
5683 // Step 0: determie flowrate on inlet to calculate resistance
5684 for (UN T=0; T<elements->numberElements(); T++) {
5685 FiniteElement fe = elements->getElement( T );
5686 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
5687 for (int surface=0; surface<fe.numSubElements(); surface++) {
5688 FiniteElement feSub = subEl->getElement( surface );
5689 if(subEl->getDimension() == dim-1 ){
5690 if(feSub.getFlag() == inletFlag){
5691 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
5692 int numNodes_T = nodeList.size();
5693 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
5694
5695 double norm_v_E = 1.;
5696 if(dim==2){
5697 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5698 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
5699 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
5700 areaSurface += norm_v_E;
5701
5702 }
5703 else if(dim==3){
5704
5705 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
5706 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5707 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
5708
5709 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
5710 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
5711 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
5712
5713 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
5714 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
5715 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
5716
5717 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
5718
5719 // A = norm_v_E * 0.5
5720 areaSurface += norm_v_E*0.5;
5721
5722
5723 }
5724
5725
5726
5727 }
5728
5729
5730 }
5731 }
5732 }
5733 reduceAll<int, double> (*domainVec_.at(0)->getComm(), REDUCE_SUM, areaSurface, outArg (areaSurface));
5734
5735 area = areaSurface;
5736
5737}
5738
5739template <class SC, class LO, class GO, class NO>
5740int FE<SC,LO,GO,NO>::assemblyFlowRate(int dim,
5741 double &flowRateParabolic,
5742 std::string FEType,
5743 int dofs,
5744 int inflowFlag,
5745 MultiVectorPtr_Type solution_rep,
5746 int FEloc){
5747
5748 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5749
5750 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5751
5752 vec2D_dbl_ptr_Type phi;
5753
5754 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5755
5756 Helper::getPhi(phi, weights, dim-1, FEType, 2);
5757
5758 vec2D_dbl_ptr_Type quadPoints;
5759 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
5760 Helper::getQuadratureValues(dim-1, 2, quadPoints, w, FEType);
5761 w.reset();
5762
5763 int inletFlag=inflowFlag; //params->sublist("Parameter Fluid").get("Fluid Flag",4);
5764
5765
5766 SC elScaling;
5767 vec_dbl_Type b(dim);
5768 SmallMatrix<SC> B(dim);
5769 SmallMatrix<SC> Binv(dim);
5770 SC detB;
5771 SC absDetB;
5772
5773 double flowRateInlet=0.;
5774
5775 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
5776
5777 Teuchos::ArrayRCP< const SC > uArray = solution_rep->getData(0);
5778 // Step 0: determie flowrate on inlet to calculate resistance
5779 for (UN T=0; T<elements->numberElements(); T++) {
5780 FiniteElement fe = elements->getElement( T );
5781 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
5782 for (int surface=0; surface<fe.numSubElements(); surface++) {
5783 FiniteElement feSub = subEl->getElement( surface );
5784 if(subEl->getDimension() == dim-1 ){
5785 if(feSub.getFlag() == inletFlag){
5786 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
5787 int numNodes_T = nodeList.size();
5788 vec_dbl_Type solution_u = getSolution(nodeList, solution_rep,dofs);
5789
5790
5791 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
5792
5793 double norm_v_E = 1.;
5794 if(dim==2){
5795 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5796 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
5797 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2));
5798
5799 }
5800 else if(dim==3){
5801
5802 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
5803 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
5804 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
5805
5806 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
5807 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
5808 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
5809
5810 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
5811 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
5812 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
5813
5814 norm_v_E = sqrt(pow(v_E[0],2)+pow(v_E[1],2)+pow(v_E[2],2));
5815
5816 // cout << " Normal Vector " << v_E[0] << " " << v_E[1] << " "<< v_E[2] <<std::endl;
5817 }
5818
5819 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
5820 // Step 1: Quadrature Points on physical surface:
5821 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
5822 elScaling = B.computeScaling( );
5823
5824 Teuchos::Array<SC> value(0);
5825 value.resize( numNodes_T, 0. ); // Volumetric flow rate over one surface is a skalar value
5826 // //cout << " Velocity over node ";
5827 // for (int w=0; w<phi->size(); w++){ //quads points
5828 // for (int d=0; d<dim; d++) {
5829 // uLoc[d][w] = 0.;
5830 // for (int i=0; i < phi->at(0).size(); i++) {
5831 // LO index = dim * nodeList[i] + d;
5832 // uLoc[d][w] += uArray[index] * phi->at(w).at(i);
5833 // }
5834 // }
5835 // }
5836
5837 for (UN i=0; i < numNodes_T; i++) {
5838 // loop over basis functions quadrature points
5839 for (UN w=0; w<phi->size(); w++) {
5840 for (int j=0; j<dim; j++){
5841 if(dofs==1){
5842 value[i] += weights->at(w) *v_E[j]/norm_v_E *solution_u[i]*(*phi)[w][i]; // valueFunc[0]* = 1.0
5843 }
5844 else{
5845 LO index = dim * i + j;
5846 value[i] += weights->at(w) *v_E[j]/norm_v_E *solution_u[index]*(*phi)[w][i]; // valueFunc[0]* = 1.0
5847 }
5848
5849 }
5850 }
5851 flowRateInlet += value[i] * elScaling;
5852
5853 }
5854 }
5855
5856
5857 }
5858 }
5859 }
5860 reduceAll<int, double> (*domainVec_.at(0)->getComm(), REDUCE_SUM, flowRateInlet, outArg (flowRateInlet));
5861 // if(flowRateInlet < 0 && domainVec_.at(0)->getComm()->getRank() == 0)
5862 // 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;
5863 int isNeg=0;
5864
5865 if(flowRateInlet <0)
5866 isNeg = 1;
5867 flowRateParabolic = fabs(flowRateInlet);
5868
5869 return isNeg;
5870
5871}
5872
5873
5874template <class SC, class LO, class GO, class NO>
5875void FE<SC,LO,GO,NO>::assemblyAverageVelocity(int dim,
5876 double &averageVelocity,
5877 std::string FEType,
5878 int dofs,
5879 int flag,
5880 MultiVectorPtr_Type solution_rep,
5881 int FEloc){
5882
5883 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5884
5885 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5886
5887 vec2D_dbl_ptr_Type phi;
5888
5889 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5890
5891 Helper::getPhi(phi, weights, dim-1, FEType, 2);
5892
5893 vec2D_dbl_ptr_Type quadPoints;
5894 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
5895 Helper::getQuadratureValues(dim-1, 2, quadPoints, w, FEType);
5896 w.reset();
5897
5898 double area =0.;
5899 this->assemblyArea(dim, area, flag);
5900
5901 SC elScaling;
5902 vec_dbl_Type b(dim);
5903 SmallMatrix<SC> B(dim);
5904 SmallMatrix<SC> Binv(dim);
5905 SC detB;
5906 SC absDetB;
5907
5908 double velocity=0.;
5909
5910 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
5911
5912 Teuchos::ArrayRCP< const SC > uArray = solution_rep->getData(0);
5913 // Step 0: determie flowrate on inlet to calculate resistance
5914 for (UN T=0; T<elements->numberElements(); T++) {
5915 FiniteElement fe = elements->getElement( T );
5916 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
5917 for(int surface=0; surface<fe.numSubElements(); surface++) {
5918 FiniteElement feSub = subEl->getElement( surface );
5919 if(subEl->getDimension() == dim-1 ){
5920 if(feSub.getFlag() == flag){
5921 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
5922 int numNodes_T = nodeList.size();
5923 vec_dbl_Type solution_u = getSolution(nodeList, solution_rep,dofs);
5924
5925 vec_dbl_Type p1(dim),p2(dim),v_E(dim,1.);
5926
5927 // Calculating R * Q = R * v * A , A = norm_v_E * 0.5
5928 // Step 1: Quadrature Points on physical surface:
5929 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
5930 elScaling = B.computeScaling( );
5931
5932 Teuchos::Array<SC> value(0);
5933 value.resize( numNodes_T, 0. ); // Volumetric flow rate over one surface is a skalar value
5934
5935 for (UN i=0; i < numNodes_T; i++) {
5936 // loop over basis functions quadrature points
5937 for (UN w=0; w<phi->size(); w++) {
5938 for (int j=0; j<dim; j++){
5939 if(dofs==1){
5940 value[i] += weights->at(w)*solution_u[i]*(*phi)[w][i]; // valueFunc[0]* = 1.0
5941 }
5942 else{
5943 LO index = dim * i + j;
5944 value[i] += weights->at(w)*solution_u[index]*(*phi)[w][i]; // valueFunc[0]* = 1.0
5945 }
5946
5947 }
5948 }
5949 velocity += value[i] * elScaling;
5950 }
5951 }
5952 }
5953 }
5954 }
5955 reduceAll<int, double> (*domainVec_.at(0)->getComm(), REDUCE_SUM, velocity, outArg (velocity));
5956 velocity = velocity/area;
5957 std::cout << " Average Flowvelocity "<< velocity << " ####### " <<std::endl;
5958
5959 averageVelocity = velocity;
5960}
5961
5962
5963
5964template <class SC, class LO, class GO, class NO>
5966 std::string FEType,
5967 MatrixPtr_Type &A,
5968 double lambda,
5969 double mu,
5970 bool callFillComplete)
5971{
5972 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
5973 int FEloc = this->checkFE(dim,FEType);
5974
5975 // Get elements and node lists
5976 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5977 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5978 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
5979
5980 vec3D_dbl_ptr_Type dPhi;
5981 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
5982 vec2D_dbl_ptr_Type quadPts;
5983
5984 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
5985
5986 // Get gradient(phi)
5987 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
5988 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
5989
5990 // Define basisfunctions \phi_i and \phi_j
5991 // vec_dbl_Type basisValues_i(dim,0.), basisValues_j(dim,0.);
5992
5993 // SC = double, GO = long, UN = int
5994 SC detB;
5995 SC absDetB;
5996 SmallMatrix<SC> B(dim);
5997 SmallMatrix<SC> Binv(dim);
5998 GO glob_i, glob_j;
5999
6000 // for intermediate results
6001 SC res;
6002
6003 // for the computation of the trace
6004 double res_trace_i, res_trace_j;
6005
6006 if (dim == 2)
6007 {
6008
6009 double v11, v12, v21, v22;
6010 // Initialize vectors of size 2 with 0.0 (double)
6011 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
6012
6013 // Matrices of size 2x2, in which the individual epsilon tensors are computed; see below for more.
6014 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
6015 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
6016
6017 for (int T = 0; T < elements->numberElements(); T++)
6018 {
6019 // Get vertices of the triangle
6020 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6021 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6022 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6023
6024 // Compute transformation matrix B for the respective element (2D)
6025 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
6026 detB = B.computeInverse(Binv);
6027 absDetB = std::fabs(detB);
6028
6029 // dPhiTrans are the transformed basisfunctions, i.e., B^(-T) * \grad_phi and \grad_phi^T * B^(-1).
6030 // So \hat{grad_phi}.
6031 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
6032 applyBTinv( dPhi, dPhiTrans, Binv ); // compute dPhiTrans
6033
6034 for (int i = 0; i < dPhi->at(0).size(); i++)
6035 {
6036 Teuchos::Array<SC> value11( 1, 0. );
6037 Teuchos::Array<SC> value12( 1, 0. );
6038 Teuchos::Array<SC> value21( 1, 0. );
6039 Teuchos::Array<SC> value22( 1, 0. );
6040 Teuchos::Array<GO> indices( 1, 0 );
6041
6042 for (int j = 0; j < dPhi->at(0).size(); j++)
6043 {
6044 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
6045 for (int k = 0; k < dPhi->size(); k++)
6046 {
6047 // In epsilonValuesMat1_i (2x2 matrix), epsilonTensor is contained for a scalar shape function for the direction 1 (cf. Mat1)
6048 // corresponding to shape function i, i.e., \phi_i.
6049 // Thus, in Mat1_i we have \eps of phi_i = (phi_scalar_i, 0).
6050
6051 // Compute \hat{grad_phi_i} = basisValues_i, i.e., B^(-T)*grad_phi_i
6052 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
6053
6054 // \eps(v) = \eps(phi_i)
6055 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x direction
6056 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y direction
6057
6058 // See above, here carried out for j
6059 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
6060
6061 // \eps(u) = \eps(phi_j)
6062 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x direction
6063 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y direction
6064
6065 // Now we compute \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
6066 // The result wil be stored in res.
6067 // Compute the trace of the epsilon tensors tr(\eps(u)) (j) and tr(\eps(v)) (i)
6068 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
6069 epsilonValuesMat1_i.trace(res_trace_i);
6070 epsilonValuesMat1_j.trace(res_trace_j);
6071 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6072
6073 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
6074 epsilonValuesMat1_i.trace(res_trace_i);
6075 epsilonValuesMat2_j.trace(res_trace_j);
6076 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6077
6078 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
6079 epsilonValuesMat2_i.trace(res_trace_i);
6080 epsilonValuesMat1_j.trace(res_trace_j);
6081 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6082
6083 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
6084 epsilonValuesMat2_i.trace(res_trace_i);
6085 epsilonValuesMat2_j.trace(res_trace_j);
6086 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6087
6088
6089 }
6090 // Scale with abs(det(B))
6091 v11 = absDetB * v11;
6092 v12 = absDetB * v12;
6093 v21 = absDetB * v21;
6094 v22 = absDetB * v22;
6095
6096 value11[0] = v11;
6097 value12[0] = v12;
6098 value21[0] = v21;
6099 value22[0] = v22;
6100
6101 // Get the global row and column to which the entries need to be written.
6102 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6103 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6104 indices[0] = glob_j;
6105 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
6106 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6107 glob_j++;
6108 indices[0] = glob_j;
6109 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
6110 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6111 }
6112 }
6113 }
6114 if (callFillComplete)
6115 {
6116 A->fillComplete();
6117 }
6118 }
6119 else if(dim == 3)
6120 {
6121
6122 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
6123
6124 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6125 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
6126 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
6127
6128 for (int T = 0; T < elements->numberElements(); T++)
6129 {
6130 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6131 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6132 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6133 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6134
6135 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
6136 detB = B.computeInverse(Binv);
6137 absDetB = std::fabs(detB);
6138
6139 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6140 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
6141 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
6142
6143 for (int i = 0; i < dPhi->at(0).size(); i++)
6144 {
6145 Teuchos::Array<SC> value11( 1, 0. );
6146 Teuchos::Array<SC> value12( 1, 0. );
6147 Teuchos::Array<SC> value13( 1, 0. );
6148 Teuchos::Array<SC> value21( 1, 0. );
6149 Teuchos::Array<SC> value22( 1, 0. );
6150 Teuchos::Array<SC> value23( 1, 0. );
6151 Teuchos::Array<SC> value31( 1, 0. );
6152 Teuchos::Array<SC> value32( 1, 0. );
6153 Teuchos::Array<SC> value33( 1, 0. );
6154 Teuchos::Array<GO> indices( 1, 0 );
6155
6156 for (int j = 0; j < dPhi->at(0).size(); j++)
6157 {
6158 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;
6159 for (int k = 0; k < dPhi->size(); k++)
6160 {
6161
6162 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
6163
6164 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
6165 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
6166 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
6167
6168
6169 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
6170
6171 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
6172 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
6173 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
6174
6175 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
6176 epsilonValuesMat1_i.trace(res_trace_i);
6177 epsilonValuesMat1_j.trace(res_trace_j);
6178 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6179
6180 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
6181 epsilonValuesMat1_i.trace(res_trace_i);
6182 epsilonValuesMat2_j.trace(res_trace_j);
6183 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6184
6185 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
6186 epsilonValuesMat1_i.trace(res_trace_i);
6187 epsilonValuesMat3_j.trace(res_trace_j);
6188 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6189
6190 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
6191 epsilonValuesMat2_i.trace(res_trace_i);
6192 epsilonValuesMat1_j.trace(res_trace_j);
6193 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6194
6195 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
6196 epsilonValuesMat2_i.trace(res_trace_i);
6197 epsilonValuesMat2_j.trace(res_trace_j);
6198 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6199
6200 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
6201 epsilonValuesMat2_i.trace(res_trace_i);
6202 epsilonValuesMat3_j.trace(res_trace_j);
6203 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6204
6205 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
6206 epsilonValuesMat3_i.trace(res_trace_i);
6207 epsilonValuesMat1_j.trace(res_trace_j);
6208 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6209
6210 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
6211 epsilonValuesMat3_i.trace(res_trace_i);
6212 epsilonValuesMat2_j.trace(res_trace_j);
6213 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6214
6215 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
6216 epsilonValuesMat3_i.trace(res_trace_i);
6217 epsilonValuesMat3_j.trace(res_trace_j);
6218 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6219
6220 }
6221 v11 = absDetB * v11;
6222 v12 = absDetB * v12;
6223 v13 = absDetB * v13;
6224 v21 = absDetB * v21;
6225 v22 = absDetB * v22;
6226 v23 = absDetB * v23;
6227 v31 = absDetB * v31;
6228 v32 = absDetB * v32;
6229 v33 = absDetB * v33;
6230
6231 value11[0] = v11;
6232 value12[0] = v12;
6233 value13[0] = v13;
6234 value21[0] = v21;
6235 value22[0] = v22;
6236 value23[0] = v23;
6237 value31[0] = v31;
6238 value32[0] = v32;
6239 value33[0] = v33;
6240
6241 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6242 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6243 indices[0] = glob_j;
6244 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
6245 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6246 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
6247 glob_j++;
6248 indices[0] = glob_j;
6249 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
6250 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6251 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
6252 glob_j++;
6253 indices[0] = glob_j;
6254 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
6255 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
6256 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
6257 }
6258 }
6259 }
6260 if (callFillComplete)
6261 {
6262 A->fillComplete();
6263 }
6264 }
6265}
6266
6267// Determine the change of emodule depending on concentration
6268template <class SC, class LO, class GO, class NO>
6269void FE<SC,LO,GO,NO>::determineEMod(std::string FEType, MultiVectorPtr_Type solution,MultiVectorPtr_Type &eModVec, DomainConstPtr_Type domain, ParameterListPtr_Type params){
6270
6271
6272 ElementsPtr_Type elements = domain->getElementsC();
6273
6274 int dim = domain->getDimension();
6275 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
6276
6277 //MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
6278
6279 Teuchos::ArrayRCP< const SC > uArray = solution->getData(0);
6280 Teuchos::ArrayRCP< SC > eModVecA = eModVec->getDataNonConst(0);
6281
6282 double E0 = params->sublist("Parameter Solid").get("E",3.0e+6);
6283 double E1 = params->sublist("Parameter Solid").get("E1",3.0e+5);
6284 double c1 = params->sublist("Parameter Solid").get("c1",1.0);
6285 double eModMax =E1;
6286 double eModMin = E0;
6287
6288 int nodesElement = elements->getElement(0).getVectorNodeList().size();
6289 for (UN T=0; T<elements->numberElements(); T++) {
6290
6291 /*buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
6292 detB = B.computeInverse(Binv);
6293 absDetB = std::fabs(detB);*/
6294
6295 double uLoc = 0.;
6296
6297 for(int i=0; i< nodesElement;i++){
6298 LO index = elements->getElement(T).getNode(i) ;
6299 uLoc += 1./nodesElement*uArray[index];
6300 }
6301
6302 eModVecA[T] = E0-(E0-E1)*(uLoc/(uLoc+c1));
6303 if(eModVecA[T] > eModMax )
6304 eModMax = eModVecA[T];
6305 if(eModVecA[T] < eModMin)
6306 eModMin = eModVecA[T];
6307 }
6308 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MIN, eModMin, Teuchos::outArg (eModMin));
6309 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MAX, eModMax, Teuchos::outArg (eModMax));
6310
6311 if(domain->getComm()->getRank()==0)
6312 std::cout << " ################# eMOD Min: " << eModMin << " \t eModMax: " << eModMax<< " ############# " << std::endl;
6313
6314
6315}
6316
6317
6319template <class SC, class LO, class GO, class NO>
6321 std::string FEType,
6322 MatrixPtr_Type &A,
6323 MultiVectorPtr_Type eModVec,
6324 double nu,
6325 bool callFillComplete)
6326{
6327 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
6328 int FEloc = this->checkFE(dim,FEType);
6329
6330 // Get elements and node lists
6331 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
6332 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
6333 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
6334
6335 vec3D_dbl_ptr_Type dPhi;
6336 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
6337 vec2D_dbl_ptr_Type quadPts;
6338
6339 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
6340
6341 // Get gradient(phi)
6342 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
6343 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
6344
6345 SC detB;
6346 SC absDetB;
6347 SmallMatrix<SC> B(dim);
6348 SmallMatrix<SC> Binv(dim);
6349 GO glob_i, glob_j;
6350
6351 // for intermediate results
6352 SC res;
6353
6354 // for the computation of the trace
6355 double res_trace_i, res_trace_j;
6356
6357 Teuchos::ArrayRCP< const SC > E = eModVec->getData(0);
6358 double lambda;
6359 double mu ;
6360
6361 if (dim == 2)
6362 {
6363
6364 double v11, v12, v21, v22;
6365 // Initialize vectors of size 2 with 0.0 (double)
6366 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
6367
6368 // Matrices of size 2x2, in which the individual epsilon tensors are computed; see below for more.
6369 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
6370 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
6371
6372 for (int T = 0; T < elements->numberElements(); T++)
6373 {
6375 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
6376 mu = E[T] / (2.*(1.+nu));
6377
6378 // Get vertices of the triangle
6379 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6380 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6381 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6382
6383 // Compute transformation matrix B for the respective element (2D)
6384 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
6385 detB = B.computeInverse(Binv);
6386 absDetB = std::fabs(detB);
6387
6388 // dPhiTrans are the transformed basisfunctions, i.e., B^(-T) * \grad_phi and \grad_phi^T * B^(-1).
6389 // So \hat{grad_phi}.
6390 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
6391 applyBTinv( dPhi, dPhiTrans, Binv ); // compute dPhiTrans
6392
6393 for (int i = 0; i < dPhi->at(0).size(); i++)
6394 {
6395 Teuchos::Array<SC> value11( 1, 0. );
6396 Teuchos::Array<SC> value12( 1, 0. );
6397 Teuchos::Array<SC> value21( 1, 0. );
6398 Teuchos::Array<SC> value22( 1, 0. );
6399 Teuchos::Array<GO> indices( 1, 0 );
6400
6401 for (int j = 0; j < dPhi->at(0).size(); j++)
6402 {
6403 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
6404 for (int k = 0; k < dPhi->size(); k++)
6405 {
6406 // In epsilonValuesMat1_i (2x2 matrix), epsilonTensor is contained for a scalar shape function for the direction 1 (cf. Mat1)
6407 // corresponding to shape function i, i.e., \phi_i.
6408 // Thus, in Mat1_i we have \eps of phi_i = (phi_scalar_i, 0).
6409
6410 // Compute \hat{grad_phi_i} = basisValues_i, i.e., B^(-T)*grad_phi_i
6411 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
6412
6413 // \eps(v) = \eps(phi_i)
6414 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x direction
6415 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y direction
6416
6417 // See above, here carried out for j
6418 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
6419
6420 // \eps(u) = \eps(phi_j)
6421 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x direction
6422 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y direction
6423
6424 // Now we compute \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
6425 // The result wil be stored in res.
6426 // Compute the trace of the epsilon tensors tr(\eps(u)) (j) and tr(\eps(v)) (i)
6427 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
6428 epsilonValuesMat1_i.trace(res_trace_i);
6429 epsilonValuesMat1_j.trace(res_trace_j);
6430 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6431
6432 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
6433 epsilonValuesMat1_i.trace(res_trace_i);
6434 epsilonValuesMat2_j.trace(res_trace_j);
6435 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6436
6437 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
6438 epsilonValuesMat2_i.trace(res_trace_i);
6439 epsilonValuesMat1_j.trace(res_trace_j);
6440 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6441
6442 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
6443 epsilonValuesMat2_i.trace(res_trace_i);
6444 epsilonValuesMat2_j.trace(res_trace_j);
6445 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6446
6447
6448 }
6449 // Scale with abs(det(B))
6450 v11 = absDetB * v11;
6451 v12 = absDetB * v12;
6452 v21 = absDetB * v21;
6453 v22 = absDetB * v22;
6454
6455 value11[0] = v11;
6456 value12[0] = v12;
6457 value21[0] = v21;
6458 value22[0] = v22;
6459
6460 // Get the global row and column to which the entries need to be written.
6461 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6462 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6463 indices[0] = glob_j;
6464 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
6465 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6466 glob_j++;
6467 indices[0] = glob_j;
6468 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
6469 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6470 }
6471 }
6472 }
6473 if (callFillComplete)
6474 {
6475 A->fillComplete();
6476 }
6477 }
6478 else if(dim == 3)
6479 {
6480
6481 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
6482
6483 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6484 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
6485 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
6486
6487 for (int T = 0; T < elements->numberElements(); T++)
6488 {
6489 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
6490 mu = E[T] / (2.*(1.+nu));
6491
6492 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6493 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6494 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6495 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6496
6497 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
6498 detB = B.computeInverse(Binv);
6499 absDetB = std::fabs(detB);
6500
6501 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6502 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
6503 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
6504
6505 for (int i = 0; i < dPhi->at(0).size(); i++)
6506 {
6507
6508 Teuchos::Array<SC> value11( 1, 0. );
6509 Teuchos::Array<SC> value12( 1, 0. );
6510 Teuchos::Array<SC> value13( 1, 0. );
6511 Teuchos::Array<SC> value21( 1, 0. );
6512 Teuchos::Array<SC> value22( 1, 0. );
6513 Teuchos::Array<SC> value23( 1, 0. );
6514 Teuchos::Array<SC> value31( 1, 0. );
6515 Teuchos::Array<SC> value32( 1, 0. );
6516 Teuchos::Array<SC> value33( 1, 0. );
6517 Teuchos::Array<GO> indices( 1, 0 );
6518
6519 for (int j = 0; j < dPhi->at(0).size(); j++)
6520 {
6521 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;
6522 for (int k = 0; k < dPhi->size(); k++)
6523 {
6524
6525 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
6526
6527 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
6528 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
6529 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
6530
6531
6532 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
6533
6534 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
6535 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
6536 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
6537
6538 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
6539 epsilonValuesMat1_i.trace(res_trace_i);
6540 epsilonValuesMat1_j.trace(res_trace_j);
6541 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6542
6543 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
6544 epsilonValuesMat1_i.trace(res_trace_i);
6545 epsilonValuesMat2_j.trace(res_trace_j);
6546 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6547
6548 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
6549 epsilonValuesMat1_i.trace(res_trace_i);
6550 epsilonValuesMat3_j.trace(res_trace_j);
6551 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6552
6553 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
6554 epsilonValuesMat2_i.trace(res_trace_i);
6555 epsilonValuesMat1_j.trace(res_trace_j);
6556 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6557
6558 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
6559 epsilonValuesMat2_i.trace(res_trace_i);
6560 epsilonValuesMat2_j.trace(res_trace_j);
6561 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6562
6563 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
6564 epsilonValuesMat2_i.trace(res_trace_i);
6565 epsilonValuesMat3_j.trace(res_trace_j);
6566 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6567
6568 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
6569 epsilonValuesMat3_i.trace(res_trace_i);
6570 epsilonValuesMat1_j.trace(res_trace_j);
6571 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6572
6573 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
6574 epsilonValuesMat3_i.trace(res_trace_i);
6575 epsilonValuesMat2_j.trace(res_trace_j);
6576 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6577
6578 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
6579 epsilonValuesMat3_i.trace(res_trace_i);
6580 epsilonValuesMat3_j.trace(res_trace_j);
6581 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
6582
6583 }
6584 v11 = absDetB * v11;
6585 v12 = absDetB * v12;
6586 v13 = absDetB * v13;
6587 v21 = absDetB * v21;
6588 v22 = absDetB * v22;
6589 v23 = absDetB * v23;
6590 v31 = absDetB * v31;
6591 v32 = absDetB * v32;
6592 v33 = absDetB * v33;
6593
6594 value11[0] = v11;
6595 value12[0] = v12;
6596 value13[0] = v13;
6597 value21[0] = v21;
6598 value22[0] = v22;
6599 value23[0] = v23;
6600 value31[0] = v31;
6601 value32[0] = v32;
6602 value33[0] = v33;
6603
6604 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6605 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6606 indices[0] = glob_j;
6607 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
6608 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6609 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
6610 glob_j++;
6611 indices[0] = glob_j;
6612 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
6613 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6614 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
6615 glob_j++;
6616 indices[0] = glob_j;
6617 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
6618 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
6619 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
6620 }
6621 }
6622 }
6623 if (callFillComplete)
6624 {
6625 A->fillComplete();
6626 }
6627 }
6628}
6629
6631template <class SC, class LO, class GO, class NO>
6633 std::string FEType,
6634 MatrixPtr_Type &A,
6635 MultiVectorPtr_Type w,
6636 bool callFillComplete)
6637{
6638
6639 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
6640 int FEloc = this->checkFE(dim,FEType);
6641
6642 DomainConstPtr_Type domain = domainVec_.at(FEloc);
6643 ElementsPtr_Type elements = domain->getElementsC();
6644 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
6645 MapConstPtr_Type map = domain->getMapRepeated();
6646
6647 vec3D_dbl_ptr_Type dPhi;
6648 vec2D_dbl_ptr_Type phi;
6649 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6650 vec2D_dbl_ptr_Type quadPts;
6651
6652 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); // Fuer diskretes (\grad \cdot w) in den Gausspuntken
6653 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
6654
6655 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
6656 Helper::getPhi(phi, weights, dim, FEType, deg);
6657 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType);
6658
6659 // SC = double, GO = long, UN = int
6660 SC detB;
6661 SC absDetB;
6662 SmallMatrix<SC> B(dim);
6663 SmallMatrix<SC> Binv(dim);
6664 GO glob_i, glob_j;
6665
6666 // Der nichtlineare Teil als Array
6667 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
6668
6669 if (dim == 2)
6670 {
6671 double val;
6672 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
6673
6674 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
6675 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
6676 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
6677
6678 for (int T = 0; T < elements->numberElements(); T++)
6679 {
6680 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6681 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6682 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6683
6684 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
6685 detB = B.computeInverse(Binv);
6686 absDetB = std::fabs(detB);
6687
6688 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6689 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
6690 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
6691
6692 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 berechnen,
6693 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
6694 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
6695 {
6696 w11[0][k] = 0.0;
6697 w22[0][k] = 0.0;
6698 for(int i = 0; i < dPhiTrans[0].size(); i++)
6699 {
6700 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
6701 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
6702 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
6703 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
6704
6705 // TEST
6706 // LO indexTest1 = dim * i + 0;
6707 // LO indexTest2 = dim * i + 1;
6708 // w11[0][k] += wTest[indexTest1] * dPhiTrans[k][i][0];
6709 // w22[0][k] += wTest[indexTest2] * dPhiTrans[k][i][1];
6710 }
6711 }
6712
6713 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
6714 {
6715 divergenz[0][k] = w11[0][k] + w22[0][k];
6716 // if(T == 0)
6717 // {
6718 // std::cout << "k: " << k << " Divergenz: " << divergenz[0][k] << '\n';
6719 // }
6720 }
6721
6722
6723 for (int i = 0; i < dPhi->at(0).size(); i++)
6724 {
6725 Teuchos::Array<SC> value( 1, 0. );
6726 Teuchos::Array<GO> indices( 1, 0 );
6727
6728 for (int j = 0; j < dPhi->at(0).size(); j++)
6729 {
6730 val = 0.0;
6731 for (int k = 0; k < dPhi->size(); k++)
6732 {
6733 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
6734 }
6735 val = absDetB * val;
6736 value[0] = val;
6737
6738 // if(T == 0)
6739 // {
6740 // std::cout << "i: " << i << " j: " << j << " val: " << val << '\n';
6741 // }
6742
6743 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6744 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6745 indices[0] = glob_j;
6746
6747 A->insertGlobalValues(glob_i, indices(), value());
6748 glob_j++;
6749 indices[0] = glob_j;
6750 A->insertGlobalValues(glob_i+1, indices(), value());
6751 }
6752 }
6753 }
6754 if (callFillComplete)
6755 {
6756 A->fillComplete();
6757 }
6758 }
6759 else if(dim == 3)
6760 {
6761 double val;
6762
6763 // long long glob_i, glob_j;
6764 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6765
6766 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
6767 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
6768 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
6769 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
6770
6771 for (int T = 0; T < elements->numberElements(); T++)
6772 {
6773 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6774 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6775 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6776 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6777
6778 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
6779 detB = B.computeInverse(Binv);
6780 absDetB = std::fabs(detB);
6781
6782 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6783 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
6784 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
6785
6786 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 + w33 berechnen,
6787 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
6788 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
6789 {
6790 w11[0][k] = 0.0;
6791 w22[0][k] = 0.0;
6792 w33[0][k] = 0.0;
6793 for(int i = 0; i < dPhiTrans[0].size(); i++)
6794 {
6795 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
6796 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
6797 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
6798 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
6799 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
6800 w33[0][k] += wArray[index3] * dPhiTrans[k][i][2];
6801 }
6802 }
6803
6804 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
6805 {
6806 divergenz[0][k] = w11[0][k] + w22[0][k] + w33[0][k];
6807 }
6808
6809 for (int i = 0; i < dPhi->at(0).size(); i++)
6810 {
6811 Teuchos::Array<SC> value( 1, 0. );
6812 Teuchos::Array<GO> indices( 1, 0 );
6813
6814 for (int j = 0; j < dPhi->at(0).size(); j++)
6815 {
6816 val = 0.0;
6817 for (int k = 0; k < dPhi->size(); k++)
6818 {
6819 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
6820 }
6821 val = absDetB * val;
6822 value[0] = val;
6823
6824 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6825 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6826 indices[0] = glob_j;
6827 A->insertGlobalValues(glob_i, indices(), value());
6828 glob_j++;
6829 indices[0] = glob_j;
6830 A->insertGlobalValues(glob_i+1, indices(), value());
6831 glob_j++;
6832 indices[0] = glob_j;
6833 A->insertGlobalValues(glob_i+2, indices(), value());
6834
6835 }
6836 }
6837 }
6838 if (callFillComplete)
6839 {
6840 A->fillComplete();
6841 }
6842 }
6843}
6844
6845template <class SC, class LO, class GO, class NO>
6846void FE<SC,LO,GO,NO>::assemblyDummyCoupling(int dim,
6847 std::string FEType,
6848 MatrixPtr_Type &C,
6849 int FEloc, // 0 = Fluid, 2 = Struktur
6850 bool callFillComplete)
6851{
6852 DomainConstPtr_Type domain = domainVec_.at(FEloc);
6853
6854 MapConstPtr_Type mapInterfaceVecField = domain->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
6855 MapConstPtr_Type mapGlobalInterfaceVecField = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
6856
6857 MapConstPtr_Type mapFieldPartial = domain->getGlobalInterfaceMapVecFieldPartial();
6858
6859 Teuchos::Array<SC> value( 1, 0. );
6860 value[0] = 1.0; // da Einheitsmatrix
6861 Teuchos::Array<GO> indices( 1, 0 );
6862
6863 GO dofGlobal, dofLocal;
6864
6865 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
6866 {
6867 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
6868 if ( mapFieldPartial->getLocalElement( dofGlobal ) == Teuchos::OrdinalTraits<LO>::invalid() ) {
6869 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
6870 dofGlobal = mapInterfaceVecField->getGlobalElement( k );
6871 indices[0] = dofGlobal;
6872 C->insertGlobalValues(dofGlobal, indices(), value());
6873 }
6874 }
6875
6876 if (callFillComplete)
6877 C->fillComplete(mapInterfaceVecField, mapInterfaceVecField);
6878
6879}
6880
6881template <class SC, class LO, class GO, class NO>
6882void FE<SC,LO,GO,NO>::assemblyFSICoupling(int dim,
6883 std::string FEType,
6884 MatrixPtr_Type &C,
6885 MatrixPtr_Type &C_T,
6886 int FEloc1, // 0 = Fluid, 2 = Struktur
6887 int FEloc2, // 0 = Fluid, 2 = Struktur
6888 MapConstPtr_Type map1, // DomainMap: InterfaceMapVecFieldUnique = Spalten von C_T
6889 MapConstPtr_Type map2, // RangeMap: this->getDomain(0)->getMapVecFieldUnique() = Zeilen von C_T
6890 bool callFillComplete)
6891{
6892 // int FEloc = this->checkFE(dim,FEType);
6893
6894 DomainConstPtr_Type domain1 = domainVec_.at(FEloc1);
6895
6896 MapConstPtr_Type mapInterfaceVecField = domain1->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
6897
6898 MapConstPtr_Type mapGlobalInterfaceVecField;
6899 MapConstPtr_Type mapFieldPartial;
6900 if (FEloc1!=FEloc2){
6901 mapFieldPartial = domain1->getOtherGlobalInterfaceMapVecFieldPartial();
6902 mapGlobalInterfaceVecField = domain1->getOtherGlobalInterfaceMapVecFieldUnique();
6903 }
6904 else{
6905 mapFieldPartial = domain1->getGlobalInterfaceMapVecFieldPartial();
6906 mapGlobalInterfaceVecField = domain1->getGlobalInterfaceMapVecFieldUnique();
6907 }
6908
6909 Teuchos::Array<SC> value( 1, 0. );
6910 value[0] = 1.0; // da Einheitsmatrix
6911 Teuchos::Array<GO> indices( 1, 0 );
6912
6913 GO dofGlobal, dofLocal;
6914 if (mapFieldPartial.is_null()) {
6915 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
6916 {
6917 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
6918 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
6919 dofLocal = mapInterfaceVecField->getGlobalElement(k);
6920
6921 indices[0] = dofLocal;
6922 C_T->insertGlobalValues(dofGlobal, indices(), value());
6923 indices[0] = dofGlobal;
6924 C->insertGlobalValues(dofLocal, indices(), value());
6925
6926 }
6927 }
6928 else{
6929 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++) {
6930 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
6931 if ( mapFieldPartial->getLocalElement( dofGlobal ) != Teuchos::OrdinalTraits<LO>::invalid() ) {
6932
6933 dofLocal = mapInterfaceVecField->getGlobalElement(k);
6934
6935 indices[0] = dofLocal;
6936 C_T->insertGlobalValues(dofGlobal, indices(), value());
6937 indices[0] = dofGlobal;
6938 C->insertGlobalValues(dofLocal, indices(), value());
6939 }
6940 }
6941 }
6942
6943 if (callFillComplete)
6944 {
6945 // Erstes Argument: Domain (=Spalten von C_T)
6946 // Zweites Arguement: Range (=Zeilen von C_T)
6947 C_T->fillComplete(map1, map2);
6948 C->fillComplete(map2, map1);
6949 }
6950}
6951
6952
6953template <class SC, class LO, class GO, class NO>
6954void FE<SC,LO,GO,NO>::assemblyGeometryCoupling(int dim,
6955 std::string FEType,
6956 MatrixPtr_Type &C,
6957 int FEloc, // 0 = Fluid, 2 = Struktur, 4 = 0 = Geometrie
6958 MapConstPtr_Type map1, // Fluid-Interface-Map
6959 MapConstPtr_Type map2, // DomainMap: this->getDomain(2)->getMapVecFieldUnique() = Spalten von C
6960 MapConstPtr_Type map3, // RangeMap: this->getDomain(4)->getMapVecFieldUnique() = Zeilen von C
6961 bool callFillComplete)
6962{
6963
6964 DomainConstPtr_Type domain = domainVec_.at(FEloc);
6965
6966 MapConstPtr_Type mapInt = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
6967 MapConstPtr_Type mapOtherInt = domain->getOtherGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung von other. For FELoc=0 or =4, otherInterface has solid dofs
6968 MapConstPtr_Type mapPartInt = domain->getGlobalInterfaceMapVecFieldPartial();
6969 MapConstPtr_Type mapOtherPartInt = domain->getOtherGlobalInterfaceMapVecFieldPartial();
6970 Teuchos::Array<SC> value( 1, 0. );
6971 value[0] = 1.0; // da Einheitsmatrix
6972 Teuchos::Array<GO> indices( 1, 0 );
6973
6974 GO dofRow;
6975 if (mapPartInt.is_null()) {
6976 for(int k = 0; k < mapInt->getNodeNumElements(); k++){
6977 dofRow = mapInt->getGlobalElement(k);
6978 indices[0] = mapOtherInt->getGlobalElement(k);
6979 C->insertGlobalValues(dofRow, indices(), value());
6980 }
6981 }
6982 else{
6983 for(int k = 0; k < mapPartInt->getNodeNumElements(); k++){
6984 dofRow = mapPartInt->getGlobalElement(k);
6985 indices[0] = mapOtherPartInt->getGlobalElement(k);
6986 C->insertGlobalValues(dofRow, indices(), value());
6987 }
6988 }
6989 if (callFillComplete)
6990 {
6991 // (Domain, Range)
6992 C->fillComplete(map2, map3);
6993 }
6994}
6995
6996
6997template <class SC, class LO, class GO, class NO>
6998void FE<SC,LO,GO,NO>::assemblyShapeDerivativeVelocity(int dim,
6999 std::string FEType1, // P2
7000 std::string FEType2, // P1
7001 MatrixPtr_Type &D,
7002 int FEloc, // 0 = Fluid (Velocity)
7003 MultiVectorPtr_Type u, // Geschwindigkeit
7004 MultiVectorPtr_Type w, // Beschleunigung Gitter
7005 MultiVectorPtr_Type p, // Druck
7006 double dt, // Zeitschrittweite
7007 double rho, // Dichte vom Fluid
7008 double nu, // Viskositaet vom Fluid
7009 bool callFillComplete)
7010{
7011 // int FEloc = this->checkFE(dim,FEType1);
7012
7013 DomainConstPtr_Type domain = domainVec_.at(FEloc);
7014 ElementsPtr_Type elements = domain->getElementsC();
7015 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
7016 MapConstPtr_Type map = domain->getMapRepeated();
7017
7018 vec3D_dbl_ptr_Type dPhiU;
7019 vec2D_dbl_ptr_Type phiU;
7020 vec2D_dbl_ptr_Type phiP;
7021 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7022 vec2D_dbl_ptr_Type quadPts;
7023
7024 // Hoechste Quadraturordnung angeben (= Zusaetzlicher Term wg. non-conservativ); bei P2/P1 hier Ordnung 6
7025 UN extraDeg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv1);
7026 UN deg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv0) + extraDeg;
7027
7028 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
7029 Helper::getPhi(phiU, weights, dim, FEType1, deg);
7030 Helper::getPhi(phiP, weights, dim, FEType2, deg);
7031 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType1);
7032
7033 // SC = double, GO = long, UN = int
7034 SC detB;
7035 SC absDetB;
7036 SmallMatrix<SC> B(dim);
7037 SmallMatrix<SC> Binv(dim);
7038 GO glob_i, glob_j;
7039
7040 // Der nichtlineare Teil als Array
7041 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
7042 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
7043 Teuchos::ArrayRCP< const SC > pArray = p->getData(0);
7044
7045 if (dim == 2)
7046 {
7047 double val11, val12, val21, val22;
7048 double valDK1_11, valDK1_12, valDK1_21, valDK1_22;
7049 double valDK2_11, valDK2_12, valDK2_21, valDK2_22;
7050 double valDN_11, valDN_12, valDN_21, valDN_22;
7051 double valDW_11, valDW_12, valDW_21, valDW_22;
7052 double valDP_11, valDP_12, valDP_21, valDP_22;
7053 double valDM_11, valDM_12, valDM_21, valDM_22;
7054 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
7055
7056 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
7057 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
7058 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
7059 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
7060 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
7061 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
7062 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
7063 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
7064 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
7065 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
7066 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
7067 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
7068 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
7069 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
7070 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
7071 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
7072 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
7073 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
7074 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
7075 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
7076
7077 for (int T = 0; T < elements->numberElements(); T++)
7078 {
7079 p1 = pointsRep->at(elements->getElement(T).getNode(0));
7080 p2 = pointsRep->at(elements->getElement(T).getNode(1));
7081 p3 = pointsRep->at(elements->getElement(T).getNode(2));
7082
7083 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
7084 detB = B.computeInverse(Binv);
7085 absDetB = std::fabs(detB);
7086
7087 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
7088 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
7089 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
7090
7091 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
7092 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
7093 {
7094 u1Loc[0][k] = 0.0;
7095 u2Loc[0][k] = 0.0;
7096 w1Loc[0][k] = 0.0;
7097 w2Loc[0][k] = 0.0;
7098 for(int i = 0; i < phiU->at(0).size(); i++)
7099 {
7100 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
7101 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
7102 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
7103 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
7104 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
7105 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
7106
7107 }
7108 }
7109
7110 // Diskreten Vektor p berechnen
7111 // Beachte: phiP->size() = phiU->size()
7112 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
7113 {
7114 pLoc[0][k] = 0.0;
7115 for(int i = 0; i < phiP->at(0).size(); i++)
7116 {
7117 // Die ersten Eintraege in der Elementliste sind P1
7118 // Alternativ elements2 holen
7119 LO index = elements->getElement(T).getNode(i) + 0;
7120 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
7121
7122 }
7123 }
7124
7125 // Diskrete Grad-Vektoren berechnen,
7126 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
7127 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
7128 {
7129 u11[0][k] = 0.0;
7130 u12[0][k] = 0.0;
7131 u21[0][k] = 0.0;
7132 u22[0][k] = 0.0;
7133 w11[0][k] = 0.0;
7134 w12[0][k] = 0.0;
7135 w21[0][k] = 0.0;
7136 w22[0][k] = 0.0;
7137 for(int i = 0; i < dPhiTransU[0].size(); i++)
7138 {
7139 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
7140 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
7141 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
7142 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
7143 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
7144 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
7145 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
7146 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
7147 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
7148 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
7149
7150 }
7151 }
7152
7153 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
7154 // Beachte: phiP->size() = phiU->size()
7155 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
7156 {
7157 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
7158 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
7159 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
7160 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
7161 }
7162
7163
7164 for (int i = 0; i < dPhiU->at(0).size(); i++)
7165 {
7166 Teuchos::Array<SC> value11( 1, 0. ); // x-x
7167 Teuchos::Array<SC> value12( 1, 0. ); // x-y
7168 Teuchos::Array<SC> value21( 1, 0. ); // y-x
7169 Teuchos::Array<SC> value22( 1, 0. ); // y-y
7170 Teuchos::Array<GO> indices( 1, 0 );
7171
7172 for (int j = 0; j < dPhiU->at(0).size(); j++)
7173 {
7174 // DK1
7175 valDK1_11 = 0.0;
7176 valDK1_12 = 0.0;
7177 valDK1_21 = 0.0;
7178 valDK1_22 = 0.0;
7179
7180 // DK2
7181 valDK2_11 = 0.0;
7182 valDK2_12 = 0.0;
7183 valDK2_21 = 0.0;
7184 valDK2_22 = 0.0;
7185
7186 // DN
7187 valDN_11 = 0.0;
7188 valDN_12 = 0.0;
7189 valDN_21 = 0.0;
7190 valDN_22 = 0.0;
7191
7192 // DW
7193 valDW_11 = 0.0;
7194 valDW_12 = 0.0;
7195 valDW_21 = 0.0;
7196 valDW_22 = 0.0;
7197
7198 // DP
7199 valDP_11 = 0.0;
7200 valDP_12 = 0.0;
7201 valDP_21 = 0.0;
7202 valDP_22 = 0.0;
7203
7204 // DM
7205 valDM_11 = 0.0;
7206 valDM_12 = 0.0;
7207 valDM_21 = 0.0;
7208 valDM_22 = 0.0;
7209
7210 for (int k = 0; k < dPhiU->size(); k++)
7211 {
7212 // DK1
7213 valDK1_11 = valDK1_11 + weights->at(k) *
7214 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7215 u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
7216 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
7217 valDK1_12 = valDK1_12 + weights->at(k) *
7218 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7219 u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
7220 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
7221 valDK1_21 = valDK1_21 + weights->at(k) *
7222 ( u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7223 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7224 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
7225 valDK1_22 = valDK1_22 + weights->at(k) *
7226 ( u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7227 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7228 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
7229
7230 // DK2
7231 valDK2_11 = valDK2_11 + weights->at(k) *
7232 ( -sigma12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7233 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
7234 valDK2_12 = valDK2_12 + weights->at(k) *
7235 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7236 -sigma11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
7237 valDK2_21 = valDK2_21 + weights->at(k) *
7238 ( -sigma22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7239 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
7240 valDK2_22 = valDK2_22 + weights->at(k) *
7241 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7242 -sigma21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
7243
7244 // DN
7245 valDN_11 = valDN_11 + weights->at(k) *
7246 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) +
7247 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
7248 valDN_12 = valDN_12 + weights->at(k) *
7249 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) -
7250 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
7251 valDN_21 = valDN_21 + weights->at(k) *
7252 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) +
7253 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
7254 valDN_22 = valDN_22 + weights->at(k) *
7255 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) -
7256 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
7257
7258 // DW
7259 valDW_11 = valDW_11 + weights->at(k) *
7260 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7261 valDW_12 = valDW_12 + weights->at(k) *
7262 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7263 valDW_21 = valDW_21 + weights->at(k) *
7264 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7265 valDW_22 = valDW_22 + weights->at(k) *
7266 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7267
7268 // DP
7269 valDP_11 = valDP_11 + weights->at(k) *
7270 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
7271 valDP_12 = valDP_12 + weights->at(k) *
7272 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
7273 valDP_21 = valDP_21 + weights->at(k) *
7274 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
7275 valDP_22 = valDP_22 + weights->at(k) *
7276 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
7277
7278 // DM
7279 valDM_11 = valDM_11 + weights->at(k) *
7280 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
7281 valDM_12 = valDM_12 + weights->at(k) *
7282 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
7283 valDM_21 = valDM_21 + weights->at(k) *
7284 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
7285 valDM_22 = valDM_22 + weights->at(k) *
7286 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
7287 }
7288
7289 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;
7290 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;
7291 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;
7292 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;
7293
7294 val11 = absDetB * val11;
7295 val12 = absDetB * val12;
7296 val21 = absDetB * val21;
7297 val22 = absDetB * val22;
7298
7299 value11[0] = val11; // x-x
7300 value12[0] = val12; // x-y
7301 value21[0] = val21; // y-x
7302 value22[0] = val22; // y-y
7303
7304 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
7305 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
7306 indices[0] = glob_j;
7307
7308 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
7309 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
7310 glob_j++;
7311 indices[0] = glob_j;
7312 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
7313 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
7314 }
7315 }
7316 }
7317 if (callFillComplete)
7318 {
7319 D->fillComplete();
7320 }
7321 }
7322 else if(dim == 3)
7323 {
7324 double val11, val12, val13, val21, val22, val23, val31, val32, val33;
7325 double valDK1_11, valDK1_12, valDK1_13, valDK1_21, valDK1_22, valDK1_23, valDK1_31, valDK1_32, valDK1_33;
7326 double valDK2_11, valDK2_12, valDK2_13, valDK2_21, valDK2_22, valDK2_23, valDK2_31, valDK2_32, valDK2_33;
7327 double valDN_11, valDN_12, valDN_13, valDN_21, valDN_22, valDN_23, valDN_31, valDN_32, valDN_33;
7328 double valDW_11, valDW_12, valDW_13, valDW_21, valDW_22, valDW_23, valDW_31, valDW_32, valDW_33;
7329 double valDP_11, valDP_12, valDP_13, valDP_21, valDP_22, valDP_23, valDP_31, valDP_32, valDP_33;
7330 double valDM_11, valDM_12, valDM_13, valDM_21, valDM_22, valDM_23, valDM_31, valDM_32, valDM_33;
7331 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
7332
7333 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
7334 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
7335 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
7336 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
7337 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
7338 vec2D_dbl_Type u3Loc(1, vec_dbl_Type(weights->size(), -1.));
7339 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
7340 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
7341 vec2D_dbl_Type w3Loc(1, vec_dbl_Type(weights->size(), -1.));
7342 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
7343 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
7344 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
7345 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
7346 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
7347 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
7348 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
7349 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
7350 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
7351 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
7352 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
7353 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
7354 vec2D_dbl_Type w13(1, vec_dbl_Type(weights->size(), -1.));
7355 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
7356 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
7357 vec2D_dbl_Type w23(1, vec_dbl_Type(weights->size(), -1.));
7358 vec2D_dbl_Type w31(1, vec_dbl_Type(weights->size(), -1.));
7359 vec2D_dbl_Type w32(1, vec_dbl_Type(weights->size(), -1.));
7360 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
7361 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
7362 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
7363 vec2D_dbl_Type sigma13(1, vec_dbl_Type(weights->size(), -1.));
7364 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
7365 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
7366 vec2D_dbl_Type sigma23(1, vec_dbl_Type(weights->size(), -1.));
7367 vec2D_dbl_Type sigma31(1, vec_dbl_Type(weights->size(), -1.));
7368 vec2D_dbl_Type sigma32(1, vec_dbl_Type(weights->size(), -1.));
7369 vec2D_dbl_Type sigma33(1, vec_dbl_Type(weights->size(), -1.));
7370
7371 for (int T = 0; T < elements->numberElements(); T++)
7372 {
7373 p1 = pointsRep->at(elements->getElement(T).getNode(0));
7374 p2 = pointsRep->at(elements->getElement(T).getNode(1));
7375 p3 = pointsRep->at(elements->getElement(T).getNode(2));
7376 p4 = pointsRep->at(elements->getElement(T).getNode(3));
7377
7378 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
7379 detB = B.computeInverse(Binv);
7380 absDetB = std::fabs(detB);
7381
7382 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
7383 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
7384 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
7385
7386 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
7387 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
7388 {
7389 u1Loc[0][k] = 0.0;
7390 u2Loc[0][k] = 0.0;
7391 u3Loc[0][k] = 0.0;
7392 w1Loc[0][k] = 0.0;
7393 w2Loc[0][k] = 0.0;
7394 w3Loc[0][k] = 0.0;
7395 for(int i = 0; i < phiU->at(0).size(); i++)
7396 {
7397 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
7398 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
7399 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
7400 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
7401 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
7402 u3Loc[0][k] += uArray[index3] * phiU->at(k).at(i);
7403 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
7404 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
7405 w3Loc[0][k] += wArray[index3] * phiU->at(k).at(i);
7406 }
7407 }
7408
7409 // Diskreten Vektor p berechnen
7410 // Beachte: phiP->size() = phiU->size()
7411 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
7412 {
7413 pLoc[0][k] = 0.0;
7414 for(int i = 0; i < phiP->at(0).size(); i++)
7415 {
7416 // Die ersten Eintraege in der Elementliste sind P1
7417 LO index = elements->getElement(T).getNode(i) + 0;
7418 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
7419 }
7420 }
7421
7422 // Diskrete Grad-Vektoren berechnen,
7423 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
7424 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
7425 {
7426 u11[0][k] = 0.0;
7427 u12[0][k] = 0.0;
7428 u13[0][k] = 0.0;
7429 u21[0][k] = 0.0;
7430 u22[0][k] = 0.0;
7431 u23[0][k] = 0.0;
7432 u31[0][k] = 0.0;
7433 u32[0][k] = 0.0;
7434 u33[0][k] = 0.0;
7435 w11[0][k] = 0.0;
7436 w12[0][k] = 0.0;
7437 w13[0][k] = 0.0;
7438 w21[0][k] = 0.0;
7439 w22[0][k] = 0.0;
7440 w23[0][k] = 0.0;
7441 w31[0][k] = 0.0;
7442 w32[0][k] = 0.0;
7443 w33[0][k] = 0.0;
7444 for(int i = 0; i < dPhiTransU[0].size(); i++)
7445 {
7446 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
7447 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
7448 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
7449 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
7450 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
7451 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
7452 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
7453 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
7454 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
7455 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
7456 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
7457 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
7458 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
7459 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
7460 w13[0][k] += wArray[index1] * dPhiTransU[k][i][2];
7461 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
7462 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
7463 w23[0][k] += wArray[index2] * dPhiTransU[k][i][2];
7464 w31[0][k] += wArray[index3] * dPhiTransU[k][i][0];
7465 w32[0][k] += wArray[index3] * dPhiTransU[k][i][1];
7466 w33[0][k] += wArray[index3] * dPhiTransU[k][i][2];
7467 }
7468 }
7469
7470 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
7471 // Beachte: phiP->size() = phiU->size()
7472 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
7473 {
7474 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
7475 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
7476 sigma13[0][k] = rho * nu * (u13[0][k] + u31[0][k]);
7477 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
7478 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
7479 sigma23[0][k] = rho * nu * (u23[0][k] + u32[0][k]);
7480 sigma31[0][k] = rho * nu * (u31[0][k] + u13[0][k]);
7481 sigma32[0][k] = rho * nu * (u32[0][k] + u23[0][k]);
7482 sigma33[0][k] = rho * nu * (u33[0][k] + u33[0][k]) - pLoc[0][k];
7483 }
7484
7485
7486 for (int i = 0; i < dPhiU->at(0).size(); i++)
7487 {
7488 Teuchos::Array<SC> value11( 1, 0. ); // x-x
7489 Teuchos::Array<SC> value12( 1, 0. ); // x-y
7490 Teuchos::Array<SC> value13( 1, 0. ); // x-z
7491 Teuchos::Array<SC> value21( 1, 0. ); // y-x
7492 Teuchos::Array<SC> value22( 1, 0. ); // y-y
7493 Teuchos::Array<SC> value23( 1, 0. ); // y-z
7494 Teuchos::Array<SC> value31( 1, 0. ); // z-x
7495 Teuchos::Array<SC> value32( 1, 0. ); // z-y
7496 Teuchos::Array<SC> value33( 1, 0. ); // z-z
7497 Teuchos::Array<GO> indices( 1, 0 );
7498
7499 for (int j = 0; j < dPhiU->at(0).size(); j++)
7500 {
7501 // DK1
7502 valDK1_11 = 0.0;
7503 valDK1_12 = 0.0;
7504 valDK1_13 = 0.0;
7505 valDK1_21 = 0.0;
7506 valDK1_22 = 0.0;
7507 valDK1_23 = 0.0;
7508 valDK1_31 = 0.0;
7509 valDK1_32 = 0.0;
7510 valDK1_33 = 0.0;
7511
7512 // DK2
7513 valDK2_11 = 0.0;
7514 valDK2_12 = 0.0;
7515 valDK2_13 = 0.0;
7516 valDK2_21 = 0.0;
7517 valDK2_22 = 0.0;
7518 valDK2_23 = 0.0;
7519 valDK2_31 = 0.0;
7520 valDK2_32 = 0.0;
7521 valDK2_33 = 0.0;
7522
7523 // DN
7524 valDN_11 = 0.0;
7525 valDN_12 = 0.0;
7526 valDN_13 = 0.0;
7527 valDN_21 = 0.0;
7528 valDN_22 = 0.0;
7529 valDN_23 = 0.0;
7530 valDN_31 = 0.0;
7531 valDN_32 = 0.0;
7532 valDN_33 = 0.0;
7533
7534 // DW
7535 valDW_11 = 0.0;
7536 valDW_12 = 0.0;
7537 valDW_13 = 0.0;
7538 valDW_21 = 0.0;
7539 valDW_22 = 0.0;
7540 valDW_23 = 0.0;
7541 valDW_31 = 0.0;
7542 valDW_32 = 0.0;
7543 valDW_33 = 0.0;
7544
7545 // DP
7546 valDP_11 = 0.0;
7547 valDP_12 = 0.0;
7548 valDP_13 = 0.0;
7549 valDP_21 = 0.0;
7550 valDP_22 = 0.0;
7551 valDP_23 = 0.0;
7552 valDP_31 = 0.0;
7553 valDP_32 = 0.0;
7554 valDP_33 = 0.0;
7555
7556 // DM
7557 valDM_11 = 0.0;
7558 valDM_12 = 0.0;
7559 valDM_13 = 0.0;
7560 valDM_21 = 0.0;
7561 valDM_22 = 0.0;
7562 valDM_23 = 0.0;
7563 valDM_31 = 0.0;
7564 valDM_32 = 0.0;
7565 valDM_33 = 0.0;
7566
7567 for (int k = 0; k < dPhiU->size(); k++)
7568 {
7569 // DK1
7570 valDK1_11 = valDK1_11 + weights->at(k) *
7571 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7572 ( u11[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
7573 ( u11[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
7574 valDK1_12 = valDK1_12 + weights->at(k) *
7575 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7576 ( u12[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
7577 ( u12[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
7578 valDK1_13 = valDK1_13 + weights->at(k) *
7579 ( 2 * u13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
7580 ( u13[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
7581 ( u13[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
7582 valDK1_21 = valDK1_21 + weights->at(k) *
7583 ( ( u21[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
7584 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
7585 ( u21[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
7586 valDK1_22 = valDK1_22 + weights->at(k) *
7587 ( ( u22[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
7588 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
7589 ( u22[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
7590 valDK1_23 = valDK1_23 + weights->at(k) *
7591 ( ( u23[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
7592 2 * u23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
7593 ( u23[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
7594 valDK1_31 = valDK1_31 + weights->at(k) *
7595 ( ( u31[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
7596 ( u31[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
7597 2 * u31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
7598 valDK1_32 = valDK1_32 + weights->at(k) *
7599 ( ( u32[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
7600 ( u32[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
7601 2 * u32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
7602 valDK1_33 = valDK1_33 + weights->at(k) *
7603 ( ( u33[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
7604 ( u33[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
7605 2 * u33[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
7606
7607 // DK2
7608 valDK2_11 = valDK2_11 + weights->at(k) *
7609 ( ( -sigma12[0][k] * dPhiTransU[k][j][1] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
7610 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
7611 sigma13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
7612 valDK2_12 = valDK2_12 + weights->at(k) *
7613 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7614 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
7615 sigma13[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
7616 valDK2_13 = valDK2_13 + weights->at(k) *
7617 ( sigma11[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
7618 sigma12[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
7619 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
7620 valDK2_21 = valDK2_21 + weights->at(k) *
7621 ( ( -sigma22[0][k] * dPhiTransU[k][j][1] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
7622 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
7623 sigma23[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
7624 valDK2_22 = valDK2_22 + weights->at(k) *
7625 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7626 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
7627 sigma23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
7628 valDK2_23 = valDK2_23 + weights->at(k) *
7629 ( sigma21[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
7630 sigma22[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
7631 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma22[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
7632 valDK2_31 = valDK2_31 + weights->at(k) *
7633 ( ( -sigma32[0][k] * dPhiTransU[k][j][1] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
7634 sigma32[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
7635 sigma33[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
7636 valDK2_32 = valDK2_32 + weights->at(k) *
7637 ( sigma31[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
7638 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
7639 sigma33[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
7640 valDK2_33 = valDK2_33 + weights->at(k) *
7641 ( sigma31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
7642 sigma32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
7643 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
7644
7645 // DN
7646 double ZN_11; // Die Z_i fuer das DN wie in der Masterarbeit definiert
7647 double ZN_12;
7648 double ZN_13;
7649 double ZN_21;
7650 double ZN_22;
7651 double ZN_23;
7652 double ZN_31;
7653 double ZN_32;
7654 double ZN_33;
7655 ZN_11 = - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
7656 ZN_12 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][0];
7657 ZN_13 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][0];
7658 ZN_21 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][1];
7659 ZN_22 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
7660 ZN_23 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][1];
7661 ZN_31 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][2];
7662 ZN_32 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][2];
7663 ZN_33 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1];
7664
7665 valDN_11 = valDN_11 + weights->at(k) *
7666 ( ZN_11 * u11[0][k] * phiU->at(k).at(i) +
7667 ZN_12 * u12[0][k] * phiU->at(k).at(i) +
7668 ZN_13 * u13[0][k] * phiU->at(k).at(i) );
7669 valDN_12 = valDN_12 + weights->at(k) *
7670 ( ZN_21 * u11[0][k] * phiU->at(k).at(i) +
7671 ZN_22 * u12[0][k] * phiU->at(k).at(i) +
7672 ZN_23 * u13[0][k] * phiU->at(k).at(i) );
7673 valDN_13 = valDN_13 + weights->at(k) *
7674 ( ZN_31 * u11[0][k] * phiU->at(k).at(i) +
7675 ZN_32 * u12[0][k] * phiU->at(k).at(i) +
7676 ZN_33 * u13[0][k] * phiU->at(k).at(i) );
7677 valDN_21 = valDN_21 + weights->at(k) *
7678 ( ZN_11 * u21[0][k] * phiU->at(k).at(i) +
7679 ZN_12 * u22[0][k] * phiU->at(k).at(i) +
7680 ZN_13 * u23[0][k] * phiU->at(k).at(i) );
7681 valDN_22 = valDN_22 + weights->at(k) *
7682 ( ZN_21 * u21[0][k] * phiU->at(k).at(i) +
7683 ZN_22 * u22[0][k] * phiU->at(k).at(i) +
7684 ZN_23 * u23[0][k] * phiU->at(k).at(i) );
7685 valDN_23 = valDN_23 + weights->at(k) *
7686 ( ZN_31 * u21[0][k] * phiU->at(k).at(i) +
7687 ZN_32 * u22[0][k] * phiU->at(k).at(i) +
7688 ZN_33 * u23[0][k] * phiU->at(k).at(i) );
7689 valDN_31 = valDN_31 + weights->at(k) *
7690 ( ZN_11 * u31[0][k] * phiU->at(k).at(i) +
7691 ZN_12 * u32[0][k] * phiU->at(k).at(i) +
7692 ZN_13 * u33[0][k] * phiU->at(k).at(i) );
7693 valDN_32 = valDN_32 + weights->at(k) *
7694 ( ZN_21 * u31[0][k] * phiU->at(k).at(i) +
7695 ZN_22 * u32[0][k] * phiU->at(k).at(i) +
7696 ZN_23 * u33[0][k] * phiU->at(k).at(i) );
7697 valDN_33 = valDN_33 + weights->at(k) *
7698 ( ZN_31 * u31[0][k] * phiU->at(k).at(i) +
7699 ZN_32 * u32[0][k] * phiU->at(k).at(i) +
7700 ZN_33 * u33[0][k] * phiU->at(k).at(i) );
7701
7702 // DW
7703 valDW_11 = valDW_11 + weights->at(k) *
7704 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7705 valDW_12 = valDW_12 + weights->at(k) *
7706 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7707 valDW_13 = valDW_13 + weights->at(k) *
7708 ( u13[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7709 valDW_21 = valDW_21 + weights->at(k) *
7710 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7711 valDW_22 = valDW_22 + weights->at(k) *
7712 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7713 valDW_23 = valDW_23 + weights->at(k) *
7714 ( u23[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7715 valDW_31 = valDW_31 + weights->at(k) *
7716 ( u31[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7717 valDW_32 = valDW_32 + weights->at(k) *
7718 ( u32[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7719 valDW_33 = valDW_33 + weights->at(k) *
7720 ( u33[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
7721
7722 // DP
7723 double ZP_1; // Die Z_i fuer das DP wie in der Masterarbeit definiert
7724 double ZP_2;
7725 double ZP_3;
7726 ZP_1 = -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] -
7727 w31[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][0];
7728 ZP_2 = w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] -
7729 w32[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][1];
7730 ZP_3 = w11[0][k] * dPhiTransU[k][j][2] - w13[0][k] * dPhiTransU[k][j][0] +
7731 w22[0][k] * dPhiTransU[k][j][2] - w23[0][k] * dPhiTransU[k][j][1];
7732
7733 valDP_11 = valDP_11 + weights->at(k) *
7734 ( ZP_1 * u1Loc[0][k] * phiU->at(k).at(i) );
7735 valDP_12 = valDP_12 + weights->at(k) *
7736 ( ZP_2 * u1Loc[0][k] * phiU->at(k).at(i) );
7737 valDP_13 = valDP_13 + weights->at(k) *
7738 ( ZP_3 * u1Loc[0][k] * phiU->at(k).at(i) );
7739 valDP_21 = valDP_21 + weights->at(k) *
7740 ( ZP_1 * u2Loc[0][k] * phiU->at(k).at(i) );
7741 valDP_22 = valDP_22 + weights->at(k) *
7742 ( ZP_2 * u2Loc[0][k] * phiU->at(k).at(i) );
7743 valDP_23 = valDP_23 + weights->at(k) *
7744 ( ZP_3 * u2Loc[0][k] * phiU->at(k).at(i) );
7745 valDP_31 = valDP_31 + weights->at(k) *
7746 ( ZP_1 * u3Loc[0][k] * phiU->at(k).at(i) );
7747 valDP_32 = valDP_32 + weights->at(k) *
7748 ( ZP_2 * u3Loc[0][k] * phiU->at(k).at(i) );
7749 valDP_33 = valDP_33 + weights->at(k) *
7750 ( ZP_3 * u3Loc[0][k] * phiU->at(k).at(i) );
7751
7752 // DM
7753 valDM_11 = valDM_11 + weights->at(k) *
7754 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
7755 valDM_12 = valDM_12 + weights->at(k) *
7756 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
7757 valDM_13 = valDM_13 + weights->at(k) *
7758 ( dPhiTransU[k][j][2] * u1Loc[0][k] * phiU->at(k).at(i) );
7759 valDM_21 = valDM_21 + weights->at(k) *
7760 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
7761 valDM_22 = valDM_22 + weights->at(k) *
7762 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
7763 valDM_23 = valDM_23 + weights->at(k) *
7764 ( dPhiTransU[k][j][2] * u2Loc[0][k] * phiU->at(k).at(i) );
7765 valDM_31 = valDM_31 + weights->at(k) *
7766 ( dPhiTransU[k][j][0] * u3Loc[0][k] * phiU->at(k).at(i) );
7767 valDM_32 = valDM_32 + weights->at(k) *
7768 ( dPhiTransU[k][j][1] * u3Loc[0][k] * phiU->at(k).at(i) );
7769 valDM_33 = valDM_33 + weights->at(k) *
7770 ( dPhiTransU[k][j][2] * u3Loc[0][k] * phiU->at(k).at(i) );
7771 }
7772
7773 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;
7774 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;
7775 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;
7776 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;
7777 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;
7778 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;
7779 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;
7780 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;
7781 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;
7782
7783 val11 = absDetB * val11;
7784 val12 = absDetB * val12;
7785 val13 = absDetB * val13;
7786 val21 = absDetB * val21;
7787 val22 = absDetB * val22;
7788 val23 = absDetB * val23;
7789 val31 = absDetB * val31;
7790 val32 = absDetB * val32;
7791 val33 = absDetB * val33;
7792
7793 value11[0] = val11; // x-x
7794 value12[0] = val12; // x-y
7795 value13[0] = val13; // x-z
7796 value21[0] = val21; // y-x
7797 value22[0] = val22; // y-y
7798 value23[0] = val23; // y-z
7799 value31[0] = val31; // z-x
7800 value32[0] = val32; // z-y
7801 value33[0] = val33; // z-z
7802
7803
7804 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
7805 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
7806 indices[0] = glob_j;
7807
7808 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
7809 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
7810 D->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
7811 glob_j++;
7812 indices[0] = glob_j;
7813 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
7814 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
7815 D->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
7816 glob_j++;
7817 indices[0] = glob_j;
7818 D->insertGlobalValues(glob_i, indices(), value13()); // x-z
7819 D->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
7820 D->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
7821 }
7822 }
7823 }
7824 if (callFillComplete)
7825 {
7826 D->fillComplete();
7827 }
7828 }
7829
7830}
7831
7832
7833template <class SC, class LO, class GO, class NO>
7834void FE<SC,LO,GO,NO>::assemblyShapeDerivativeDivergence(int dim,
7835 std::string FEType1,
7836 std::string FEType2,
7837 MatrixPtr_Type &DB,
7838 int FEloc1, // 1 = Fluid-Pressure
7839 int FEloc2, // 0 = Fluid-Velocity
7840 MapConstPtr_Type map1_unique, // Pressure-Map
7841 MapConstPtr_Type map2_unique, // Velocity-Map unique als VecField
7842 MultiVectorPtr_Type u, // Geschwindigkeit
7843 bool callFillComplete)
7844{
7845 DomainConstPtr_Type domain1 = domainVec_.at(FEloc1);
7846 ElementsPtr_Type elements = domain1->getElementsC();
7847 vec2D_dbl_ptr_Type pointsRep = domain1->getPointsRepeated();
7848 MapConstPtr_Type map1_rep = domain1->getMapRepeated();
7849
7850 // Fuer die Fluid-Velocity-Map
7851 DomainConstPtr_Type domain2 = domainVec_.at(FEloc2);
7852 MapConstPtr_Type map2_rep = domain2->getMapRepeated();
7853 ElementsPtr_Type elements2 = domain2->getElementsC();
7854
7855 vec3D_dbl_ptr_Type dPhiU;
7856 vec2D_dbl_ptr_Type phiU;
7857 vec2D_dbl_ptr_Type phiP;
7858 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7859 vec2D_dbl_ptr_Type quadPts;
7860
7861 UN extraDeg = Helper::determineDegree( dim, FEType1, Helper::Deriv1);
7862 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv0) + 2*extraDeg;
7863
7864
7865 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
7866 Helper::getPhi(phiU, weights, dim, FEType1, deg);
7867 Helper::getPhi(phiP, weights, dim, FEType2, deg);
7868 Helper::getQuadratureValues(dim, deg, quadPts, weights, FEType1);
7869
7870 // SC = double, GO = long, UN = int
7871 SC detB;
7872 SC absDetB;
7873 SmallMatrix<SC> B(dim);
7874 SmallMatrix<SC> Binv(dim);
7875 GO glob_i, glob_j;
7876
7877 // Der nichtlineare Teil als Array
7878 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
7879
7880 if (dim == 2)
7881 {
7882 double val1, val2;
7883 double valDB_1, valDB_2;
7884 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
7885
7886 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
7887 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
7888 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
7889 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
7890 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
7891 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
7892 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
7893
7894 for (int T = 0; T < elements->numberElements(); T++)
7895 {
7896 p1 = pointsRep->at(elements->getElement(T).getNode(0));
7897 p2 = pointsRep->at(elements->getElement(T).getNode(1));
7898 p3 = pointsRep->at(elements->getElement(T).getNode(2));
7899
7900 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
7901 detB = B.computeInverse(Binv);
7902 absDetB = std::fabs(detB);
7903
7904 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
7905 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
7906 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
7907
7908 // Diskrete Grad-Vektoren berechnen,
7909 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
7910 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
7911 {
7912 u11[0][k] = 0.0;
7913 u12[0][k] = 0.0;
7914 u21[0][k] = 0.0;
7915 u22[0][k] = 0.0;
7916 for(int i = 0; i < dPhiTransU[0].size(); i++)
7917 {
7918 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
7919 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
7920 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
7921 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
7922 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
7923 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
7924
7925 }
7926 }
7927
7928 for (int i = 0; i < phiP->at(0).size(); i++)
7929 {
7930 Teuchos::Array<SC> value1( 1, 0. ); // p-x
7931 Teuchos::Array<SC> value2( 1, 0. ); // p-y
7932 Teuchos::Array<GO> indices( 1, 0 );
7933
7934 for (int j = 0; j < dPhiU->at(0).size(); j++)
7935 {
7936 valDB_1 = 0.0;
7937 valDB_2 = 0.0;
7938
7939 for (int k = 0; k < dPhiU->size(); k++)
7940 {
7941 // DB
7942 valDB_1 = valDB_1 + weights->at(k) *
7943 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) );
7944 valDB_2 = valDB_2 + weights->at(k) *
7945 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] ) );
7946 }
7947
7948 val1 = valDB_1;
7949 val2 = valDB_2;
7950
7951 val1 = absDetB * val1;
7952 val2 = absDetB * val2;
7953
7954 value1[0] = val1; // p-x
7955 value2[0] = val2; // p-y
7956
7957 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
7958 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
7959 indices[0] = glob_j;
7960
7961 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
7962 glob_j++;
7963 indices[0] = glob_j;
7964 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
7965 }
7966 }
7967 }
7968 if (callFillComplete)
7969 {
7970 DB->fillComplete(map2_unique, map1_unique);
7971 }
7972 }
7973 else if(dim == 3)
7974 {
7975 double val1, val2, val3;
7976 double valDB_1, valDB_2, valDB_3;
7977 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
7978
7979 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
7980 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
7981 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
7982 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
7983 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
7984 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
7985 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
7986 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
7987 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
7988 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
7989 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
7990 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
7991
7992 for (int T = 0; T < elements->numberElements(); T++)
7993 {
7994 p1 = pointsRep->at(elements->getElement(T).getNode(0));
7995 p2 = pointsRep->at(elements->getElement(T).getNode(1));
7996 p3 = pointsRep->at(elements->getElement(T).getNode(2));
7997 p4 = pointsRep->at(elements->getElement(T).getNode(3));
7998
7999 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
8000 detB = B.computeInverse(Binv);
8001 absDetB = std::fabs(detB);
8002
8003 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
8004 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
8005 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
8006
8007 // Diskrete Grad-Vektoren berechnen,
8008 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
8009 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
8010 {
8011 u11[0][k] = 0.0;
8012 u12[0][k] = 0.0;
8013 u13[0][k] = 0.0;
8014 u21[0][k] = 0.0;
8015 u22[0][k] = 0.0;
8016 u23[0][k] = 0.0;
8017 u31[0][k] = 0.0;
8018 u32[0][k] = 0.0;
8019 u33[0][k] = 0.0;
8020
8021 for(int i = 0; i < dPhiTransU[0].size(); i++)
8022 {
8023 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
8024 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
8025 LO index3 = dim * elements2->getElement(T).getNode(i) + 2; // z
8026 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
8027 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
8028 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
8029 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
8030 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
8031 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
8032 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
8033 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
8034 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
8035 }
8036 }
8037
8038 for (int i = 0; i < phiP->at(0).size(); i++)
8039 {
8040 Teuchos::Array<SC> value1( 1, 0. ); // p-x
8041 Teuchos::Array<SC> value2( 1, 0. ); // p-y
8042 Teuchos::Array<SC> value3( 1, 0. ); // p-z
8043 Teuchos::Array<GO> indices( 1, 0 );
8044
8045 for (int j = 0; j < dPhiU->at(0).size(); j++)
8046 {
8047 valDB_1 = 0.0;
8048 valDB_2 = 0.0;
8049 valDB_3 = 0.0;
8050
8051 for (int k = 0; k < dPhiU->size(); k++)
8052 {
8053 // DB
8054 valDB_1 = valDB_1 + weights->at(k) *
8055 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] -
8056 u31[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) );
8057 valDB_2 = valDB_2 + weights->at(k) *
8058 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] -
8059 u32[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) );
8060 valDB_3 = valDB_3 + weights->at(k) *
8061 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][2] - u13[0][k] * dPhiTransU[k][j][0] +
8062 u22[0][k] * dPhiTransU[k][j][2] - u23[0][k] * dPhiTransU[k][j][1] ) );
8063 }
8064
8065 val1 = valDB_1;
8066 val2 = valDB_2;
8067 val3 = valDB_3;
8068
8069 val1 = absDetB * val1;
8070 val2 = absDetB * val2;
8071 val3 = absDetB * val3;
8072
8073 value1[0] = val1; // p-x
8074 value2[0] = val2; // p-y
8075 value3[0] = val3; // p-z
8076
8077 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
8078 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
8079 indices[0] = glob_j;
8080
8081 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
8082 glob_j++;
8083 indices[0] = glob_j;
8084 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
8085 glob_j++;
8086 indices[0] = glob_j;
8087 DB->insertGlobalValues(glob_i, indices(), value3()); // p-z
8088 }
8089 }
8090 }
8091 if (callFillComplete)
8092 {
8093 DB->fillComplete(map2_unique, map1_unique);
8094 }
8095 }
8096
8097}
8098
8099template <class SC, class LO, class GO, class NO>
8100void FE<SC,LO,GO,NO>::assemblySurfaceIntegralExternal(int dim,
8101 std::string FEType,
8102 MultiVectorPtr_Type f,
8103 MultiVectorPtr_Type d_rep,
8104 std::vector<SC>& funcParameter,
8105 RhsFunc_Type func,
8106 ParameterListPtr_Type params,
8107 int FEloc) {
8108
8109 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8110
8111 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8112
8113 SC elScaling;
8114 SmallMatrix<SC> B(dim);
8115 vec_dbl_Type b(dim);
8116 f->putScalar(0.);
8117 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
8118
8119 int flagSurface = params->sublist("Parameter Solid").get("Flag Surface",5);
8120
8121 std::vector<double> valueFunc(dim);
8122
8123 SC* paramsFunc = &(funcParameter[0]);
8124
8125 // The second last entry is a placeholder for the surface element flag. It will be set below
8126 for (UN T=0; T<elements->numberElements(); T++) {
8127 FiniteElement fe = elements->getElement( T );
8128 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
8129 for (int surface=0; surface<fe.numSubElements(); surface++) {
8130 FiniteElement feSub = subEl->getElement( surface );
8131 if(subEl->getDimension() == dim-1 ){
8132
8133 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
8134
8135
8136 vec_dbl_Type solution_d = getSolution(nodeList, d_rep,dim);
8137 vec2D_dbl_Type nodes;
8138 nodes = getCoordinates(nodeList, pointsRep);
8139
8140
8141 double positions[18];
8142 int count =0;
8143 for(int i=0;i<6;i++)
8144 for(int j=0;j<3;j++){
8145 positions[count] = nodes[i][j];
8146 count++;
8147
8148 }
8149
8150
8151 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
8152 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
8153 func( &p1[0], &valueFunc[0], paramsFunc);
8154
8155 if(valueFunc[0] != 0.){
8156
8157 double *residuumVector;
8158 #ifdef FEDD_HAVE_ACEGENINTERFACE
8159
8160 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1., 35, &positions[0], &solution_d[0]);
8161 pt.computeTangentResidual();
8162 residuumVector = pt.getResiduum();
8163 #endif
8164
8165 for(int i=0; i< nodeList.size() ; i++){
8166 for(int d=0; d<dim; d++)
8167 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
8168 }
8169
8170 // free(residuumVector);
8171 }
8172
8173 }
8174 }
8175 }
8176 //f->scale(-1.);
8177
8178}
8179
8182
8183template <class SC, class LO, class GO, class NO>
8185 std::string FEType,
8186 MultiVectorPtr_Type f,
8187 MultiVectorPtr_Type d_rep,
8188 MatrixPtr_Type &Kext,
8189 std::vector<SC>& funcParameter,
8190 RhsFunc_Type func,
8191 ParameterListPtr_Type params,
8192 int FEloc) {
8193
8194 // degree of function funcParameter[0]
8195
8196 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8197
8198 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8199
8200 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
8201 SC elScaling;
8202 SmallMatrix<SC> B(dim);
8203 vec_dbl_Type b(dim);
8204 f->putScalar(0.);
8205 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
8206
8207 std::vector<double> valueFunc(dim);
8208
8209 SC* paramsFunc = &(funcParameter[0]);
8210
8211 // The second last entry is a placeholder for the surface element flag. It will be set below
8212 for (UN T=0; T<elements->numberElements(); T++) {
8213 FiniteElement fe = elements->getElement( T );
8214 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
8215 for (int surface=0; surface<fe.numSubElements(); surface++) {
8216 FiniteElement feSub = subEl->getElement( surface );
8217 if(subEl->getDimension() == dim-1 ){
8218 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
8219
8220 vec_dbl_Type solution_d = getSolution(nodeList, d_rep,dim);
8221 vec2D_dbl_Type nodes;
8222 nodes = getCoordinates(nodeList, pointsRep);
8223
8224
8225 double positions[18];
8226 int count =0;
8227 for(int i=0;i<6;i++){
8228 for(int j=0;j<3;j++){
8229 positions[count] = nodes[i][j];
8230 count++;
8231
8232 }
8233 }
8234
8235 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
8236 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
8237 func( &p1[0], &valueFunc[0], paramsFunc);
8238
8239 if(valueFunc[0] != 0.){
8240
8241 double *residuumVector;
8242 double **stiffMat;
8243
8244 #ifdef FEDD_HAVE_ACEGENINTERFACE
8245 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1.0, 35, &positions[0], &solution_d[0]);
8246 pt.computeTangentResidual();
8247
8248 residuumVector = pt.getResiduum();
8249 stiffMat = pt.getStiffnessMatrix();
8250 #endif
8251
8252
8253
8254 int dofs1 = dim;
8255 int numNodes1 =nodeList.size();
8256
8257 SmallMatrix_Type elementMatrixPrint(18,0.);
8258 for(int i=0; i< 18 ; i++){
8259 for(int j=0; j< 18; j++){
8260 if(std::fabs(stiffMat[i][j]) >1e-13)
8261 elementMatrixPrint[i][j] = stiffMat[i][j];
8262
8263 }
8264 }
8265
8266 SmallMatrix_Type elementMatrixWrite(18,0.);
8267
8268 SmallMatrix_Type elementMatrixIDsRow(18,0.);
8269 SmallMatrix_Type elementMatrixIDsCol(18,0.);
8270
8271
8272 for (UN i=0; i < numNodes1 ; i++) {
8273 for(int di=0; di<dim; di++){
8274 Teuchos::Array<SC> value1( numNodes1*dim, 0. );
8275 Teuchos::Array<GO> columnIndices1( numNodes1*dim, 0 );
8276 GO row =GO (dim* map->getGlobalElement( nodeList[i] )+di);
8277 LO rowLO = dim*i+di;
8278 // Zeilenweise werden die Einträge global assembliert
8279 for (UN j=0; j <numNodes1; j++){
8280 for(int d=0; d<dim; d++){
8281 columnIndices1[dim*j+d] = GO ( dim * map->getGlobalElement( nodeList[j] ) + d );
8282 value1[dim*j+d] = stiffMat[rowLO][dim*j+d];
8283 }
8284 }
8285 Kext->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
8286 }
8287 }
8288
8289
8290
8291 for(int i=0; i< nodeList.size() ; i++){
8292 for(int d=0; d<dim; d++){
8293 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
8294 }
8295 }
8296
8297
8298 }
8299
8300
8301 }
8302 }
8303 }
8304 //f->scale(-1.);
8305 Kext->fillComplete(domainVec_.at(FEloc)->getMapVecFieldUnique(),domainVec_.at(FEloc)->getMapVecFieldUnique());
8306}
8307
8309template <class SC, class LO, class GO, class NO>
8310void FE<SC,LO,GO,NO>::computeSurfaceNormal(int dim,
8311 vec2D_dbl_ptr_Type pointsRep,
8312 vec_int_Type nodeList,
8313 vec_dbl_Type &v_E,
8314 double &norm_v_E)
8315{
8316
8317 vec_dbl_Type p1(dim),p2(dim);
8318
8319 if(dim==2){
8320 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
8321 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
8322 norm_v_E = std::sqrt(std::pow(v_E[0],2)+std::pow(v_E[1],2));
8323
8324 }
8325 else if(dim==3){
8326
8327 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
8328 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
8329 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
8330
8331 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
8332 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
8333 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
8334
8335 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
8336 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
8337 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
8338
8339 norm_v_E = std::sqrt(std::pow(v_E[0],2)+std::pow(v_E[1],2)+std::pow(v_E[2],2));
8340
8341 }
8342
8343}
8344
8345template <class SC, class LO, class GO, class NO>
8346void FE<SC,LO,GO,NO>::assemblySurfaceIntegral(int dim,
8347 std::string FEType,
8348 MultiVectorPtr_Type f,
8349 std::string fieldType,
8350 RhsFunc_Type func,
8351 std::vector<SC>& funcParameter) {
8352
8353 // degree of function funcParameter[0]
8354 //TEUCHOS_TEST_FOR_EXCEPTION( funcParameter[funcParameter.size()-1] > 0., std::logic_error, "We only support constant functions for now.");
8355 UN FEloc = checkFE(dim,FEType);
8356
8357 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8358
8359 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8360
8361 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
8362 vec2D_dbl_ptr_Type phi;
8363 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
8364
8365 UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // Degree from function set/determined externally
8366 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
8367
8368 Helper::getPhi(phi, weights, dim-1, FEType, deg);
8369
8370 vec2D_dbl_ptr_Type quadPoints;
8371 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
8372 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
8373 w.reset();
8374
8375 SC elScaling;
8376 SmallMatrix<SC> B(dim);
8377 vec_dbl_Type b(dim);
8378 f->putScalar(0.);
8379 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
8380 int parameters;
8381
8382
8383 std::vector<double> valueFunc(dim);
8384 // The second last entry is a placeholder for the surface element flag. It will be set below
8385 SC* params = &(funcParameter[0]);
8386 for (UN T=0; T<elements->numberElements(); T++) {
8387 FiniteElement fe = elements->getElement( T );
8388 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
8389 for (int surface=0; surface<fe.numSubElements(); surface++) {
8390 FiniteElement feSub = subEl->getElement( surface );
8391 if(subEl->getDimension() == dim-1){
8392 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
8393 params[ funcParameter.size() - 1 ] = feSub.getFlag();
8394
8395 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
8396
8397 vec_dbl_Type v_E(dim,1.);
8398 double norm_v_E=1.;
8399
8400 Helper::computeSurfaceNormal(dim, pointsRep,nodeList,v_E,norm_v_E);
8401
8402 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
8403 elScaling = B.computeScaling( );
8404 // loop over basis functions
8405 for (UN i=0; i < phi->at(0).size(); i++) {
8406 Teuchos::Array<SC> value(0);
8407 if ( fieldType == "Scalar" )
8408 value.resize( 1, 0. );
8409 else if ( fieldType == "Vector" )
8410 value.resize( dim, 0. );
8411 // loop over basis functions quadrature points
8412 for (UN w=0; w<phi->size(); w++) {
8413 vec_dbl_Type x(dim,0.); //coordinates
8414 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
8415 for (int l=0; l<dim-1; l++){
8416 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
8417 }
8418 x[k] += b[k];
8419 }
8420
8421 func( &x[0], &valueFunc[0], params);
8422 if ( fieldType == "Scalar" )
8423 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
8424 else if ( fieldType == "Vector" ){
8425 for (int j=0; j<value.size(); j++){
8426 value[j] += weights->at(w) * valueFunc[j]*v_E[j]/norm_v_E * (*phi)[w][i];
8427 }
8428 }
8429 }
8430
8431 for (int j=0; j<value.size(); j++)
8432 value[j] *= elScaling;
8433
8434 if ( fieldType== "Scalar" )
8435 valuesF[ nodeList[ i ] ] += value[0];
8436
8437
8438 else if ( fieldType== "Vector" ){
8439 for (int j=0; j<value.size(); j++)
8440 valuesF[ dim * nodeList[ i ] + j ] += value[j];
8441 }
8442 }
8443 }
8444 }
8445 }
8446 f->scale(-1.); // Generally the pressure is definied in opposite direction of the normal
8447}
8448
8449template <class SC, class LO, class GO, class NO>
8450void FE<SC,LO,GO,NO>::assemblySurfaceIntegralFlag(int dim,
8451 std::string FEType,
8452 MultiVectorPtr_Type f,
8453 std::string fieldType,
8454 BC_func_Type func,
8455 std::vector<SC>& funcParameter) {
8456
8457// degree of function funcParameter[0]
8458 TEUCHOS_TEST_FOR_EXCEPTION(funcParameter[0]!=0,std::logic_error, "We only support constant functions for now.");
8459
8460 UN FEloc = checkFE(dim,FEType);
8461
8462 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8463
8464 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8465
8466 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
8467 vec2D_dbl_ptr_Type phi;
8468 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
8469 UN degFunc = funcParameter[0] + 1.e-14;
8470 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
8471
8472 Helper::getPhi(phi, weights, dim-1, FEType, deg);
8473
8474 vec2D_dbl_ptr_Type quadPoints;
8475 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
8476 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
8477 w.reset();
8478
8479 SC elScaling;
8480 SmallMatrix<SC> B(dim);
8481 vec_dbl_Type b(dim);
8482 f->putScalar(0.);
8483 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
8484 int parameters;
8485
8486 std::vector<double> valueFunc(dim);
8487 SC* params = &(funcParameter[1]);
8488 for (UN T=0; T<elements->numberElements(); T++) {
8489 FiniteElement fe = elements->getElement( T );
8490 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
8491 for (int surface=0; surface<fe.numSubElements(); surface++) {
8492 FiniteElement feSub = subEl->getElement( surface );
8493 if (params[1] == feSub.getFlag()){
8494 FiniteElement feSub = subEl->getElement( surface );
8495 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
8496 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
8497 elScaling = B.computeScaling( );
8498 // loop over basis functions
8499 for (UN i=0; i < phi->at(0).size(); i++) {
8500 Teuchos::Array<SC> value(0);
8501 if ( fieldType == "Scalar" )
8502 value.resize( 1, 0. );
8503 else if ( fieldType == "Vector" )
8504 value.resize( dim, 0. );
8505 // loop over basis functions quadrature points
8506 for (UN w=0; w<phi->size(); w++) {
8507 vec_dbl_Type x(dim,0.); //coordinates
8508 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
8509 for (int l=0; l<dim-1; l++)
8510 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
8511 x[k] += b[k];
8512 }
8513
8514 func( &x[0], &valueFunc[0], params[0], params);
8515// func( &x[0], &valueFunc[0], params);
8516 if ( fieldType == "Scalar" )
8517 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
8518 else if ( fieldType == "Vector" ){
8519 for (int j=0; j<value.size(); j++){
8520 value[j] += weights->at(w) * valueFunc[j] * (*phi)[w][i];
8521 }
8522 }
8523 }
8524
8525 for (int j=0; j<value.size(); j++)
8526 value[j] *= elScaling;
8527
8528 if ( fieldType== "Scalar" )
8529 valuesF[ nodeList[ i ] ] += value[0];
8530
8531
8532 else if ( fieldType== "Vector" ){
8533 for (int j=0; j<value.size(); j++)
8534 valuesF[ dim * nodeList[ i ] + j ] += value[j];
8535 }
8536 }
8537 }
8538 }
8539
8540 }
8541}
8542
8543template <class SC, class LO, class GO, class NO>
8544void FE<SC,LO,GO,NO>::assemblyRHS( int dim,
8545 std::string FEType,
8546 MultiVectorPtr_Type a,
8547 std::string fieldType,
8548 RhsFunc_Type func,
8549 std::vector<SC>& funcParameter
8550 ) {
8551
8552 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
8553
8554 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
8555 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
8556 UN FEloc;
8557 FEloc = checkFE(dim,FEType);
8558
8559 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8560
8561 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8562
8563 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
8564 vec2D_dbl_ptr_Type phi;
8565 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
8566
8567 // last parameter should alwayss be the degree
8568 //UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // TODO: [JK] Can we remove this?
8569 // inner( f(x), phi(x) ) requires the integration degree of the basis function + some
8570 // extra user-provided degree that accounts for the heterogeneity of f(x).
8571 UN degFunc = 2; // TODO: [JK] Hard coded for now, but needs to be passed by the user. See GitHub issue #66.
8572 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv0) + degFunc;
8573
8574 vec2D_dbl_ptr_Type quadPoints;
8575 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
8576
8577
8578 Helper::getPhi(phi, weights, dim, FEType, deg);
8579
8580 SC detB;
8581 SC absDetB;
8582 SmallMatrix<SC> B(dim);
8583 GO glob_i, glob_j;
8584 vec_dbl_Type v_i(dim);
8585 vec_dbl_Type v_j(dim);
8586
8587 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
8588 int parameters;
8589 double x;
8590 //for now just const!
8591 std::vector<double> valueFunc(dim);
8592 SC* paras = &(funcParameter[0]);
8593
8594 func( &x, &valueFunc[0], paras );
8595 SC value;
8596
8597 for (UN T=0; T<elements->numberElements(); T++) {
8598
8599 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
8600 detB = B.computeDet( );
8601 absDetB = std::fabs(detB);
8602
8603 vec2D_dbl_Type quadPointsTrans(weights->size(),vec_dbl_Type(dim));
8604 for(int i=0; i< weights->size(); i++){
8605 for(int j=0; j< dim ; j++){
8606 for(int k=0; k< dim; k++){
8607 quadPointsTrans[i][j] += B[j][k]* quadPoints->at(i).at(k) ;
8608 }
8609 quadPointsTrans[i][j] += pointsRep->at(elements->getElement(T).getNode(0)).at(j);
8610 }
8611 }
8612 for (UN i=0; i < phi->at(0).size(); i++) {
8613 if ( !fieldType.compare("Scalar") ) {
8614 value = Teuchos::ScalarTraits<SC>::zero();
8615 for (UN w=0; w<weights->size(); w++){
8616 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
8617 value += weights->at(w) * phi->at(w).at(i)*valueFunc[0];
8618 }
8619 value *= absDetB;
8620 LO row = (LO) elements->getElement(T).getNode(i);
8621 valuesRhs[row] += value;
8622 }
8623 else if( !fieldType.compare("Vector") ) {
8624 for (UN d=0; d<dim; d++) {
8625 value = Teuchos::ScalarTraits<SC>::zero();
8626 for (UN w=0; w<weights->size(); w++){
8627 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
8628 value += weights->at(w) * phi->at(w).at(i)*valueFunc[d];
8629 }
8630 value *= absDetB;
8631 SC v_i = value;
8632 LO row = (LO) ( dim * elements->getElement(T).getNode(i) + d );
8633 valuesRhs[row] += v_i;
8634 }
8635 }
8636 else
8637 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
8638 }
8639 }
8640}
8641
8642
8643
8648template <class SC, class LO, class GO, class NO>
8650 std::string FEType,
8651 MultiVectorPtr_Type a)
8652 {
8653
8654 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
8655
8656 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "Multivector is null." );
8657
8658 UN FEloc;
8659 FEloc = checkFE(dim,FEType);
8660
8661 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8662
8663 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8664
8665 vec2D_dbl_ptr_Type phi;
8666 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
8667
8668 UN deg = 2;
8669
8670 vec2D_dbl_ptr_Type quadPoints;
8671 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
8672
8673 Helper::getPhi(phi, weights, dim, FEType, deg);
8674
8675 SC detB;
8676 SC absDetB;
8677 SmallMatrix<SC> B(dim);
8678
8679 // Repeated version we assemble
8680 MultiVectorPtr_Type a_rep = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FEloc)->getMapRepeated(), 1 ) );
8681 a_rep->putScalar(0.);
8682 Teuchos::ArrayRCP< SC > values_a = a_rep->getDataNonConst(0);
8683
8684 for (UN T=0; T<elements->numberElements(); T++) {
8685
8686 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
8687 detB = B.computeDet( );
8688 absDetB = std::fabs(detB);
8689
8690 for (UN i=0; i < phi->at(0).size(); i++) {
8691 Teuchos::Array<SC> value( 1, 0. );
8692 for (UN w=0; w<weights->size(); w++){
8693 value[0] += weights->at(w) * phi->at(w).at(i)*1.0; // We integrate the 1 function over the elements
8694 }
8695 value[0] *= absDetB;
8696 LO row = (LO) elements->getElement(T).getNode(i);
8697
8698 values_a[row] += value[0];
8699 }
8700 }
8701
8702 // Adding it together in the unique vector
8703 a->putScalar(0.);
8704 a->exportFromVector( a_rep, true, "Add" );
8705}
8706
8707
8708template <class SC, class LO, class GO, class NO>
8709void FE<SC,LO,GO,NO>::assemblyRHSDegTest( int dim,
8710 std::string FEType,
8711 MultiVectorPtr_Type a,
8712 std::string fieldType,
8713 RhsFunc_Type func,
8714 std::vector<SC>& funcParameter,
8715 int degree) {
8716 // TODO: [JK] What is the aim of this function? It is not called by any problems, only by a test.
8717 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
8718
8719 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
8720 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
8721
8722 UN FEloc = checkFE(dim,FEType);
8723
8724 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
8725
8726 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
8727
8728 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
8729 vec2D_dbl_ptr_Type phi;
8730 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
8731 Helper::getPhi(phi, weights, dim, FEType, degree);
8732
8733 vec2D_dbl_ptr_Type quadPoints;
8734 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
8735 Helper::getQuadratureValues(dim, degree, quadPoints, w, FEType);
8736 w.reset();
8737
8738
8739 SC detB;
8740 SC absDetB;
8741 SmallMatrix<SC> B(dim);
8742 vec_dbl_Type b(dim);
8743 GO glob_i, glob_j;
8744 vec_dbl_Type v_i(dim);
8745 vec_dbl_Type v_j(dim);
8746
8747 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
8748 int parameters;
8749 double x;
8750 //for now just const!
8751 std::vector<double> valueFunc(dim);
8752 SC* params = &(funcParameter[1]);
8753 for (UN T=0; T<elements->numberElements(); T++) {
8754
8755 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, b, FEType);
8756 detB = B.computeDet( );
8757 absDetB = std::fabs(detB);
8758
8759 for (UN i=0; i < phi->at(0).size(); i++) {
8760 Teuchos::Array<SC> value(1);
8761 for (UN w=0; w<weights->size(); w++){
8762 vec_dbl_Type x(dim,0.); //coordinates
8763 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
8764 for (int l=0; l<dim; l++)
8765 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ] + b[k];
8766 }
8767
8768 func( &x[0], &valueFunc[0], params);
8769 if ( !fieldType.compare("Scalar") ) {
8770 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
8771 }
8772 else if( !fieldType.compare("Vector") ) {
8773 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No test for field type Vector." );
8774 }
8775 else
8776 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
8777
8778 }
8779 value[0] *= absDetB;
8780 LO row = (LO) elements->getElement(T).getNode(i);
8781 valuesRhs[row] += value[0];
8782
8783 }
8784 }
8785}
8786
8787
8788template <class SC, class LO, class GO, class NO>
8789void FE<SC,LO,GO,NO>::buildFullDPhi(vec3D_dbl_ptr_Type dPhi, Teuchos::Array<SmallMatrix<double> >& dPhiMat){
8790
8791 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.");
8792
8793 int dim = dPhi->at(0).at(0).size();
8794 int nmbBasisFunc = dPhi->at(0).size();
8795 int nmbTotalBasisFunc = nmbBasisFunc * dim;
8796 if (dim==2) {
8797 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
8798 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
8799 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
8800 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
8801 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
8802 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
8803
8804 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
8805 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
8806 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
8807 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
8808 }
8809 }
8810 }
8811 else if(dim==3){
8812 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
8813 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
8814 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
8815 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
8816 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][2] = dPhi->at(p).at(i).at(2);
8817 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
8818 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
8819 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][2] = 0.;
8820 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][0] = 0.;
8821 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][1] = 0.;
8822 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][2] = 0.;
8823
8824 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
8825 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
8826 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][2] = 0.;
8827 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
8828 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
8829 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][2] = dPhi->at(p).at(i).at(2);
8830 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][0] = 0.;
8831 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][1] = 0.;
8832 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][2] = 0.;
8833
8834 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][0] = 0.;
8835 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][1] = 0.;
8836 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][2] = 0.;
8837 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][0] = 0.;
8838 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][1] = 0.;
8839 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][2] = 0.;
8840 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][0] = dPhi->at(p).at(i).at(0);
8841 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][1] = dPhi->at(p).at(i).at(1);
8842 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][2] = dPhi->at(p).at(i).at(2);
8843 }
8844 }
8845 }
8846}
8847
8848template <class SC, class LO, class GO, class NO>
8849void FE<SC,LO,GO,NO>::fillMatrixArray(SmallMatrix<double> &matIn, double* matArrayOut, std::string order,int offset){
8850 if (!order.compare("cols")) {
8851 for (int j=0; j<matIn.size(); j++) {
8852 for (int i=0; i<matIn.size(); i++) {
8853 matArrayOut[ j * matIn.size() + i + offset ] = matIn[i][j]; //Spalten der Matrix werden hintereinander in array geschrieben
8854 }
8855 }
8856 }
8857 else if(!order.compare("rows")) {
8858 for (int i=0; i<matIn.size(); i++) {
8859 for (int j=0; j<matIn.size(); j++) {
8860 matArrayOut[ i * matIn.size() + j + offset ] = matIn[i][j]; //Zeilen der Matrix werden hintereinander in array geschrieben
8861 }
8862 }
8863 }
8864 else
8865 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Unknown ordering for matrix to array conversion. Choose rows or cols.");
8866}
8867
8868template <class SC, class LO, class GO, class NO>
8869void FE<SC,LO,GO,NO>::epsilonTensor(vec_dbl_Type &basisValues, SmallMatrix<SC> &epsilonValues, int activeDof){
8870
8871 for (int i=0; i<epsilonValues.size(); i++) {
8872 for (int j=0; j<epsilonValues.size(); j++) {
8873 epsilonValues[i][j] = 0.;
8874 if (i==activeDof) {
8875 epsilonValues[i][j] += 0.5*basisValues.at(j);
8876 }
8877 if (j==activeDof) {
8878 epsilonValues[i][j] += 0.5*basisValues.at(i);
8879 }
8880 }
8881 }
8882}
8883
8884template <class SC, class LO, class GO, class NO>
8885int FE<SC,LO,GO,NO>::checkFE(int dim,
8886 std::string FEType){
8887
8888 int FEloc;
8889 std::vector<int> matches;
8890 for (int i = 0; i < domainVec_.size(); i++) {
8891 if (domainVec_.at(i)->getDimension() == dim)
8892 matches.push_back(i);
8893 }
8894
8895 bool found = false;
8896 for (int i = 0; i < matches.size();i++) {
8897 if (domainVec_.at( matches.at(i) )->getFEType() == FEType) {
8898 FEloc = matches.at(i);
8899 found = true;
8900 }
8901 }
8902
8903 TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error ,"Combination of dimenson(2/3) and FE Type(P1/P2) not defined yet. Use addFE(domain)");
8904
8905 return FEloc;
8906}
8907
8908
8909/*************************************************************
8910 * AceGen 6.921 MacOSX (29 Jan 19) *
8911 * Co. J. Korelc 2013 12 Feb 19 12:07:04 *
8912 **************************************************************
8913 User : Full professional version
8914 Notebook : nh3d_C
8915 Evaluation time : 6 s Mode : Optimal
8916 Number of formulae : 181 Method: Automatic
8917 Subroutine : nh3d size: 4928
8918 Total size of Mathematica code : 4928 subexpressions
8919 Total size of C code : 10178 bytes */
8920/******************* S U B R O U T I N E *********************/
8921template <class SC, class LO, class GO, class NO>
8922void FE<SC,LO,GO,NO>::nh3d(double* v, double (*E), double (*Nu), double** F , double** Pmat, double**** Amat)
8923{
8924 v[356]=2e0*F[0][2];
8925 v[354]=2e0*F[0][1];
8926 v[323]=(*E)/(1e0+(*Nu));
8927 v[3]=((*Nu)*v[323])/(1e0-2e0*(*Nu));
8928 v[5]=v[323]/2e0;
8929 v[36]=v[5]/2e0;
8930 v[65]=2e0*F[0][1];
8931 v[86]=2e0*F[0][2];
8932 v[57]=2e0*F[1][0];
8933 v[66]=2e0*F[1][1];
8934 v[87]=2e0*F[1][2];
8935 v[58]=2e0*F[2][0];
8936 v[67]=2e0*F[2][1];
8937 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
8938 v[335]=(v[18]*v[18]);
8939 v[88]=2e0*F[2][2];
8940 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
8941 v[334]=(v[24]*v[24]);
8942 v[325]=v[18]*v[24];
8943 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
8944 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
8945 v[228]=-(F[2][1]*v[18]);
8946 v[225]=F[2][2]*v[18];
8947 v[217]=-(F[1][1]*v[18]);
8948 v[214]=F[1][2]*v[18];
8949 v[194]=-(F[2][0]*v[18]);
8950 v[185]=-(F[1][0]*v[18]);
8951 v[268]=F[2][1]*v[22];
8952 v[264]=-(F[2][2]*v[22]);
8953 v[255]=F[1][1]*v[22];
8954 v[251]=-(F[1][2]*v[22]);
8955 v[190]=-(F[2][0]*v[22]);
8956 v[181]=-(F[1][0]*v[22]);
8957 v[172]=-(F[0][0]*v[22]);
8958 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
8959 v[324]=-(v[20]*v[22]);
8960 v[327]=2e0*(v[324]+v[325]);
8961 v[94]=v[20]*v[88];
8962 v[92]=v[20]*v[87];
8963 v[90]=v[20]*v[86];
8964 v[138]=v[15]*v[20]-v[335];
8965 v[270]=F[2][0]*v[24];
8966 v[260]=-(F[2][2]*v[24]);
8967 v[257]=F[1][0]*v[24];
8968 v[247]=-(F[1][2]*v[24]);
8969 v[244]=F[0][0]*v[24];
8970 v[232]=-(F[0][2]*v[24]);
8971 v[222]=-(F[2][1]*v[24]);
8972 v[211]=-(F[1][1]*v[24]);
8973 v[198]=-(F[0][1]*v[24]);
8974 v[168]=v[18]*v[22]-v[15]*v[24];
8975 v[331]=2e0*v[168];
8976 v[329]=2e0*v[168];
8977 v[326]=2e0*v[168];
8978 v[38]=-(v[22]*v[22]);
8979 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
8980 v[333]=v[20]*v[26]-v[334];
8981 v[351]=2e0*F[0][0]*v[333];
8982 v[236]=v[22]*v[24]-v[18]*v[26];
8983 v[332]=2e0*v[236];
8984 v[330]=2e0*v[236];
8985 v[328]=2e0*v[236];
8986 v[99]=v[26]*v[58];
8987 v[97]=v[26]*v[57];
8988 v[93]=v[26]*v[67];
8989 v[91]=v[26]*v[66];
8990 v[89]=v[26]*v[65];
8991 v[148]=v[15]*v[26]+v[38];
8992 v[29]=v[148]*v[20]+2e0*v[22]*v[325]-v[15]*v[334]-v[26]*v[335];
8993 v[336]=1e0/Power(v[29],2);
8994 v[32]=-v[5]+v[3]*std::log(std::sqrt(v[29]));
8995 v[337]=(v[3]/4e0-v[32]/2e0)*v[336];
8996 v[137]=v[337]*(F[2][1]*v[326]+F[2][0]*v[327]-v[335]*v[88]+v[15]*v[94]);
8997 v[147]=v[137]*v[138];
8998 v[136]=v[337]*(F[2][2]*v[329]+F[2][0]*v[330]+v[38]*v[67]+v[15]*v[93]);
8999 v[156]=v[136]*v[148];
9000 v[135]=v[337]*(F[2][2]*v[327]+F[2][1]*v[328]-v[334]*v[58]+v[20]*v[99]);
9001 v[165]=v[135]*v[333];
9002 v[134]=v[337]*(F[1][1]*v[326]+F[1][0]*v[327]-v[335]*v[87]+v[15]*v[92]);
9003 v[144]=v[134]*v[138];
9004 v[133]=v[337]*(F[1][2]*v[331]+F[1][0]*v[332]+v[38]*v[66]+v[15]*v[91]);
9005 v[153]=v[133]*v[148];
9006 v[132]=v[337]*(F[1][2]*v[327]+F[1][1]*v[328]-v[334]*v[57]+v[20]*v[97]);
9007 v[162]=v[132]*v[333];
9008 v[131]=v[337]*(F[0][0]*v[327]+F[0][1]*v[329]-v[335]*v[86]+v[15]*v[90]);
9009 v[130]=v[337]*(F[0][2]*v[331]+F[0][0]*v[332]+v[38]*v[65]+v[15]*v[89]);
9010 v[128]=v[337]*(F[0][2]*v[327]+F[0][1]*v[330]+v[351]);
9011 v[37]=v[32]/(2e0*v[29]);
9012 v[355]=v[37]*(2e0*v[172]+v[15]*v[86]);
9013 v[353]=v[37]*(2e0*v[232]+v[89]);
9014 v[352]=v[37]*(2e0*v[198]+v[90]);
9015 v[349]=-2e0*(F[1][0]*v[20]+v[217])*v[37];
9016 v[348]=-(v[37]*(2e0*v[185]+v[15]*v[66]));
9017 v[347]=-2e0*(F[2][0]*v[20]+v[228])*v[37];
9018 v[346]=-(v[37]*(2e0*v[194]+v[15]*v[67]));
9019 v[345]=-(v[37]*(2e0*v[251]+v[97]));
9020 v[344]=-(v[37]*(2e0*v[181]+v[15]*v[87]));
9021 v[343]=-(v[37]*(2e0*v[264]+v[99]));
9022 v[342]=-(v[37]*(2e0*v[190]+v[15]*v[88]));
9023 v[341]=-(v[37]*(2e0*v[247]+v[91]));
9024 v[340]=-(v[37]*(2e0*v[211]+v[92]));
9025 v[339]=-(v[37]*(2e0*v[260]+v[93]));
9026 v[338]=-(v[37]*(2e0*v[222]+v[94]));
9027 v[272]=v[137]*v[328]+v[37]*(2e0*v[268]+2e0*v[270]-2e0*v[18]*v[88]);
9028 v[267]=v[136]*v[328]+v[343];
9029 v[263]=v[135]*v[328]+v[339];
9030 v[259]=v[134]*v[328]+v[37]*(2e0*v[255]+2e0*v[257]-2e0*v[18]*v[87]);
9031 v[254]=v[133]*v[328]+v[345];
9032 v[250]=v[132]*v[328]+v[341];
9033 v[246]=v[131]*v[328]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[244]-2e0*v[18]*v[86]);
9034 v[241]=v[130]*v[328]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
9035 v[231]=v[137]*v[327]+v[347];
9036 v[227]=v[136]*v[327]+v[37]*(2e0*v[225]+2e0*v[270]-2e0*v[22]*v[67]);
9037 v[224]=v[135]*v[327]+v[338];
9038 v[301]=2e0*F[1][0]*v[165]+F[1][2]*v[224]+F[1][1]*v[263];
9039 v[279]=2e0*F[0][0]*v[165]+F[0][2]*v[224]+F[0][1]*v[263];
9040 v[220]=v[134]*v[327]+v[349];
9041 v[216]=v[133]*v[327]+v[37]*(2e0*v[214]+2e0*v[257]-2e0*v[22]*v[66]);
9042 v[213]=v[132]*v[327]+v[340];
9043 v[276]=2e0*F[0][0]*v[162]+F[0][2]*v[213]+F[0][1]*v[250];
9044 v[209]=v[131]*v[327]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
9045 v[196]=v[137]*v[326]+v[346];
9046 v[314]=2e0*F[1][2]*v[147]+F[1][1]*v[196]+F[1][0]*v[231];
9047 v[296]=2e0*F[0][2]*v[147]+F[0][1]*v[196]+F[0][0]*v[231];
9048 v[192]=v[136]*v[326]+v[342];
9049 v[308]=2e0*F[1][1]*v[156]+F[1][2]*v[192]+F[1][0]*v[267];
9050 v[288]=2e0*F[0][1]*v[156]+F[0][2]*v[192]+F[0][0]*v[267];
9051 v[188]=v[135]*v[326]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[24]*v[58]);
9052 v[187]=v[134]*v[326]+v[348];
9053 v[293]=2e0*F[0][2]*v[144]+F[0][1]*v[187]+F[0][0]*v[220];
9054 v[183]=v[133]*v[326]+v[344];
9055 v[285]=2e0*F[0][1]*v[153]+F[0][2]*v[183]+F[0][0]*v[254];
9056 v[179]=v[132]*v[326]+v[37]*(2e0*v[214]+2e0*v[255]-2e0*v[24]*v[57]);
9057 v[178]=v[131]*v[326]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
9058 v[167]=v[137]*v[333]-v[338];
9059 v[303]=2e0*F[1][0]*v[167]+F[1][2]*v[231]+F[1][1]*v[272];
9060 v[281]=2e0*F[0][0]*v[167]+F[0][2]*v[231]+F[0][1]*v[272];
9061 v[166]=v[136]*v[333]-v[339];
9062 v[302]=2e0*F[1][0]*v[166]+F[1][2]*v[227]+F[1][1]*v[267];
9063 v[280]=2e0*F[0][0]*v[166]+F[0][2]*v[227]+F[0][1]*v[267];
9064 v[164]=v[134]*v[333]-v[340];
9065 v[278]=2e0*F[0][0]*v[164]+F[0][2]*v[220]+F[0][1]*v[259];
9066 v[163]=v[133]*v[333]-v[341];
9067 v[277]=2e0*F[0][0]*v[163]+F[0][2]*v[216]+F[0][1]*v[254];
9068 v[157]=v[137]*v[148]-v[342];
9069 v[309]=2e0*F[1][1]*v[157]+F[1][2]*v[196]+F[1][0]*v[272];
9070 v[289]=2e0*F[0][1]*v[157]+F[0][2]*v[196]+F[0][0]*v[272];
9071 v[155]=v[135]*v[148]-v[343];
9072 v[307]=2e0*F[1][1]*v[155]+F[1][2]*v[188]+F[1][0]*v[263];
9073 v[287]=2e0*F[0][1]*v[155]+F[0][2]*v[188]+F[0][0]*v[263];
9074 v[154]=v[134]*v[148]-v[344];
9075 v[286]=2e0*F[0][1]*v[154]+F[0][2]*v[187]+F[0][0]*v[259];
9076 v[284]=F[0][2]*v[179]+F[0][0]*v[250]+2e0*F[0][1]*(v[132]*v[148]-v[345]);
9077 v[146]=v[136]*v[138]-v[346];
9078 v[313]=2e0*F[1][2]*v[146]+F[1][1]*v[192]+F[1][0]*v[227];
9079 v[295]=2e0*F[0][2]*v[146]+F[0][1]*v[192]+F[0][0]*v[227];
9080 v[145]=v[135]*v[138]-v[347];
9081 v[312]=2e0*F[1][2]*v[145]+F[1][1]*v[188]+F[1][0]*v[224];
9082 v[294]=2e0*F[0][2]*v[145]+F[0][1]*v[188]+F[0][0]*v[224];
9083 v[292]=F[0][1]*v[183]+F[0][0]*v[216]+2e0*F[0][2]*(v[133]*v[138]-v[348]);
9084 v[291]=F[0][1]*v[179]+F[0][0]*v[213]+(v[132]*v[138]-v[349])*v[356];
9085 v[35]=v[36]+v[138]*v[37];
9086 v[310]=2e0*v[35];
9087 v[40]=v[36]+v[148]*v[37];
9088 v[304]=2e0*v[40];
9089 v[43]=v[36]+v[333]*v[37];
9090 v[297]=2e0*v[43];
9091 v[44]=v[326]*v[37];
9092 v[319]=2e0*F[2][1]*v[157]+F[2][2]*v[196]+F[2][0]*v[272]+v[44];
9093 v[306]=2e0*F[1][1]*v[154]+F[1][2]*v[187]+F[1][0]*v[259]+v[44];
9094 v[283]=F[0][2]*v[178]+F[0][0]*v[246]+v[354]*(v[131]*v[148]+v[355])+v[44];
9095 v[45]=v[327]*v[37];
9096 v[317]=2e0*F[2][0]*v[167]+F[2][2]*v[231]+F[2][1]*v[272]+v[45];
9097 v[300]=2e0*F[1][0]*v[164]+F[1][2]*v[220]+F[1][1]*v[259]+v[45];
9098 v[275]=F[0][2]*v[209]+F[0][1]*v[246]+2e0*F[0][0]*(v[131]*v[333]+v[352])+v[45];
9099 v[46]=v[328]*v[37];
9100 v[316]=2e0*F[2][0]*v[166]+F[2][2]*v[227]+F[2][1]*v[267]+v[46];
9101 v[299]=2e0*F[1][0]*v[163]+F[1][2]*v[216]+F[1][1]*v[254]+v[46];
9102 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]*
9103 (2e0*F[0][2]*v[18]+2e0*v[244]-2e0*v[22]*v[65]));
9104 Pmat[0][0]=F[0][0]*v[297]+F[0][2]*v[45]+F[0][1]*v[46];
9105 Pmat[0][1]=F[0][1]*v[304]+F[0][2]*v[44]+F[0][0]*v[46];
9106 Pmat[0][2]=F[0][2]*v[310]+F[0][1]*v[44]+F[0][0]*v[45];
9107 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[45]+F[1][1]*v[46];
9108 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[44]+F[1][0]*v[46];
9109 Pmat[1][2]=2e0*F[1][2]*v[35]+F[1][1]*v[44]+F[1][0]*v[45];
9110 Pmat[2][0]=F[2][0]*v[297]+F[2][2]*v[45]+F[2][1]*v[46];
9111 Pmat[2][1]=F[2][1]*v[304]+F[2][2]*v[44]+F[2][0]*v[46];
9112 Pmat[2][2]=F[2][2]*v[310]+F[2][1]*v[44]+F[2][0]*v[45];
9113 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]
9114 );
9115 Amat[0][0][0][1]=v[274];
9116 Amat[0][0][0][2]=v[275];
9117 Amat[0][0][1][0]=v[276];
9118 Amat[0][0][1][1]=v[277];
9119 Amat[0][0][1][2]=v[278];
9120 Amat[0][0][2][0]=v[279];
9121 Amat[0][0][2][1]=v[280];
9122 Amat[0][0][2][2]=v[281];
9123 Amat[0][1][0][0]=v[274];
9124 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]);
9125 Amat[0][1][0][2]=v[283];
9126 Amat[0][1][1][0]=v[284];
9127 Amat[0][1][1][1]=v[285];
9128 Amat[0][1][1][2]=v[286];
9129 Amat[0][1][2][0]=v[287];
9130 Amat[0][1][2][1]=v[288];
9131 Amat[0][1][2][2]=v[289];
9132 Amat[0][2][0][0]=v[275];
9133 Amat[0][2][0][1]=v[283];
9134 Amat[0][2][0][2]=F[0][1]*v[178]+F[0][0]*v[209]+v[310]+v[131]*v[138]*v[356];
9135 Amat[0][2][1][0]=v[291];
9136 Amat[0][2][1][1]=v[292];
9137 Amat[0][2][1][2]=v[293];
9138 Amat[0][2][2][0]=v[294];
9139 Amat[0][2][2][1]=v[295];
9140 Amat[0][2][2][2]=v[296];
9141 Amat[1][0][0][0]=v[276];
9142 Amat[1][0][0][1]=v[284];
9143 Amat[1][0][0][2]=v[291];
9144 Amat[1][0][1][0]=2e0*F[1][0]*v[162]+F[1][2]*v[213]+F[1][1]*v[250]+v[297];
9145 Amat[1][0][1][1]=v[299];
9146 Amat[1][0][1][2]=v[300];
9147 Amat[1][0][2][0]=v[301];
9148 Amat[1][0][2][1]=v[302];
9149 Amat[1][0][2][2]=v[303];
9150 Amat[1][1][0][0]=v[277];
9151 Amat[1][1][0][1]=v[285];
9152 Amat[1][1][0][2]=v[292];
9153 Amat[1][1][1][0]=v[299];
9154 Amat[1][1][1][1]=2e0*F[1][1]*v[153]+F[1][2]*v[183]+F[1][0]*v[254]+v[304];
9155 Amat[1][1][1][2]=v[306];
9156 Amat[1][1][2][0]=v[307];
9157 Amat[1][1][2][1]=v[308];
9158 Amat[1][1][2][2]=v[309];
9159 Amat[1][2][0][0]=v[278];
9160 Amat[1][2][0][1]=v[286];
9161 Amat[1][2][0][2]=v[293];
9162 Amat[1][2][1][0]=v[300];
9163 Amat[1][2][1][1]=v[306];
9164 Amat[1][2][1][2]=2e0*F[1][2]*v[144]+F[1][1]*v[187]+F[1][0]*v[220]+v[310];
9165 Amat[1][2][2][0]=v[312];
9166 Amat[1][2][2][1]=v[313];
9167 Amat[1][2][2][2]=v[314];
9168 Amat[2][0][0][0]=v[279];
9169 Amat[2][0][0][1]=v[287];
9170 Amat[2][0][0][2]=v[294];
9171 Amat[2][0][1][0]=v[301];
9172 Amat[2][0][1][1]=v[307];
9173 Amat[2][0][1][2]=v[312];
9174 Amat[2][0][2][0]=2e0*F[2][0]*v[165]+F[2][2]*v[224]+F[2][1]*v[263]+v[297];
9175 Amat[2][0][2][1]=v[316];
9176 Amat[2][0][2][2]=v[317];
9177 Amat[2][1][0][0]=v[280];
9178 Amat[2][1][0][1]=v[288];
9179 Amat[2][1][0][2]=v[295];
9180 Amat[2][1][1][0]=v[302];
9181 Amat[2][1][1][1]=v[308];
9182 Amat[2][1][1][2]=v[313];
9183 Amat[2][1][2][0]=v[316];
9184 Amat[2][1][2][1]=2e0*F[2][1]*v[156]+F[2][2]*v[192]+F[2][0]*v[267]+v[304];
9185 Amat[2][1][2][2]=v[319];
9186 Amat[2][2][0][0]=v[281];
9187 Amat[2][2][0][1]=v[289];
9188 Amat[2][2][0][2]=v[296];
9189 Amat[2][2][1][0]=v[303];
9190 Amat[2][2][1][1]=v[309];
9191 Amat[2][2][1][2]=v[314];
9192 Amat[2][2][2][0]=v[317];
9193 Amat[2][2][2][1]=v[319];
9194 Amat[2][2][2][2]=2e0*F[2][2]*v[147]+F[2][1]*v[196]+F[2][0]*v[231]+v[310];
9195}
9196
9197
9198/*************************************************************
9199 * AceGen 6.921 MacOSX (29 Jan 19) *
9200 * Co. J. Korelc 2013 12 Feb 19 12:06:46 *
9201 **************************************************************
9202 User : Full professional version
9203 Notebook : mr3d_C
9204 Evaluation time : 7 s Mode : Optimal
9205 Number of formulae : 190 Method: Automatic
9206 Subroutine : mr3d size: 5215
9207 Total size of Mathematica code : 5215 subexpressions
9208 Total size of C code : 10798 bytes */
9209
9210/******************* S U B R O U T I N E *********************/
9211template <class SC, class LO, class GO, class NO>
9212void FE<SC,LO,GO,NO>::mr3d(double* v,double (*E),double (*Nu),double (*C)
9213 ,double** F,double** Pmat,double**** Amat)
9214{
9215 v[366]=2e0*F[0][2];
9216 v[364]=2e0*F[0][1];
9217 v[4]=(*E)/(2e0+2e0*(*Nu));
9218 v[139]=((*C)*v[4])/2e0;
9219 v[5]=(*E)/(3e0-6e0*(*Nu));
9220 v[57]=2e0*F[0][0];
9221 v[150]=v[139]*v[57];
9222 v[66]=2e0*F[0][1];
9223 v[165]=v[139]*v[66];
9224 v[87]=2e0*F[0][2];
9225 v[167]=v[139]*v[87];
9226 v[58]=2e0*F[1][0];
9227 v[155]=v[139]*v[58];
9228 v[67]=2e0*F[1][1];
9229 v[170]=v[139]*v[67];
9230 v[88]=2e0*F[1][2];
9231 v[172]=v[139]*v[88];
9232 v[59]=2e0*F[2][0];
9233 v[159]=v[139]*v[59];
9234 v[68]=2e0*F[2][1];
9235 v[175]=v[139]*v[68];
9236 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
9237 v[345]=(v[18]*v[18]);
9238 v[89]=2e0*F[2][2];
9239 v[177]=v[139]*v[89];
9240 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
9241 v[344]=(v[24]*v[24]);
9242 v[335]=v[18]*v[24];
9243 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
9244 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
9245 v[239]=-(F[2][1]*v[18]);
9246 v[236]=F[2][2]*v[18];
9247 v[228]=-(F[1][1]*v[18]);
9248 v[225]=F[1][2]*v[18];
9249 v[205]=-(F[2][0]*v[18]);
9250 v[196]=-(F[1][0]*v[18]);
9251 v[279]=F[2][1]*v[22];
9252 v[275]=-(F[2][2]*v[22]);
9253 v[266]=F[1][1]*v[22];
9254 v[262]=-(F[1][2]*v[22]);
9255 v[201]=-(F[2][0]*v[22]);
9256 v[192]=-(F[1][0]*v[22]);
9257 v[183]=-(F[0][0]*v[22]);
9258 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
9259 v[334]=-(v[20]*v[22]);
9260 v[337]=2e0*(v[334]+v[335]);
9261 v[95]=v[20]*v[89];
9262 v[93]=v[20]*v[88];
9263 v[91]=v[20]*v[87];
9264 v[140]=v[15]*v[20]-v[345];
9265 v[281]=F[2][0]*v[24];
9266 v[271]=-(F[2][2]*v[24]);
9267 v[268]=F[1][0]*v[24];
9268 v[258]=-(F[1][2]*v[24]);
9269 v[255]=F[0][0]*v[24];
9270 v[243]=-(F[0][2]*v[24]);
9271 v[233]=-(F[2][1]*v[24]);
9272 v[222]=-(F[1][1]*v[24]);
9273 v[209]=-(F[0][1]*v[24]);
9274 v[179]=v[18]*v[22]-v[15]*v[24];
9275 v[341]=2e0*v[179];
9276 v[339]=2e0*v[179];
9277 v[336]=2e0*v[179];
9278 v[38]=-(v[22]*v[22]);
9279 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
9280 v[343]=v[20]*v[26]-v[344];
9281 v[361]=v[343]*v[57];
9282 v[247]=v[22]*v[24]-v[18]*v[26];
9283 v[342]=2e0*v[247];
9284 v[340]=2e0*v[247];
9285 v[338]=2e0*v[247];
9286 v[100]=v[26]*v[59];
9287 v[98]=v[26]*v[58];
9288 v[94]=v[26]*v[68];
9289 v[92]=v[26]*v[67];
9290 v[90]=v[26]*v[66];
9291 v[151]=v[15]*v[26]+v[38];
9292 v[29]=v[151]*v[20]+2e0*v[22]*v[335]-v[15]*v[344]-v[26]*v[345];
9293 v[346]=1e0/Power(v[29],2);
9294 v[33]=-2e0*v[139]-v[4]+v[5]*std::log(std::sqrt(v[29]));
9295 v[347]=v[346]*(-v[33]/2e0+v[5]/4e0);
9296 v[138]=v[347]*(F[2][1]*v[336]+F[2][0]*v[337]-v[345]*v[89]+v[15]*v[95]);
9297 v[149]=v[138]*v[140];
9298 v[137]=v[347]*(F[2][2]*v[339]+F[2][0]*v[340]+v[38]*v[68]+v[15]*v[94]);
9299 v[161]=v[137]*v[151];
9300 v[136]=v[347]*(v[100]*v[20]+F[2][2]*v[337]+F[2][1]*v[338]-v[344]*v[59]);
9301 v[174]=v[136]*v[343];
9302 v[135]=v[347]*(F[1][1]*v[336]+F[1][0]*v[337]-v[345]*v[88]+v[15]*v[93]);
9303 v[146]=v[135]*v[140];
9304 v[134]=v[347]*(F[1][2]*v[341]+F[1][0]*v[342]+v[38]*v[67]+v[15]*v[92]);
9305 v[157]=v[134]*v[151];
9306 v[133]=v[347]*(F[1][2]*v[337]+F[1][1]*v[338]-v[344]*v[58]+v[20]*v[98]);
9307 v[169]=v[133]*v[343];
9308 v[132]=v[347]*(F[0][0]*v[337]+F[0][1]*v[339]-v[345]*v[87]+v[15]*v[91]);
9309 v[131]=v[347]*(F[0][2]*v[341]+F[0][0]*v[342]+v[38]*v[66]+v[15]*v[90]);
9310 v[129]=v[347]*(F[0][2]*v[337]+F[0][1]*v[340]+v[361]);
9311 v[37]=v[33]/(2e0*v[29]);
9312 v[365]=v[37]*(2e0*v[183]+v[15]*v[87]);
9313 v[363]=v[37]*(2e0*v[243]+v[90]);
9314 v[362]=v[37]*(2e0*v[209]+v[91]);
9315 v[359]=-2e0*(F[1][0]*v[20]+v[228])*v[37];
9316 v[358]=-(v[37]*(2e0*v[196]+v[15]*v[67]));
9317 v[357]=-2e0*(F[2][0]*v[20]+v[239])*v[37];
9318 v[356]=-(v[37]*(2e0*v[205]+v[15]*v[68]));
9319 v[355]=-(v[37]*(2e0*v[262]+v[98]));
9320 v[354]=-(v[37]*(2e0*v[192]+v[15]*v[88]));
9321 v[353]=-((v[100]+2e0*v[275])*v[37]);
9322 v[352]=-(v[37]*(2e0*v[201]+v[15]*v[89]));
9323 v[351]=-(v[37]*(2e0*v[258]+v[92]));
9324 v[350]=-(v[37]*(2e0*v[222]+v[93]));
9325 v[349]=-(v[37]*(2e0*v[271]+v[94]));
9326 v[348]=-(v[37]*(2e0*v[233]+v[95]));
9327 v[283]=v[138]*v[338]+v[37]*(2e0*v[279]+2e0*v[281]-2e0*v[18]*v[89]);
9328 v[278]=-v[159]+v[137]*v[338]+v[353];
9329 v[274]=-v[175]+v[136]*v[338]+v[349];
9330 v[270]=v[135]*v[338]+v[37]*(2e0*v[266]+2e0*v[268]-2e0*v[18]*v[88]);
9331 v[265]=-v[155]+v[134]*v[338]+v[355];
9332 v[261]=-v[170]+v[133]*v[338]+v[351];
9333 v[257]=v[132]*v[338]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[255]-2e0*v[18]*v[87]);
9334 v[252]=-v[150]+v[131]*v[338]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
9335 v[242]=-v[159]+v[138]*v[337]+v[357];
9336 v[238]=v[137]*v[337]+v[37]*(2e0*v[236]+2e0*v[281]-2e0*v[22]*v[68]);
9337 v[235]=-v[177]+v[136]*v[337]+v[348];
9338 v[312]=2e0*F[1][0]*v[174]+F[1][2]*v[235]+F[1][1]*v[274];
9339 v[290]=2e0*F[0][0]*v[174]+F[0][2]*v[235]+F[0][1]*v[274];
9340 v[231]=-v[155]+v[135]*v[337]+v[359];
9341 v[227]=v[134]*v[337]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[22]*v[67]);
9342 v[224]=-v[172]+v[133]*v[337]+v[350];
9343 v[287]=2e0*F[0][0]*v[169]+F[0][2]*v[224]+F[0][1]*v[261];
9344 v[220]=-v[150]+v[132]*v[337]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
9345 v[207]=-v[175]+v[138]*v[336]+v[356];
9346 v[325]=2e0*F[1][2]*v[149]+F[1][1]*v[207]+F[1][0]*v[242];
9347 v[307]=2e0*F[0][2]*v[149]+F[0][1]*v[207]+F[0][0]*v[242];
9348 v[203]=-v[177]+v[137]*v[336]+v[352];
9349 v[319]=2e0*F[1][1]*v[161]+F[1][2]*v[203]+F[1][0]*v[278];
9350 v[299]=2e0*F[0][1]*v[161]+F[0][2]*v[203]+F[0][0]*v[278];
9351 v[199]=v[136]*v[336]+v[37]*(2e0*v[236]+2e0*v[279]-2e0*v[24]*v[59]);
9352 v[198]=-v[170]+v[135]*v[336]+v[358];
9353 v[304]=2e0*F[0][2]*v[146]+F[0][1]*v[198]+F[0][0]*v[231];
9354 v[194]=-v[172]+v[134]*v[336]+v[354];
9355 v[296]=2e0*F[0][1]*v[157]+F[0][2]*v[194]+F[0][0]*v[265];
9356 v[190]=v[133]*v[336]+v[37]*(2e0*v[225]+2e0*v[266]-2e0*v[24]*v[58]);
9357 v[189]=-v[165]+v[132]*v[336]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
9358 v[178]=v[177]+v[138]*v[343]-v[348];
9359 v[314]=2e0*F[1][0]*v[178]+F[1][2]*v[242]+F[1][1]*v[283];
9360 v[292]=2e0*F[0][0]*v[178]+F[0][2]*v[242]+F[0][1]*v[283];
9361 v[176]=v[175]+v[137]*v[343]-v[349];
9362 v[313]=2e0*F[1][0]*v[176]+F[1][2]*v[238]+F[1][1]*v[278];
9363 v[291]=2e0*F[0][0]*v[176]+F[0][2]*v[238]+F[0][1]*v[278];
9364 v[173]=v[172]+v[135]*v[343]-v[350];
9365 v[289]=2e0*F[0][0]*v[173]+F[0][2]*v[231]+F[0][1]*v[270];
9366 v[171]=v[170]+v[134]*v[343]-v[351];
9367 v[288]=2e0*F[0][0]*v[171]+F[0][2]*v[227]+F[0][1]*v[265];
9368 v[162]=v[138]*v[151]+v[177]-v[352];
9369 v[320]=2e0*F[1][1]*v[162]+F[1][2]*v[207]+F[1][0]*v[283];
9370 v[300]=2e0*F[0][1]*v[162]+F[0][2]*v[207]+F[0][0]*v[283];
9371 v[160]=v[136]*v[151]+v[159]-v[353];
9372 v[318]=2e0*F[1][1]*v[160]+F[1][2]*v[199]+F[1][0]*v[274];
9373 v[298]=2e0*F[0][1]*v[160]+F[0][2]*v[199]+F[0][0]*v[274];
9374 v[158]=v[135]*v[151]+v[172]-v[354];
9375 v[297]=2e0*F[0][1]*v[158]+F[0][2]*v[198]+F[0][0]*v[270];
9376 v[295]=F[0][2]*v[190]+F[0][0]*v[261]+2e0*F[0][1]*(v[133]*v[151]+v[155]-v[355]);
9377 v[148]=v[137]*v[140]+v[175]-v[356];
9378 v[324]=2e0*F[1][2]*v[148]+F[1][1]*v[203]+F[1][0]*v[238];
9379 v[306]=2e0*F[0][2]*v[148]+F[0][1]*v[203]+F[0][0]*v[238];
9380 v[147]=v[136]*v[140]+v[159]-v[357];
9381 v[323]=2e0*F[1][2]*v[147]+F[1][1]*v[199]+F[1][0]*v[235];
9382 v[305]=2e0*F[0][2]*v[147]+F[0][1]*v[199]+F[0][0]*v[235];
9383 v[303]=F[0][1]*v[194]+F[0][0]*v[227]+2e0*F[0][2]*(v[134]*v[140]+v[170]-v[358]);
9384 v[302]=F[0][1]*v[190]+F[0][0]*v[224]+(v[133]*v[140]+v[155]-v[359])*v[366];
9385 v[36]=v[140]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[20]))*v[4])/2e0;
9386 v[321]=2e0*v[36];
9387 v[40]=v[151]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[26]))*v[4])/2e0;
9388 v[315]=2e0*v[40];
9389 v[43]=v[343]*v[37]+((1e0+(*C)*(-1e0+v[20]+v[26]))*v[4])/2e0;
9390 v[308]=2e0*v[43];
9391 v[45]=-2e0*v[139]*v[24]+v[336]*v[37];
9392 v[330]=2e0*F[2][1]*v[162]+F[2][2]*v[207]+F[2][0]*v[283]+v[45];
9393 v[317]=2e0*F[1][1]*v[158]+F[1][2]*v[198]+F[1][0]*v[270]+v[45];
9394 v[294]=F[0][2]*v[189]+F[0][0]*v[257]+v[364]*(v[132]*v[151]+v[167]+v[365])+v[45];
9395 v[46]=-2e0*v[139]*v[22]+v[337]*v[37];
9396 v[328]=2e0*F[2][0]*v[178]+F[2][2]*v[242]+F[2][1]*v[283]+v[46];
9397 v[311]=2e0*F[1][0]*v[173]+F[1][2]*v[231]+F[1][1]*v[270]+v[46];
9398 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];
9399 v[47]=-2e0*v[139]*v[18]+v[338]*v[37];
9400 v[327]=2e0*F[2][0]*v[176]+F[2][2]*v[238]+F[2][1]*v[278]+v[47];
9401 v[310]=2e0*F[1][0]*v[171]+F[1][2]*v[227]+F[1][1]*v[265]+v[47];
9402 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]*
9403 (2e0*F[0][2]*v[18]+2e0*v[255]-2e0*v[22]*v[66]));
9404 Pmat[0][0]=F[0][0]*v[308]+F[0][2]*v[46]+F[0][1]*v[47];
9405 Pmat[0][1]=F[0][1]*v[315]+F[0][2]*v[45]+F[0][0]*v[47];
9406 Pmat[0][2]=F[0][2]*v[321]+F[0][1]*v[45]+F[0][0]*v[46];
9407 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[46]+F[1][1]*v[47];
9408 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[45]+F[1][0]*v[47];
9409 Pmat[1][2]=2e0*F[1][2]*v[36]+F[1][1]*v[45]+F[1][0]*v[46];
9410 Pmat[2][0]=F[2][0]*v[308]+F[2][2]*v[46]+F[2][1]*v[47];
9411 Pmat[2][1]=F[2][1]*v[315]+F[2][2]*v[45]+F[2][0]*v[47];
9412 Pmat[2][2]=F[2][2]*v[321]+F[2][1]*v[45]+F[2][0]*v[46];
9413 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]
9414 +v[129]*v[338]-v[363]);
9415 Amat[0][0][0][1]=v[285];
9416 Amat[0][0][0][2]=v[286];
9417 Amat[0][0][1][0]=v[287];
9418 Amat[0][0][1][1]=v[288];
9419 Amat[0][0][1][2]=v[289];
9420 Amat[0][0][2][0]=v[290];
9421 Amat[0][0][2][1]=v[291];
9422 Amat[0][0][2][2]=v[292];
9423 Amat[0][1][0][0]=v[285];
9424 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]);
9425 Amat[0][1][0][2]=v[294];
9426 Amat[0][1][1][0]=v[295];
9427 Amat[0][1][1][1]=v[296];
9428 Amat[0][1][1][2]=v[297];
9429 Amat[0][1][2][0]=v[298];
9430 Amat[0][1][2][1]=v[299];
9431 Amat[0][1][2][2]=v[300];
9432 Amat[0][2][0][0]=v[286];
9433 Amat[0][2][0][1]=v[294];
9434 Amat[0][2][0][2]=F[0][1]*v[189]+F[0][0]*v[220]+v[321]+v[132]*v[140]*v[366];
9435 Amat[0][2][1][0]=v[302];
9436 Amat[0][2][1][1]=v[303];
9437 Amat[0][2][1][2]=v[304];
9438 Amat[0][2][2][0]=v[305];
9439 Amat[0][2][2][1]=v[306];
9440 Amat[0][2][2][2]=v[307];
9441 Amat[1][0][0][0]=v[287];
9442 Amat[1][0][0][1]=v[295];
9443 Amat[1][0][0][2]=v[302];
9444 Amat[1][0][1][0]=2e0*F[1][0]*v[169]+F[1][2]*v[224]+F[1][1]*v[261]+v[308];
9445 Amat[1][0][1][1]=v[310];
9446 Amat[1][0][1][2]=v[311];
9447 Amat[1][0][2][0]=v[312];
9448 Amat[1][0][2][1]=v[313];
9449 Amat[1][0][2][2]=v[314];
9450 Amat[1][1][0][0]=v[288];
9451 Amat[1][1][0][1]=v[296];
9452 Amat[1][1][0][2]=v[303];
9453 Amat[1][1][1][0]=v[310];
9454 Amat[1][1][1][1]=2e0*F[1][1]*v[157]+F[1][2]*v[194]+F[1][0]*v[265]+v[315];
9455 Amat[1][1][1][2]=v[317];
9456 Amat[1][1][2][0]=v[318];
9457 Amat[1][1][2][1]=v[319];
9458 Amat[1][1][2][2]=v[320];
9459 Amat[1][2][0][0]=v[289];
9460 Amat[1][2][0][1]=v[297];
9461 Amat[1][2][0][2]=v[304];
9462 Amat[1][2][1][0]=v[311];
9463 Amat[1][2][1][1]=v[317];
9464 Amat[1][2][1][2]=2e0*F[1][2]*v[146]+F[1][1]*v[198]+F[1][0]*v[231]+v[321];
9465 Amat[1][2][2][0]=v[323];
9466 Amat[1][2][2][1]=v[324];
9467 Amat[1][2][2][2]=v[325];
9468 Amat[2][0][0][0]=v[290];
9469 Amat[2][0][0][1]=v[298];
9470 Amat[2][0][0][2]=v[305];
9471 Amat[2][0][1][0]=v[312];
9472 Amat[2][0][1][1]=v[318];
9473 Amat[2][0][1][2]=v[323];
9474 Amat[2][0][2][0]=2e0*F[2][0]*v[174]+F[2][2]*v[235]+F[2][1]*v[274]+v[308];
9475 Amat[2][0][2][1]=v[327];
9476 Amat[2][0][2][2]=v[328];
9477 Amat[2][1][0][0]=v[291];
9478 Amat[2][1][0][1]=v[299];
9479 Amat[2][1][0][2]=v[306];
9480 Amat[2][1][1][0]=v[313];
9481 Amat[2][1][1][1]=v[319];
9482 Amat[2][1][1][2]=v[324];
9483 Amat[2][1][2][0]=v[327];
9484 Amat[2][1][2][1]=2e0*F[2][1]*v[161]+F[2][2]*v[203]+F[2][0]*v[278]+v[315];
9485 Amat[2][1][2][2]=v[330];
9486 Amat[2][2][0][0]=v[292];
9487 Amat[2][2][0][1]=v[300];
9488 Amat[2][2][0][2]=v[307];
9489 Amat[2][2][1][0]=v[314];
9490 Amat[2][2][1][1]=v[320];
9491 Amat[2][2][1][2]=v[325];
9492 Amat[2][2][2][0]=v[328];
9493 Amat[2][2][2][1]=v[330];
9494 Amat[2][2][2][2]=2e0*F[2][2]*v[149]+F[2][1]*v[207]+F[2][0]*v[242]+v[321];
9495};
9496
9497
9498/*************************************************************
9499 * AceGen 6.921 MacOSX (29 Jan 19) *
9500 * Co. J. Korelc 2013 17 Jul 19 15:09:55 *
9501 **************************************************************
9502 User : Full professional version
9503 Notebook : st_venant_kirchhoff_3d
9504 Evaluation time : 3 s Mode : Optimal
9505 Number of formulae : 91 Method: Automatic
9506 Subroutine : stvk3d size: 2846
9507 Total size of Mathematica code : 2846 subexpressions
9508 Total size of C code : 5830 bytes */
9509
9510/******************* S U B R O U T I N E *********************/
9511template <class SC, class LO, class GO, class NO>
9512void FE<SC,LO,GO,NO>::stvk3d(double* v,double (*lam),double (*mue),double** F
9513 ,double** Pmat,double**** Amat)
9514{
9515 v[169]=Power(F[0][0],2);
9516 v[168]=2e0*(*mue);
9517 v[167]=Power(F[0][2],2);
9518 v[166]=F[2][2]*(*mue);
9519 v[165]=F[2][1]*(*mue);
9520 v[164]=F[2][0]*(*mue);
9521 v[163]=F[1][2]*(*mue);
9522 v[162]=F[1][1]*(*mue);
9523 v[161]=F[1][0]*(*mue);
9524 v[88]=F[0][0]*(*mue);
9525 v[116]=F[0][0]*v[88];
9526 v[70]=F[0][1]*(*lam);
9527 v[93]=F[0][1]*(*mue);
9528 v[117]=F[0][1]*v[93];
9529 v[71]=F[0][2]*(*lam);
9530 v[105]=(*mue)*v[167];
9531 v[72]=F[1][0]*(*lam);
9532 v[85]=2e0*v[161]+v[72];
9533 v[142]=F[1][0]*v[161];
9534 v[121]=F[0][0]*v[161];
9535 v[73]=F[1][1]*(*lam);
9536 v[100]=F[0][1]*v[161]+F[0][0]*v[73];
9537 v[82]=2e0*v[162]+v[73];
9538 v[143]=F[1][1]*v[162];
9539 v[122]=F[0][1]*v[162];
9540 v[108]=F[0][0]*v[162]+F[0][1]*v[72];
9541 v[74]=F[1][2]*(*lam);
9542 v[111]=F[0][2]*v[162]+F[0][1]*v[74];
9543 v[101]=F[0][2]*v[161]+F[0][0]*v[74];
9544 v[79]=2e0*v[163]+v[74];
9545 v[123]=v[121]+v[122]+F[0][2]*v[79];
9546 v[135]=F[1][2]*v[163];
9547 v[120]=F[0][1]*v[163]+F[0][2]*v[73];
9548 v[119]=F[0][0]*v[163]+F[0][2]*v[72];
9549 v[109]=F[0][2]*v[163];
9550 v[110]=v[109]+v[121]+F[0][1]*v[82];
9551 v[99]=v[109]+v[122]+F[0][0]*v[85];
9552 v[75]=F[2][0]*(*lam);
9553 v[86]=2e0*v[164]+v[75];
9554 v[156]=F[2][0]*v[164];
9555 v[147]=F[1][0]*v[164];
9556 v[126]=F[0][0]*v[164];
9557 v[76]=F[2][1]*(*lam);
9558 v[133]=F[1][1]*v[164]+F[1][0]*v[76];
9559 v[103]=F[0][1]*v[164]+F[0][0]*v[76];
9560 v[83]=2e0*v[165]+v[76];
9561 v[157]=F[2][1]*v[165];
9562 v[148]=F[1][1]*v[165];
9563 v[138]=F[1][0]*v[165]+F[1][1]*v[75];
9564 v[127]=F[0][1]*v[165];
9565 v[112]=F[0][0]*v[165]+F[0][1]*v[75];
9566 v[77]=F[2][2]*(*lam);
9567 v[141]=F[1][2]*v[165]+F[1][1]*v[77];
9568 v[134]=F[1][2]*v[164]+F[1][0]*v[77];
9569 v[115]=F[0][2]*v[165]+F[0][1]*v[77];
9570 v[104]=F[0][2]*v[164]+F[0][0]*v[77];
9571 v[80]=2e0*v[166]+v[77];
9572 v[149]=v[147]+v[148]+F[1][2]*v[80];
9573 v[128]=v[126]+v[127]+F[0][2]*v[80];
9574 v[153]=F[2][2]*v[166];
9575 v[146]=F[1][1]*v[166]+F[1][2]*v[76];
9576 v[145]=F[1][0]*v[166]+F[1][2]*v[75];
9577 v[139]=F[1][2]*v[166];
9578 v[140]=v[139]+v[147]+F[1][1]*v[83];
9579 v[132]=v[139]+v[148]+F[1][0]*v[86];
9580 v[125]=F[0][1]*v[166]+F[0][2]*v[76];
9581 v[124]=F[0][0]*v[166]+F[0][2]*v[75];
9582 v[113]=F[0][2]*v[166];
9583 v[114]=v[113]+v[126]+F[0][1]*v[83];
9584 v[102]=v[113]+v[127]+F[0][0]*v[86];
9585 v[24]=(-1e0+Power(F[1][0],2)+Power(F[2][0],2)+v[169])/2e0;
9586 v[28]=(-1e0+Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2))/2e0;
9587 v[32]=(-1e0+Power(F[1][2],2)+Power(F[2][2],2)+v[167])/2e0;
9588 v[36]=(*lam)*(v[24]+v[28]+v[32]);
9589 v[35]=2e0*(*mue)*v[32]+v[36];
9590 v[37]=2e0*(*mue)*v[28]+v[36];
9591 v[38]=2e0*(*mue)*v[24]+v[36];
9592 v[39]=(F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2])*(*mue);
9593 v[152]=F[2][2]*v[164]+v[39]+F[2][0]*v[77];
9594 v[131]=F[1][2]*v[161]+v[39]+F[1][0]*v[74];
9595 v[98]=v[39]+F[0][0]*v[71]+F[0][2]*v[88];
9596 v[40]=(F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2])*(*mue);
9597 v[155]=F[2][2]*v[165]+v[40]+F[2][1]*v[77];
9598 v[137]=F[1][2]*v[162]+v[40]+F[1][1]*v[74];
9599 v[107]=v[40]+F[0][1]*v[71]+F[0][2]*v[93];
9600 v[41]=(F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1])*(*mue);
9601 v[151]=F[2][1]*v[164]+v[41]+F[2][0]*v[76];
9602 v[130]=F[1][1]*v[161]+v[41]+F[1][0]*v[73];
9603 v[97]=v[41]+F[0][0]*v[70]+F[0][1]*v[88];
9604 Pmat[0][0]=F[0][0]*v[38]+F[0][2]*v[39]+F[0][1]*v[41];
9605 Pmat[0][1]=F[0][1]*v[37]+F[0][2]*v[40]+F[0][0]*v[41];
9606 Pmat[0][2]=F[0][2]*v[35]+F[0][0]*v[39]+F[0][1]*v[40];
9607 Pmat[1][0]=F[1][0]*v[38]+F[1][2]*v[39]+F[1][1]*v[41];
9608 Pmat[1][1]=F[1][1]*v[37]+F[1][2]*v[40]+F[1][0]*v[41];
9609 Pmat[1][2]=F[1][2]*v[35]+F[1][0]*v[39]+F[1][1]*v[40];
9610 Pmat[2][0]=F[2][0]*v[38]+F[2][2]*v[39]+F[2][1]*v[41];
9611 Pmat[2][1]=F[2][1]*v[37]+F[2][2]*v[40]+F[2][0]*v[41];
9612 Pmat[2][2]=F[2][2]*v[35]+F[2][0]*v[39]+F[2][1]*v[40];
9613 Amat[0][0][0][0]=v[105]+v[117]+((*lam)+v[168])*v[169]+v[38];
9614 Amat[0][0][0][1]=v[97];
9615 Amat[0][0][0][2]=v[98];
9616 Amat[0][0][1][0]=v[99];
9617 Amat[0][0][1][1]=v[100];
9618 Amat[0][0][1][2]=v[101];
9619 Amat[0][0][2][0]=v[102];
9620 Amat[0][0][2][1]=v[103];
9621 Amat[0][0][2][2]=v[104];
9622 Amat[0][1][0][0]=v[97];
9623 Amat[0][1][0][1]=v[105]+v[116]+v[37]+F[0][1]*(v[70]+2e0*v[93]);
9624 Amat[0][1][0][2]=v[107];
9625 Amat[0][1][1][0]=v[108];
9626 Amat[0][1][1][1]=v[110];
9627 Amat[0][1][1][2]=v[111];
9628 Amat[0][1][2][0]=v[112];
9629 Amat[0][1][2][1]=v[114];
9630 Amat[0][1][2][2]=v[115];
9631 Amat[0][2][0][0]=v[98];
9632 Amat[0][2][0][1]=v[107];
9633 Amat[0][2][0][2]=v[116]+v[117]+v[35]+F[0][2]*(F[0][2]*v[168]+v[71]);
9634 Amat[0][2][1][0]=v[119];
9635 Amat[0][2][1][1]=v[120];
9636 Amat[0][2][1][2]=v[123];
9637 Amat[0][2][2][0]=v[124];
9638 Amat[0][2][2][1]=v[125];
9639 Amat[0][2][2][2]=v[128];
9640 Amat[1][0][0][0]=v[99];
9641 Amat[1][0][0][1]=v[108];
9642 Amat[1][0][0][2]=v[119];
9643 Amat[1][0][1][0]=v[135]+v[143]+v[38]+F[1][0]*v[85];
9644 Amat[1][0][1][1]=v[130];
9645 Amat[1][0][1][2]=v[131];
9646 Amat[1][0][2][0]=v[132];
9647 Amat[1][0][2][1]=v[133];
9648 Amat[1][0][2][2]=v[134];
9649 Amat[1][1][0][0]=v[100];
9650 Amat[1][1][0][1]=v[110];
9651 Amat[1][1][0][2]=v[120];
9652 Amat[1][1][1][0]=v[130];
9653 Amat[1][1][1][1]=v[135]+v[142]+v[37]+F[1][1]*v[82];
9654 Amat[1][1][1][2]=v[137];
9655 Amat[1][1][2][0]=v[138];
9656 Amat[1][1][2][1]=v[140];
9657 Amat[1][1][2][2]=v[141];
9658 Amat[1][2][0][0]=v[101];
9659 Amat[1][2][0][1]=v[111];
9660 Amat[1][2][0][2]=v[123];
9661 Amat[1][2][1][0]=v[131];
9662 Amat[1][2][1][1]=v[137];
9663 Amat[1][2][1][2]=v[142]+v[143]+v[35]+F[1][2]*v[79];
9664 Amat[1][2][2][0]=v[145];
9665 Amat[1][2][2][1]=v[146];
9666 Amat[1][2][2][2]=v[149];
9667 Amat[2][0][0][0]=v[102];
9668 Amat[2][0][0][1]=v[112];
9669 Amat[2][0][0][2]=v[124];
9670 Amat[2][0][1][0]=v[132];
9671 Amat[2][0][1][1]=v[138];
9672 Amat[2][0][1][2]=v[145];
9673 Amat[2][0][2][0]=v[153]+v[157]+v[38]+F[2][0]*v[86];
9674 Amat[2][0][2][1]=v[151];
9675 Amat[2][0][2][2]=v[152];
9676 Amat[2][1][0][0]=v[103];
9677 Amat[2][1][0][1]=v[114];
9678 Amat[2][1][0][2]=v[125];
9679 Amat[2][1][1][0]=v[133];
9680 Amat[2][1][1][1]=v[140];
9681 Amat[2][1][1][2]=v[146];
9682 Amat[2][1][2][0]=v[151];
9683 Amat[2][1][2][1]=v[153]+v[156]+v[37]+F[2][1]*v[83];
9684 Amat[2][1][2][2]=v[155];
9685 Amat[2][2][0][0]=v[104];
9686 Amat[2][2][0][1]=v[115];
9687 Amat[2][2][0][2]=v[128];
9688 Amat[2][2][1][0]=v[134];
9689 Amat[2][2][1][1]=v[141];
9690 Amat[2][2][1][2]=v[149];
9691 Amat[2][2][2][0]=v[152];
9692 Amat[2][2][2][1]=v[155];
9693 Amat[2][2][2][2]=v[156]+v[157]+v[35]+F[2][2]*v[80];
9694};
9695/*************************************************************
9696 * AceGen 6.921 MacOSX (29 Jan 19) *
9697 * Co. J. Korelc 2013 17 Jul 19 16:01:42 *
9698 **************************************************************
9699 User : Full professional version
9700 Notebook : st_venant_kirchhoff_2d
9701 Evaluation time : 1 s Mode : Optimal
9702 Number of formulae : 25 Method: Automatic
9703 Subroutine : stvk2d size: 772
9704 Total size of Mathematica code : 772 subexpressions
9705 Total size of C code : 1672 bytes */
9706
9707
9708/******************* S U B R O U T I N E *********************/
9709template <class SC, class LO, class GO, class NO>
9710void FE<SC,LO,GO,NO>::stvk2d(double* v, double (*lam),double (*mue),double** F
9711 ,double** Pmat,double**** Amat)
9712{
9713 v[43]=F[0][0]*F[1][0];
9714 v[42]=F[0][1]*F[1][1];
9715 v[37]=Power(F[0][0],2);
9716 v[12]=F[0][0]/2e0;
9717 v[36]=Power(F[0][1],2);
9718 v[34]=F[0][0]*F[0][1];
9719 v[11]=F[0][1]/2e0;
9720 v[27]=Power(F[1][0],2);
9721 v[31]=-1e0+v[27]+v[37];
9722 v[14]=F[1][0]/2e0;
9723 v[25]=Power(F[1][1],2);
9724 v[26]=-1e0+v[25]+v[36];
9725 v[23]=F[1][0]*F[1][1];
9726 v[22]=v[23]+v[34];
9727 v[35]=(*lam)*v[34]+(*mue)*(v[22]+v[34]);
9728 v[24]=(*lam)*v[23]+(*mue)*(v[22]+v[23]);
9729 v[21]=(*lam)*v[42]+2e0*(*mue)*(2e0*v[12]*v[14]+v[42]);
9730 v[20]=F[0][0]*F[1][1]*(*lam)+4e0*(*mue)*v[11]*v[14];
9731 v[13]=F[1][1]/2e0;
9732 v[30]=F[0][1]*F[1][0]*(*lam)+4e0*(*mue)*v[12]*v[13];
9733 v[29]=(*lam)*v[43]+2e0*(*mue)*(2e0*v[11]*v[13]+v[43]);
9734 v[44]=2e0*v[22];
9735 v[32]=((*lam)*(v[26]+v[31]))/2e0;
9736 Pmat[0][0]=F[0][0]*v[32]+(*mue)*(F[0][0]*v[31]+v[11]*v[44]);
9737 Pmat[0][1]=F[0][1]*v[32]+(*mue)*(F[0][1]*v[26]+v[12]*v[44]);
9738 Pmat[1][0]=F[1][0]*v[32]+(*mue)*(F[1][0]*v[31]+v[13]*v[44]);
9739 Pmat[1][1]=F[1][1]*v[32]+(*mue)*(F[1][1]*v[26]+v[14]*v[44]);
9740 Amat[0][0][0][0]=v[32]+(*lam)*v[37]+(*mue)*(v[31]+v[36]+2e0*v[37]);
9741 Amat[0][0][0][1]=v[35];
9742 Amat[0][0][1][0]=v[29];
9743 Amat[0][0][1][1]=v[20];
9744 Amat[0][1][0][0]=v[35];
9745 Amat[0][1][0][1]=v[32]+(*lam)*v[36]+(*mue)*(v[26]+2e0*v[36]+v[37]);
9746 Amat[0][1][1][0]=v[30];
9747 Amat[0][1][1][1]=v[21];
9748 Amat[1][0][0][0]=v[29];
9749 Amat[1][0][0][1]=v[30];
9750 Amat[1][0][1][0]=(*lam)*v[27]+(*mue)*(v[25]+2e0*v[27]+v[31])+v[32];
9751 Amat[1][0][1][1]=v[24];
9752 Amat[1][1][0][0]=v[20];
9753 Amat[1][1][0][1]=v[21];
9754 Amat[1][1][1][0]=v[24];
9755 Amat[1][1][1][1]=(*lam)*v[25]+(*mue)*(2e0*v[25]+v[26]+v[27])+v[32];
9756};
9757
9758}
9759#endif
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:8184
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:3895
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:3982
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:4471
void changeLinearizationFE(std::string linearization)
Method to loop over all assembleFESpecific elements and set the defined linearization.
Definition FE_def.hpp:1246
void assemblyAceDeformDiffuBlock(int dim, std::string FETypeChem, std::string FETypeSolid, int degree, int dofsChem, int dofsSolid, MultiVectorPtr_Type c_rep, MultiVectorPtr_Type d_rep, BlockMatrixPtr_Type &A, int blockRow, int blockCol, BlockMultiVectorPtr_Type &resVec, int block, ParameterListPtr_Type params, std::string assembleMode, bool callFillComplete=true, int FELocExternal=-1)
Definition FE_def.hpp:822
void assemblyNonLinearElasticity(int dim, std::string FEType, int degree, int dofs, MultiVectorPtr_Type d_rep, BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec, ParameterListPtr_Type params, bool callFillComplete=true, int FELocExternal=-1)
Assembly of Jacobian for nonlinear Elasticity.
Definition FE_def.hpp:449
void assemblyLinearElasticity(int dim, std::string FEType, int degree, int dofs, MultiVectorPtr_Type d_rep, BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec, ParameterListPtr_Type params, bool reAssemble, std::string assembleMode, bool callFillComplete=true, int FELocExternal=-1)
Assembly of Jacobian.
Definition FE_def.hpp:362
void assemblyBDStabilization(int dim, std::string FEType, MatrixPtr_Type &A, bool callFillComplete=true)
Bochev- Dohrmann Stabilization.
Definition FE_def.hpp:4206
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:4112
void assemblyLaplaceXDim(int dim, std::string FEType, MatrixPtr_Type &A, CoeffFuncDbl_Type func, double *parameters, bool callFillComplete=true)
Definition FE_def.hpp:4289
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:3710
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:3804
void computeSteadyViscosityFE_CM(int dim, std::string FETypeVelocity, std::string FETypePressure, int dofsVelocity, int dofsPressure, MultiVectorPtr_Type u_rep, MultiVectorPtr_Type p_rep, ParameterListPtr_Type params)
Postprocessing: Using a converged velocity solution -> compute averaged viscosity inside an element a...
Definition FE_def.hpp:1266
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:6320
void assemblyNonlinearLaplace(int dim, std::string FEType, int degree, MultiVectorPtr_Type u_rep, BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec, ParameterListPtr_Type params, std::string assembleMode, bool callFillComplete=true, int FELocExternal=-1)
Assembly of Jacobian for nonlinear Laplace example.
Definition FE_def.hpp:2749
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:6632
void assemblyNavierStokes(int dim, std::string FETypeVelocity, std::string FETypePressure, int degree, int dofsVelocity, int dofsPressure, MultiVectorPtr_Type u_rep, MultiVectorPtr_Type p_rep, BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec, SmallMatrix_Type coeff, ParameterListPtr_Type params, bool reAssemble, std::string assembleMode, bool callFillComplete=true, int FELocExternal=-1)
Assembly of Jacobian for NavierStokes.
Definition FE_def.hpp:1078
void assemblyLaplaceAssFE(int dim, std::string FEType, int degree, int dofs, BlockMatrixPtr_Type &A, bool callFillComplete, int FELocExternal=-1)
Assembly of constant stiffness matix for laplacian operator .
Definition FE_def.hpp:1877
void assemblyLinElasXDim(int dim, std::string FEType, MatrixPtr_Type &A, double lambda, double mu, bool callFillComplete=true)
Definition FE_def.hpp:5965
void assemblyAceDeformDiffu(int dim, std::string FETypeChem, std::string FETypeSolid, int degree, int dofsChem, int dofsSolid, MultiVectorPtr_Type c_rep, MultiVectorPtr_Type d_rep, BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec, ParameterListPtr_Type params, std::string assembleMode, bool callFillComplete=true, int FELocExternal=-1)
Definition FE_def.hpp:644
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:8649
Definition FiniteElement.hpp:17
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
@ 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 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