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#ifdef FEDD_HAVE_ACEGENINTERFACE
5#include <aceinterface.hpp>
6#endif
7
8#include "FE_decl.hpp"
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);
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();
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
309 }
310 }
311
312 }
313 }
315
316*/
317
322
323@param[in] res BlockMultiVector of residual vec; Repeated distribution; 2 blocks
324@param[in] rhsVec sorted the same way as residual vec
325@param[in] element of block1
326
327*/
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];
344 }
345 }
346}
347*/
348
351 \brief Assembly of Jacobian for Linear Elasticity
352@param[in] dim Dimension
353@param[in] FEType FE Discretization
354@param[in] degree Degree of basis function
355@param[in] A Resulting matrix
356@param[in] callFillComplete If Matrix A should be completely filled at end of function
357@param[in] FELocExternal
359*/
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();
378
379 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(0)->getPointsRepeated();
381 MapConstPtr_Type mapVel = domainVec_.at(0)->getMapRepeated();
382
383 vec_dbl_Type solution(0);
384 vec_dbl_Type solution_d;
385
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);
407
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
431
432
433
434}
435
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();
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
527 \brief Assembly of Jacobian for nonlinear Elasticity
528@param[in] dim Dimension
529@param[in] FEType FE Discretization
530@param[in] degree Degree of basis function
531@param[in] A Resulting matrix
532@param[in] callFillComplete If Matrix A should be completely filled at end of function
533@param[in] FELocExternal
534
535*/
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() );
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}
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();
673
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
1249
1250
1251template <class SC, class LO, class GO, class NO>
1253 std::string FETypeVelocity,
1254 std::string FETypePressure,
1255 int dofsVelocity,
1256 int dofsPressure,
1257 MultiVectorPtr_Type u_rep,
1258 MultiVectorPtr_Type p_rep,
1259 ParameterListPtr_Type params){
1260
1261
1262 UN FElocVel = checkFE(dim,FETypeVelocity); // Checks for different domains which belongs to a certain fetype
1263 UN FElocPres = checkFE(dim,FETypePressure); // Checks for different domains which belongs to a certain fetype
1264
1265 ElementsPtr_Type elements = domainVec_.at(FElocVel)->getElementsC();
1266 ElementsPtr_Type elementsPres = domainVec_.at(FElocPres)->getElementsC();
1267
1268 vec_dbl_Type solution(0);
1269 vec_dbl_Type solution_u;
1270 vec_dbl_Type solution_p;
1271 vec_dbl_Type solution_viscosity;
1272
1273 // We have to compute viscosity solution in each element
1274 MultiVectorPtr_Type Sol_viscosity = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getElementMap(), 1 ) ); //
1275 BlockMultiVectorPtr_Type visco_output = Teuchos::rcp( new BlockMultiVector_Type(1) );
1276 visco_output->addBlock(Sol_viscosity,0);
1277
1278
1279 for (UN T=0; T<assemblyFEElements_.size(); T++) {
1280
1281 vec_dbl_Type solution(0);
1282 solution_u = getSolution(elements->getElement(T).getVectorNodeList(), u_rep,dofsVelocity); // get the solution inside an element on the nodes
1283 solution_p = getSolution(elementsPres->getElement(T).getVectorNodeList(), p_rep,dofsPressure);
1284
1285 solution.insert( solution.end(), solution_u.begin(), solution_u.end() ); // here we insert the solution
1286 solution.insert( solution.end(), solution_p.begin(), solution_p.end() );
1287
1288 assemblyFEElements_[T]->updateSolution(solution); // here we update the value of the solutions inside an element
1289
1290 assemblyFEElements_[T]->computeLocalconstOutputField(); // we compute the viscosity inside an element
1291 solution_viscosity = assemblyFEElements_[T]->getLocalconstOutputField();
1292
1293 Teuchos::ArrayRCP<SC> resArray_block = visco_output->getBlockNonConst(0)->getDataNonConst(0); // First
1294 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
1295
1296 } // end loop over all elements
1297 // 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
1298 this->const_output_fields= visco_output;
1299
1300
1301}
1302
1303
1304
1315
1316template <class SC, class LO, class GO, class NO>
1317void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec, FiniteElement elementBlock1,FiniteElement elementBlock2, int dofs1, int dofs2 ){
1318
1319 Teuchos::ArrayRCP<SC> resArray_block1 = res->getBlockNonConst(0)->getDataNonConst(0);
1320
1321 Teuchos::ArrayRCP<SC> resArray_block2 = res->getBlockNonConst(1)->getDataNonConst(0);
1322
1323 vec_LO_Type nodeList_block1 = elementBlock1.getVectorNodeList();
1324
1325 vec_LO_Type nodeList_block2 = elementBlock2.getVectorNodeList();
1326
1327 for(int i=0; i< nodeList_block1.size() ; i++){
1328 for(int d=0; d<dofs1; d++){
1329 resArray_block1[nodeList_block1[i]*dofs1+d] += (*rhsVec)[i*dofs1+d];
1330 }
1331 }
1332 int offset = nodeList_block1.size()*dofs1;
1333
1334 for(int i=0; i < nodeList_block2.size(); i++){
1335 for(int d=0; d<dofs2; d++)
1336 resArray_block2[nodeList_block2[i]*dofs2+d] += (*rhsVec)[i*dofs2+d+offset];
1337 }
1338
1339}
1340
1341
1354template <class SC, class LO, class GO, class NO>
1355void 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){
1356
1357 int dofs1 = std::get<2>(problemDisk->at(row));
1358
1359 int numNodes1 = std::get<3>(problemDisk->at(row));
1360
1361 int dofsBlock1 = dofs1*numNodes1;
1362
1363 Teuchos::Array<SC> value( numNodes1, 0. );
1364 Teuchos::Array<GO> columnIndices( numNodes1, 0 );
1365
1366 for (UN i=0; i < numNodes1 ; i++) {
1367 for(int di=0; di<dofs1; di++){
1368 GO rowID =GO (dofs1* mapRow->getGlobalElement( element.getNode(i) )+di);
1369 for(int d=0; d<dofs1; d++){
1370 for (UN j=0; j < columnIndices.size(); j++){
1371 columnIndices[j] = GO ( dofs1 * mapRow->getGlobalElement( element.getNode(j) ) + d );
1372 value[j] = (*elementMatrix)[dofs1*i+di][dofs1*j+d];
1373 }
1374 A->getBlock(row,column)->insertGlobalValues( rowID, columnIndices(), value() ); // Automatically adds entries if a value already exists
1375 }
1376 }
1377 }
1378}
1379
1390template <class SC, class LO, class GO, class NO>
1391void 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){
1392
1393 vec2D_dbl_Type nodes;
1394 for (UN T=0; T<elements->numberElements(); T++) {
1395
1396 nodes = getCoordinates(elements->getElement(T).getVectorNodeList(), pointsRep);
1397
1398 AssembleFEFactory<SC,LO,GO,NO> assembleFEFactory;
1399
1400 AssembleFEPtr_Type assemblyFE = assembleFEFactory.build(elementType,elements->getElement(T).getFlag(),nodes, params,problemDisk);
1401 //
1402 assemblyFE->setGlobalElementID(elementMap->getGlobalElement(T));
1403
1404 assemblyFEElements_.push_back(assemblyFE);
1405
1406 }
1407
1408}
1409
1419
1420template <class SC, class LO, class GO, class NO>
1421vec2D_dbl_Type FE<SC,LO,GO,NO>::getCoordinates(vec_LO_Type localIDs, vec2D_dbl_ptr_Type points){
1422
1423 vec2D_dbl_Type coordinates(0,vec_dbl_Type( points->at(0).size()));
1424 for(int i=0; i < localIDs.size() ; i++){
1425 coordinates.push_back(points->at(localIDs[i]));
1426 }
1427
1428 return coordinates;
1429}
1430
1440
1441template <class SC, class LO, class GO, class NO>
1442vec_dbl_Type FE<SC,LO,GO,NO>::getSolution(vec_LO_Type localIDs, MultiVectorPtr_Type u_rep, int dofsVelocity){
1443
1444 Teuchos::ArrayRCP<SC> uArray = u_rep->getDataNonConst(0);
1445
1446 vec_dbl_Type solution(0);
1447 for(int i=0; i < localIDs.size() ; i++){
1448 for(int d=0; d<dofsVelocity; d++)
1449 solution.push_back(uArray[localIDs[i]*dofsVelocity+d]);
1450 }
1451
1452 return solution;
1453}
1454
1455
1456template <class SC, class LO, class GO, class NO>
1457void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
1458 vec3D_dbl_Type& dPhiOut,
1459 const SmallMatrix<SC>& Binv){
1460 UN dim = Binv.size();
1461 for (UN w=0; w<dPhiIn->size(); w++){
1462 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
1463 for (UN d1=0; d1<dim; d1++) {
1464 for (UN d2=0; d2<dim; d2++) {
1465 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
1466 }
1467 }
1468 }
1469 }
1470}
1471
1472template <class SC, class LO, class GO, class NO>
1473void FE<SC,LO,GO,NO>::assemblyEmptyMatrix(MatrixPtr_Type &A){
1474 A->fillComplete();
1475}
1476template <class SC, class LO, class GO, class NO>
1477void FE<SC,LO,GO,NO>::assemblyIdentity(MatrixPtr_Type &A){
1478 Teuchos::Array<SC> value(1, Teuchos::ScalarTraits<SC>::one() );
1479 Teuchos::Array<GO> index(1);
1480 MapConstPtr_Type map = A->getMap();
1481 for (int i=0; i<A->getNodeNumRows(); i++) {
1482 index[0] = map->getGlobalElement( i );
1483 A->insertGlobalValues( index[0], index(), value() );
1484 }
1485 A->fillComplete();
1486}
1487
1488
1489template <class SC, class LO, class GO, class NO>
1490void FE<SC,LO,GO,NO>::assemblySurfaceRobinBC(int dim,
1491 std::string FETypeP,
1492 std::string FETypeV,
1493 MultiVectorPtr_Type u,
1494 MatrixPtr_Type A,
1495 std::vector<SC>& funcParameter,
1496 RhsFunc_Type func,
1497 ParameterListPtr_Type parameters){
1498
1499 ElementsPtr_Type elements = domainVec_.at(1)->getElementsC();
1500 ElementsPtr_Type elementsV = domainVec_.at(0)->getElementsC();
1501
1502 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(1)->getPointsRepeated();
1503
1504 MapConstPtr_Type map = domainVec_.at(1)->getMapRepeated();
1505
1506 vec2D_dbl_ptr_Type phi,phiV;
1507 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1508
1509
1510 UN extraDeg = Helper::determineDegree( dim-1, FETypeV, Helper::Deriv0);
1511 UN deg = Helper::determineDegree( dim-1, FETypeP, Helper::Deriv0)*2 + extraDeg;
1512
1513
1514 Helper::getPhi(phi, weights, dim-1, FETypeP, deg);
1515 Helper::getPhi(phiV, weights, dim-1, FETypeV, deg);
1516
1517 SC detB;
1518 SC absDetB;
1519 SmallMatrix<SC> B(dim);
1520
1521
1522 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
1523 vec_dbl_Type uLocN( weights->size() , -1. );
1524
1525 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1526
1527
1528 SC elScaling;
1529 vec_dbl_Type b(dim);
1530
1531 std::vector<double> valueFunc(dim);
1532 // The second last entry is a placeholder for the surface element flag. It will be set below
1533 SC* paramsFunc = &(funcParameter[0]);
1534 for (UN T=0; T<elements->numberElements(); T++) {
1535 FiniteElement fe = elementsV->getElement( T );
1536 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
1537 for (int surface=0; surface<fe.numSubElements(); surface++) {
1538 FiniteElement feSub = subEl->getElement( surface );
1539 if(subEl->getDimension() == dim-1){
1540 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
1541
1542 vec_int_Type nodeList = feSub.getVectorNodeListNonConst();
1543 vec_int_Type nodeListP = elements->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
1544
1545 vec_dbl_Type v_E(dim,1.);
1546 double norm_v_E=1.;
1547 vec_dbl_Type x(dim,0.); //dummy
1548 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
1549
1550 func( &x[0], &valueFunc[0], paramsFunc);
1551 if(valueFunc[0] > 0.){
1552 Helper::computeSurfaceNormal(dim, pointsRep,nodeListP,v_E,norm_v_E);
1553
1554 Helper::buildTransformationSurface( nodeListP, pointsRep, B, b, FETypeP);
1555
1556 elScaling = B.computeScaling( );
1557 for (int w=0; w<phiV->size(); w++){ //quads points
1558 for (int d=0; d<dim; d++) {
1559 uLoc[d][w] = 0.;
1560 for (int i=0; i < phiV->at(0).size(); i++) {
1561 LO index = dim * nodeList[i] + d;
1562 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
1563 }
1564 }
1565 }
1566 for (int w=0; w<phiV->size(); w++){ //quads points
1567 uLocN[w] = 0.;
1568 for (int d=0; d<dim; d++) {
1569 uLocN[w] += uLoc[d][w] *v_E[d] / norm_v_E;
1570 }
1571 }
1572 for (UN i=0; i < phi->at(0).size(); i++) {
1573 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1574 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1575 for (UN j=0; j < value.size(); j++) {
1576 for (UN w=0; w<phi->size(); w++) {
1577 value[j] += weights->at(w) * uLocN[w]* (*phi)[w][j] * (*phi)[w][i] ;
1578 }
1579 value[j] *= elScaling;
1580 indices[j] = GO ( map->getGlobalElement( nodeListP[j] ) );
1581 }
1582
1583 GO row = GO ( map->getGlobalElement( nodeListP[i] ) );
1584 A->insertGlobalValues( row, indices(), value() );
1585 }
1586
1587 }
1588 }
1589 }
1590 }
1591 A->fillComplete();
1592}
1593
1594// Assembling the nonlinear reaction part of Reaction-Diffusion equation
1595// Gerneral function in case of nonlinear reaction function
1596// template <class SC, class LO, class GO, class NO>
1597// void FE<SC,LO,GO,NO>::assemblyReactionTerm(int dim,
1598// std::string FEType,
1599// MatrixPtr_Type &A,
1600// MultiVectorPtr_Type u,
1601// bool callFillComplete,
1602// std::vector<SC>& funcParameter,
1603// RhsFunc_Type reactionFunc){
1604
1605// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1606// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1607
1608// UN FEloc = checkFE(dim,FEType);
1609
1610// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1611
1612// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1613
1614// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1615
1616// vec2D_dbl_ptr_Type phi;
1617// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1618
1619// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1620
1621// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1622// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1623// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1624// extraDeg;
1625
1626// Helper::getPhi(phi, weights, dim, FEType, deg);
1627
1628// // We have a scalar value of concentration in each point
1629// vec_dbl_Type uLoc( weights->size() , -1. );
1630// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1631
1632// std::vector<double> valueFunc(1);
1633
1634// SC* paras = &(funcParameter[0]);
1635
1636// SC detB;
1637// SC absDetB;
1638// SmallMatrix<SC> B(dim);
1639// SmallMatrix<SC> Binv(dim);
1640
1641// for (UN T=0; T<elements->numberElements(); T++) {
1642// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1643// detB = B.computeInverse(Binv);
1644// absDetB = std::fabs(detB);
1645
1646// // Building u
1647// for (int w=0; w<phi->size(); w++){ //quadpoints
1648// uLoc[w] = 0.;
1649// for (int i=0; i < phi->at(0).size(); i++) { // points of element
1650// LO index = elements->getElement(T).getNode(i);
1651// uLoc[w] += uArray[index] * phi->at(w).at(i);
1652// }
1653// }
1654
1655// for (UN i=0; i < phi->at(0).size(); i++) {
1656// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1657// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1658// for (UN j=0; j < value.size(); j++) {
1659// for (UN w=0; w<phi->size(); w++) {
1660// value[j] += weights->at(w) * uLoc[w] * (*phi)[w][i] ;
1661// }
1662// reactionFunc(&value[j], &valueFunc[0] ,paras);
1663
1664// value[j] *= valueFunc[0] * absDetB;
1665// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1666// value[j] = 0.;
1667// }
1668// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1669
1670// }
1671// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1672
1673
1674// A->insertGlobalValues( row, indices(), value() );
1675
1676// }
1677// }
1678
1679// if (callFillComplete)
1680// A->fillComplete();
1681// }
1682
1683
1684// // Assembling the nonlinear reaction part of Reaction-Diffusion equation
1685// template <class SC, class LO, class GO, class NO>
1686// void FE<SC,LO,GO,NO>::assemblyLinearReactionTerm(int dim,
1687// std::string FEType,
1688// MatrixPtr_Type &A,
1689// bool callFillComplete,
1690// std::vector<SC>& funcParameter,
1691// RhsFunc_Type reactionFunc){
1692
1693// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1694// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1695
1696// UN FEloc = checkFE(dim,FEType);
1697
1698// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1699
1700// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1701
1702// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1703
1704// vec2D_dbl_ptr_Type phi;
1705// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1706
1707// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1708// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1709// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1710// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1711// extraDeg;
1712
1713// Helper::getPhi(phi, weights, dim, FEType, deg);
1714
1715// std::vector<double> valueFunc(1);
1716
1717// SC* paras = &(funcParameter[0]);
1718
1719// SC detB;
1720// SC absDetB;
1721// SmallMatrix<SC> B(dim);
1722// SmallMatrix<SC> Binv(dim);
1723
1724// for (UN T=0; T<elements->numberElements(); T++) {
1725// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1726// detB = B.computeInverse(Binv);
1727// absDetB = std::fabs(detB);
1728
1729// for (UN i=0; i < phi->at(0).size(); i++) {
1730// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1731// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1732// for (UN j=0; j < value.size(); j++) {
1733// for (UN w=0; w<phi->size(); w++) {
1734// value[j] += weights->at(w) * (*phi)[w][j] * (*phi)[w][i] ;
1735// }
1736// reactionFunc(&value[j], &valueFunc[0] ,paras);
1737
1738// value[j] *= valueFunc[0] * absDetB;
1739// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1740// value[j] = 0.;
1741// }
1742// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1743
1744// }
1745// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1746
1747// A->insertGlobalValues( row, indices(), value() );
1748
1749// }
1750// }
1751// if (callFillComplete)
1752// A->fillComplete();
1753
1754// A->print();
1755
1756// }
1757
1758// Assembling the nonlinear reaction part of Reaction-Diffusion equation
1759// template <class SC, class LO, class GO, class NO>
1760// void FE<SC,LO,GO,NO>::assemblyDReactionTerm(int dim,
1761// std::string FEType,
1762// MatrixPtr_Type &A,
1763// MultiVectorPtr_Type u,
1764// bool callFillComplete,
1765// std::vector<SC>& funcParameter,
1766// RhsFunc_Type reactionFunc){
1767
1768// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1769// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1770
1771// UN FEloc = checkFE(dim,FEType);
1772
1773// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1774
1775// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1776
1777// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1778
1779// vec2D_dbl_ptr_Type phi;
1780// vec3D_dbl_ptr_Type dPhi;
1781// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1782
1783// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1784// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1785// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1786// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1787// extraDeg;
1788
1789// Helper::getPhi(phi, weights, dim, FEType, deg);
1790
1791// Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1792
1793// // We have a scalar value of concentration in each point
1794// vec2D_dbl_Type duLoc( weights->size() ,vec_dbl_Type(dim ,-1. ));
1795// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1796
1797// std::vector<double> valueFunc(1);
1798
1799// SC* paras = &(funcParameter[0]);
1800
1801// SC detB;
1802// SC absDetB;
1803// SmallMatrix<SC> B(dim);
1804// SmallMatrix<SC> Binv(dim);
1805
1806// for (UN T=0; T<elements->numberElements(); T++) {
1807
1808
1809// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1810// detB = B.computeInverse(Binv);
1811// absDetB = std::fabs(detB);
1812
1813// vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1814// applyBTinv( dPhi, dPhiTrans, Binv );
1815
1816// for (int w=0; w<dPhiTrans.size(); w++){ //quads points
1817// for (int i=0; i < dPhiTrans[0].size(); i++) {
1818// LO index = elements->getElement(T).getNode(i) ;
1819// for (int d2=0; d2<dim; d2++)
1820// duLoc[w][d2] += uArray[index] * dPhiTrans[w][i][d2];
1821// }
1822
1823// }
1824
1825
1826// for (UN i=0; i < phi->at(0).size(); i++) {
1827// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1828// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1829// for (UN j=0; j < value.size(); j++) {
1830// for (UN d2=0; d2<dim; d2++){
1831// for (UN w=0; w<phi->size(); w++) {
1832// value[j] += weights->at(w) * duLoc[w][d2] * (*phi)[w][i] ;
1833// }
1834// }
1835// reactionFunc(&value[j], &valueFunc[0] ,paras);
1836
1837// value[j] *= valueFunc[0] * absDetB;
1838// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1839// value[j] = 0.;
1840// }
1841// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1842
1843// }
1844// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1845// A->insertGlobalValues( row, indices(), value() );
1846// }
1847// }
1848
1849// if (callFillComplete)
1850// A->fillComplete();
1851// }
1852
1862template <class SC, class LO, class GO, class NO>
1864 std::string FEType,
1865 int degree,
1866 int dofs,
1867 BlockMatrixPtr_Type &A,
1868 bool callFillComplete,
1869 int FELocExternal){
1870 ParameterListPtr_Type params = Teuchos::getParametersFromXmlFile("parametersProblemLaplace.xml");
1871
1872 UN FEloc = checkFE(dim,FEType);
1873 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1874 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1875 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1876 vec2D_dbl_Type nodes;
1877 int numNodes=dim+1;
1878 if(FEType == "P2"){
1879 numNodes= 6;
1880 if(dim==3)
1881 numNodes=10;
1882 }
1883 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
1884 tuple_ssii_Type vel ("Laplace",FEType,dofs,numNodes);
1885 problemDisk->push_back(vel);
1886 if(assemblyFEElements_.size()== 0)
1887 initAssembleFEElements("Laplace",problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
1888 else if(assemblyFEElements_.size() != elements->numberElements())
1889 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
1890 for (UN T=0; T<elements->numberElements(); T++) {
1891 assemblyFEElements_[T]->assembleJacobian();
1892 SmallMatrixPtr_Type elementMatrix = assemblyFEElements_[T]->getJacobian();
1893 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
1894
1895 }
1896 if(callFillComplete)
1897 A->getBlock(0,0)->fillComplete();
1898}
1899
1900
1901template <class SC, class LO, class GO, class NO>
1902void FE<SC,LO,GO,NO>::assemblyLaplaceDiffusion(int dim,
1903 std::string FEType,
1904 int degree,
1905 MatrixPtr_Type &A,
1906 vec2D_dbl_Type diffusionTensor,
1907 bool callFillComplete,
1908 int FELocExternal){
1909 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1910 UN FEloc;
1911 if (FELocExternal<0)
1912 FEloc = checkFE(dim,FEType);
1913 else
1914 FEloc = FELocExternal;
1915
1916 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1917
1918 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1919
1920 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1921
1922 vec3D_dbl_ptr_Type dPhi;
1923 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1924
1925 // inner( grad(u) , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
1926 // The diffusion tensor is constant and, thus, does not require a higher-order quadrature rule.
1927 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);//+1;
1928 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1929
1930 SC detB;
1931 SC absDetB;
1932 SmallMatrix<SC> B(dim);
1933 SmallMatrix<SC> Binv(dim);
1934 GO glob_i, glob_j;
1935 vec_dbl_Type v_i(dim);
1936 vec_dbl_Type v_j(dim);
1937
1938
1939 SmallMatrix<SC> diffusionT(dim);
1940 // Linear Diffusion Tensor
1941 if(diffusionTensor.size()==0 || diffusionTensor.size() < dim ){
1942 vec2D_dbl_Type diffusionTensor(3,vec_dbl_Type(3,0));
1943 for(int i=0; i< dim; i++){
1944 diffusionTensor[i][i]=1.;
1945 }
1946 }
1947
1948 for(int i=0; i< dim; i++){
1949 for(int j=0; j<dim; j++){
1950 diffusionT[i][j]=diffusionTensor[i][j];
1951 }
1952 }
1953 //Teuchos::ArrayRCP< SC > linearDiff = diffusionTensor->getDataNonConst( 0 );
1954 //std::cout << "Assembly Info " << "num Elements " << elements->numberElements() << " num Nodes " << pointsRep->size() << std::endl;
1955 for (UN T=0; T<elements->numberElements(); T++) {
1956
1957 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1958 detB = B.computeInverse(Binv);
1959 absDetB = std::fabs(detB);
1960
1961 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1962 applyBTinv( dPhi, dPhiTrans, Binv );
1963
1964 vec3D_dbl_Type dPhiTransDiff( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1965 applyDiff( dPhiTrans, dPhiTransDiff, diffusionT );
1966
1967 for (UN i=0; i < dPhiTrans[0].size(); i++) {
1968 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
1969 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
1970
1971 for (UN j=0; j < value.size(); j++) {
1972 for (UN w=0; w<dPhiTrans.size(); w++) {
1973 for (UN d=0; d<dim; d++){
1974 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTransDiff[w][j][d];
1975 }
1976 }
1977 value[j] *= absDetB;
1978 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
1979 if (setZeros_ && std::fabs(value[j]) < myeps_) {
1980 value[j] = 0.;
1981 }
1982 }
1983 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
1984
1985 A->insertGlobalValues( row, indices(), value() );
1986 }
1987
1988
1989 }
1990 if (callFillComplete)
1991 A->fillComplete();
1992
1993}
1994
1995template <class SC, class LO, class GO, class NO>
1996void FE<SC,LO,GO,NO>::applyDiff( vec3D_dbl_Type& dPhiIn,
1997 vec3D_dbl_Type& dPhiOut,
1998 SmallMatrix<SC>& diffT){
1999 UN dim = diffT.size();
2000 for (UN w=0; w<dPhiIn.size(); w++){
2001 for (UN i=0; i < dPhiIn[w].size(); i++) {
2002 for (UN d1=0; d1<dim; d1++) {
2003 for (UN d2=0; d2<dim; d2++) {
2004 dPhiOut[w][i][d1] += dPhiIn[w][i][d2]* diffT[d2][d1];
2005 }
2006 }
2007 }
2008 }
2009}
2010
2011// template <class SC, class LO, class GO, class NO>
2012// void FE<SC,LO,GO,NO>::assemblyAceGenTPM( MatrixPtr_Type &A00,
2013// MatrixPtr_Type &A01,
2014// MatrixPtr_Type &A10,
2015// MatrixPtr_Type &A11,
2016// MultiVectorPtr_Type &F0,
2017// MultiVectorPtr_Type &F1,
2018// MapPtr_Type &mapRepeated1,
2019// MapPtr_Type &mapRepeated2,
2020// ParameterListPtr_Type parameterList,
2021// MultiVectorPtr_Type u_repeatedNewton,
2022// MultiVectorPtr_Type p_repeatedNewton,
2023// MultiVectorPtr_Type u_repeatedTime,
2024// MultiVectorPtr_Type p_repeatedTime,
2025// bool update,
2026// bool updateHistory)
2027// {
2028
2029
2030// std::string tpmType = parameterList->sublist("Parameter").get("TPM Type","Biot");
2031
2032// int dim = domainVec_[0]->getDimension();
2033// int idata = 1; //= we should init this
2034// int ic = -1; int ng = -1;
2035
2036// //ed.hp:history previous (timestep); previous solution (velocity and acceleration)
2037// //ed.ht:? same length as hp
2038// ElementsPtr_Type elements1 = domainVec_[0]->getElementsC();
2039// ElementsPtr_Type elements2 = domainVec_[1]->getElementsC();
2040
2041// int sizeED = 24; /* 2D case for P2 elements:
2042// 12 velocities, 12 accelerations (2 dof per P2 node)
2043// */
2044// if (dim==3)
2045// sizeED = 60;/* 3D case for P2 elements:
2046// 30 velocities, 30 accelerations (3 dof per P2 node)
2047// */
2048// if (ed_.size()==0){
2049// for (UN T=0; T<elements1->numberElements(); T++)
2050// ed_.push_back( Teuchos::rcp(new DataElement( sizeED )) );
2051// }
2052
2053// std::vector<ElementSpec> es_vec( parameterList->sublist("Parameter").get("Number of materials",1) , ElementSpec());
2054// vec2D_dbl_Type dataVec( parameterList->sublist("Parameter").get("Number of materials",1), vec_dbl_Type(6,0.) );
2055
2056// for (int i=0; i<dataVec.size(); i++) {
2057// if (tpmType == "Biot") {
2058// if (dim==2) {
2059// dataVec[i][0] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2060// dataVec[i][1] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2061// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
2062// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
2063// dataVec[i][4] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
2064// dataVec[i][5] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2065// }
2066// else if (dim==3) {
2067// dataVec[i].resize(12);
2068// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),2.e5);
2069// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2070// dataVec[i][2] = 0.; //body force x
2071// dataVec[i][3] = 0.; //body force y
2072// dataVec[i][4] = parameterList->sublist("Parameter").get("body force z"+std::to_string(i+1),0.);; //body force z
2073// dataVec[i][5] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.67);
2074// dataVec[i][6] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),0.01);
2075// dataVec[i][7] = 2000.; //effective density solid
2076// dataVec[i][8] = 1000.; //effective density fluid?
2077// dataVec[i][9] = 9.81; // gravity
2078// dataVec[i][10] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2079// dataVec[i][11] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2080// }
2081// }
2082
2083
2084// else if (tpmType == "Biot-StVK") {
2085// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
2086// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2087// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
2088// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
2089// dataVec[i][4] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2090// dataVec[i][5] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2091// }
2092// }
2093
2094// for (int i=0; i<es_vec.size(); i++){
2095// if(tpmType == "Biot"){
2096// if (dim==2)
2097// this->SMTSetElSpecBiot(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2098// else if(dim==3)
2099// this->SMTSetElSpecBiot3D(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2100// }
2101// else if(tpmType == "Biot-StVK")
2102// this->SMTSetElSpecBiotStVK(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2103// }
2104// LO elementSizePhase = elements1->nodesPerElement();
2105// LO sizePhase = dim * elementSizePhase;
2106// LO sizePressure = elements2->nodesPerElement();
2107// GO sizePhaseGlobal = A00->getMap()->getMaxAllGlobalIndex()+1;
2108// int workingVectorSize;
2109// if(tpmType == "Biot"){
2110// if (dim==2)
2111// workingVectorSize = 5523;
2112// else if(dim==3)
2113// workingVectorSize = 1817;
2114// }
2115// else if(tpmType == "Biot-StVK")
2116// workingVectorSize = 5223;
2117
2118// double* v = new double [workingVectorSize];
2119
2120// // nd sind Nodalwerte, Anzahl an structs in nd sollte den Knoten entsprechen, bei P2-P1 in 2D also 9
2121// // In X stehen die Koordinaten, X[0] ist x-Koordinate, X[1] ist y-Koordinate, etc.
2122// // nd->X[0]
2123// // at ist die Loesung im letzten Newtonschritt.
2124// // nd[0]->at[0];
2125// // ap ist die Loesung im letzten Zeitschritt.
2126// // nd[0]->ap[0]
2127// // 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.
2128
2129// std::vector<double> rdata(RD_TimeIncrement+1, 0.);
2130
2131// rdata[RD_TimeIncrement] = parameterList->sublist("Timestepping Parameter").get("dt",0.01);
2132
2133// NodeSpec *ns=NULL;//dummy not need in SKR
2134
2135// NodeData** nd = new NodeData*[ elementSizePhase + sizePressure ];
2136
2137// for (int i=0; i<elementSizePhase + sizePressure; i++){
2138// nd[i] = new NodeData();
2139// }
2140
2141// int numNodes = elementSizePhase + sizePressure;
2142
2143// vec2D_dbl_Type xFull( numNodes, vec_dbl_Type(dim,0.) );
2144// vec2D_dbl_Type atFull( numNodes, vec_dbl_Type(dim,0.) );
2145// vec2D_dbl_Type apFull( numNodes, vec_dbl_Type(dim,0.) );
2146
2147// for (int i=0; i<elementSizePhase + sizePressure; i++) {
2148// nd[i]->X = &(xFull[i][0]);
2149// nd[i]->at = &(atFull[i][0]);
2150// nd[i]->ap = &(apFull[i][0]);
2151// }
2152
2153// GO offsetMap1 = dim * mapRepeated1->getMaxAllGlobalIndex()+1;
2154// vec2D_dbl_ptr_Type pointsRepU = domainVec_.at(0)->getPointsRepeated();
2155// vec2D_dbl_ptr_Type pointsRepP = domainVec_.at(1)->getPointsRepeated();
2156
2157// Teuchos::ArrayRCP< const SC > uArrayNewton = u_repeatedNewton->getData(0);
2158// Teuchos::ArrayRCP< const SC > pArrayNewton = p_repeatedNewton->getData(0);
2159// Teuchos::ArrayRCP< const SC > uArrayTime = u_repeatedTime->getData(0);
2160// Teuchos::ArrayRCP< const SC > pArrayTime = p_repeatedTime->getData(0);
2161
2162// double** mat = new double*[sizePhase+sizePressure];
2163// for (int i=0; i<sizePhase+sizePressure; i++){
2164// mat[i] = new double[sizePhase+sizePressure];
2165// }
2166
2167// Teuchos::ArrayRCP<SC> fValues0 = F0->getDataNonConst(0);
2168// Teuchos::ArrayRCP<SC> fValues1 = F1->getDataNonConst(0);
2169
2170// // Element loop
2171
2172// ElementData ed = ElementData();
2173// for (UN T=0; T<elements1->numberElements(); T++) {
2174
2175// std::vector<double> tmpHp = ed_[T]->getHp(); // Dies sind die alten Daten
2176// 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.
2177// ed.hp = &tmpHp[0];
2178// ed.ht = &tmpHt[0];
2179
2180// int materialFlag = elements1->getElement(T).getFlag();
2181// TEUCHOS_TEST_FOR_EXCEPTION( materialFlag>es_vec.size()-1, std::runtime_error, "There are not enought material parameters initialized." ) ;
2182// int counter=0;
2183// //Newtonloesung at und Zeitschrittloesung ap
2184// for (int j=0; j<elementSizePhase; j++) {
2185// for (int d=0; d<dim; d++) {
2186// LO index = dim * elements1->getElement(T).getNode(j)+d;//dim * elements1->at(T).at( j ) + d;
2187// atFull[j][d] = uArrayNewton[index];
2188// apFull[j][d] = uArrayTime[index];
2189// }
2190// }
2191// for (int j=0; j<sizePressure; j++) {
2192// LO index = elements2->getElement(T).getNode(j);//elements2->at(T).at( j );
2193// atFull[elementSizePhase+j][0] = pArrayNewton[index];
2194// apFull[elementSizePhase+j][0] = pArrayTime[index];
2195// }
2196
2197// //Nodes
2198// for (int j=0; j<elementSizePhase; j++ ) {
2199// LO index = elements1->getElement(T).getNode(j);
2200// for (int d=0; d<dim; d++) {
2201// xFull[j][d] = (*pointsRepU)[index][d];
2202// }
2203// }
2204// for (int j=0; j<sizePressure; j++ ) {
2205// LO index = elements2->getElement(T).getNode(j);
2206// for (int d=0; d<dim; d++) {
2207// xFull[elementSizePhase+j][d] = (*pointsRepP)[index][d];
2208// }
2209// }
2210// vec_dbl_Type p( sizePhase+sizePressure , 0. );
2211
2212// for (int i=0; i<sizePhase+sizePressure; i++){
2213// for (int j=0; j<sizePhase+sizePressure; j++)
2214// mat[i][j] = 0.;
2215// }
2216// // element assembly
2217// if(tpmType == "Biot"){
2218// if(dim==2)
2219// this->SKR_Biot( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2220// else if (dim==3)
2221// this->SKR_Biot3D( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2222// }
2223// else if(tpmType == "Biot-StVK")
2224// this->SKR_Biot_StVK( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2225
2226// if (updateHistory)
2227// ed_[T]->setHp( ed.ht );
2228
2229// if (update) {
2230
2231// // A00 & A01
2232// for (UN i=0; i < sizePhase; i++) {
2233// Teuchos::Array<SC> value00( sizePhase, 0. );
2234// Teuchos::Array<GO> indices00( sizePhase, 0 );
2235// for (UN j=0; j < value00.size(); j++) {
2236
2237// value00[j] = mat[i][j];
2238
2239// LO tmpJ = j/dim;
2240// LO index = elements1->getElement(T).getNode(tmpJ);
2241// if (j%dim==0)
2242// indices00[j] = dim * mapRepeated1->getGlobalElement( index );
2243// else if (j%dim==1)
2244// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
2245// else if (j%dim==2)
2246// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
2247// }
2248
2249// Teuchos::Array<SC> value01( sizePressure, 0. );
2250// Teuchos::Array<GO> indices01( sizePressure, 0 );
2251
2252// for (UN j=0; j < value01.size(); j++) {
2253// value01[j] = mat[i][sizePhase+j];
2254// LO index = elements2->getElement(T).getNode(j);
2255// indices01[j] = mapRepeated2->getGlobalElement( index );
2256// }
2257
2258// GO row;
2259// LO tmpI = i/dim;
2260// LO index = elements1->getElement(T).getNode(tmpI);
2261// if (i%dim==0)
2262// row = dim * mapRepeated1->getGlobalElement( index );
2263// else if (i%dim==1)
2264// row = dim * mapRepeated1->getGlobalElement( index ) + 1;
2265// else if (i%dim==2)
2266// row = dim * mapRepeated1->getGlobalElement( index ) + 2;
2267
2268// A00->insertGlobalValues( row, indices00(), value00() );
2269// A01->insertGlobalValues( row, indices01(), value01() );
2270
2271// if (i%dim==0)
2272// fValues0[ dim*index ] += p[ i ];
2273// else if (i%dim==1)
2274// fValues0[ dim*index+1 ] += p[ i ];
2275// else if (i%dim==2)
2276// fValues0[ dim*index+2 ] += p[ i ];
2277// }
2278// // A10 & A11
2279// for (UN i=0; i < sizePressure; i++) {
2280// Teuchos::Array<SC> value10( sizePhase , 0. );
2281// Teuchos::Array<GO> indices10( sizePhase , 0 );
2282// for (UN j=0; j < value10.size(); j++) {
2283// value10[j] = mat[sizePhase+i][j];
2284
2285// LO tmpJ = j/dim;
2286// LO index = elements1->getElement(T).getNode(tmpJ);
2287// if (j%dim==0)
2288// indices10[j] = dim * mapRepeated1->getGlobalElement( index );
2289// else if (j%dim==1)
2290// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
2291// else if (j%dim==2)
2292// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
2293// }
2294
2295// Teuchos::Array<SC> value11( sizePressure, 0. );
2296// Teuchos::Array<GO> indices11( sizePressure, 0 );
2297// for (UN j=0; j < value11.size(); j++) {
2298// value11[j] = mat[sizePhase+i][sizePhase+j];
2299
2300// LO index = elements2->getElement(T).getNode(j);
2301// indices11[j] = mapRepeated2->getGlobalElement( index );
2302// }
2303
2304
2305// LO index2 = elements2->getElement(T).getNode(i);
2306// GO row = mapRepeated2->getGlobalElement( index2 );
2307// A10->insertGlobalValues( row, indices10(), value10() );
2308// A11->insertGlobalValues( row, indices11(), value11() );
2309
2310// fValues1[ index2 ] += p[ sizePhase + i ];
2311// }
2312// }
2313// }
2314
2315// for (int i=0; i<sizePhase+sizePressure; i++)
2316// delete [] mat[i];
2317// delete [] mat;
2318
2319// delete [] v;
2320
2321// for (int i=0; i<elementSizePhase+sizePressure; i++)
2322// delete nd[i];
2323
2324// delete [] nd;
2325
2326
2327// A00->fillComplete( A00->getMap("row"), A00->getMap("row") );
2328// A01->fillComplete( A10->getMap("row"), A00->getMap("row") );
2329// A10->fillComplete( A00->getMap("row"), A10->getMap("row") );
2330// A11->fillComplete( A10->getMap("row"), A10->getMap("row") );
2331
2332// }
2333
2334template <class SC, class LO, class GO, class NO>
2335void FE<SC,LO,GO,NO>::assemblyMass(int dim,
2336 std::string FEType,
2337 std::string fieldType,
2338 MatrixPtr_Type &A,
2339 bool callFillComplete){
2340
2341 TEUCHOS_TEST_FOR_EXCEPTION( FEType == "P0", std::logic_error, "Not implemented for P0" );
2342 UN FEloc = checkFE(dim,FEType);
2343 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2344
2345 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2346
2347 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2348
2349 vec2D_dbl_ptr_Type phi;
2350 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2351
2352 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
2353 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2354
2355 Helper::getPhi( phi, weights, dim, FEType, deg );
2356
2357 SC detB;
2358 SC absDetB;
2359 SmallMatrix<SC> B(dim);
2360 GO glob_i, glob_j;
2361 vec_dbl_Type v_i(dim);
2362 vec_dbl_Type v_j(dim);
2363
2364 for (UN T=0; T<elements->numberElements(); T++) {
2365
2366 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2367 detB = B.computeDet( );
2368 absDetB = std::fabs(detB);
2369
2370 for (UN i=0; i < phi->at(0).size(); i++) {
2371 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2372 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2373 for (UN j=0; j < value.size(); j++) {
2374 for (UN w=0; w<phi->size(); w++) {
2375 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2376
2377 }
2378 value[j] *= absDetB;
2379 if (!fieldType.compare("Scalar")) {
2380 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2381 }
2382
2383 }
2384 if (!fieldType.compare("Scalar")) {
2385 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2386 A->insertGlobalValues( row, indices(), value() );
2387 }
2388 else if (!fieldType.compare("Vector")) {
2389 for (UN d=0; d<dim; d++) {
2390 for (int j=0; j<indices.size(); j++) {
2391 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2392 }
2393 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2394 A->insertGlobalValues( row, indices(), value() );
2395 }
2396 }
2397 else
2398 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
2399 }
2400
2401 }
2402
2403 if (callFillComplete)
2404 A->fillComplete();
2405}
2406
2407
2408// Ueberladung der Assemblierung der Massematrix fuer FSI, da
2409// checkFE sonst auch fuer das Strukturproblem FEloc = 1 liefert (= Fluid)
2410// und somit die welche domain und Map in der Assemblierung genutzt wird.
2411template <class SC, class LO, class GO, class NO>
2412void FE<SC,LO,GO,NO>::assemblyMass(int dim,
2413 std::string FEType,
2414 std::string fieldType,
2415 MatrixPtr_Type &A,
2416 int FEloc, // 0 = Fluid, 2 = Struktur
2417 bool callFillComplete){
2418
2419 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2420
2421 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2422
2423 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2424
2425 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2426
2427 vec2D_dbl_ptr_Type phi;
2428 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2429
2430 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
2431 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2432
2433 Helper::getPhi( phi, weights, dim, FEType, deg );
2434
2435 SC detB;
2436 SC absDetB;
2437 SmallMatrix<SC> B(dim);
2438 GO glob_i, glob_j;
2439 vec_dbl_Type v_i(dim);
2440 vec_dbl_Type v_j(dim);
2441
2442 for (UN T=0; T<elements->numberElements(); T++) {
2443
2444 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2445 detB = B.computeDet( );
2446 absDetB = std::fabs(detB);
2447
2448 for (UN i=0; i < phi->at(0).size(); i++) {
2449 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2450 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2451 for (UN j=0; j < value.size(); j++) {
2452 for (UN w=0; w<phi->size(); w++) {
2453 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2454 }
2455 value[j] *= absDetB;
2456 if (!fieldType.compare("Scalar")) {
2457 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2458 }
2459
2460 }
2461 if (!fieldType.compare("Scalar")) {
2462 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2463 A->insertGlobalValues( row, indices(), value() );
2464 }
2465 else if (!fieldType.compare("Vector")) {
2466 for (UN d=0; d<dim; d++) {
2467 for (int j=0; j<indices.size(); j++) {
2468 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2469 }
2470 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2471 A->insertGlobalValues( row, indices(), value() );
2472 }
2473 }
2474 else
2475 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
2476 }
2477
2478
2479 }
2480 if (callFillComplete)
2481 A->fillComplete();
2482}
2483
2484
2485template <class SC, class LO, class GO, class NO>
2486void FE<SC,LO,GO,NO>::assemblyLaplace(int dim,
2487 std::string FEType,
2488 int degree,
2489 MatrixPtr_Type &A,
2490 bool callFillComplete,
2491 int FELocExternal){
2492 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2493 UN FEloc;
2494 if (FELocExternal<0)
2495 FEloc = checkFE(dim,FEType);
2496 else
2497 FEloc = FELocExternal;
2498
2499 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2500
2501 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2502
2503 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2504
2505 vec3D_dbl_ptr_Type dPhi;
2506 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2507
2508 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2509 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2510
2511 SC detB;
2512 SC absDetB;
2513 SmallMatrix<SC> B(dim);
2514 SmallMatrix<SC> Binv(dim);
2515 GO glob_i, glob_j;
2516 vec_dbl_Type v_i(dim);
2517 vec_dbl_Type v_j(dim);
2518
2519 for (UN T=0; T<elements->numberElements(); T++) {
2520
2521 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2522 detB = B.computeInverse(Binv);
2523 absDetB = std::fabs(detB);
2524
2525 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2526 applyBTinv( dPhi, dPhiTrans, Binv );
2527 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2528 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2529 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2530 for (UN j=0; j < value.size(); j++) {
2531 for (UN w=0; w<dPhiTrans.size(); w++) {
2532 for (UN d=0; d<dim; d++){
2533 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
2534 }
2535 }
2536 value[j] *= absDetB;
2537 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2538 }
2539 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2540
2541 A->insertGlobalValues( row, indices(), value() );
2542 }
2543
2544
2545 }
2546 if (callFillComplete)
2547 A->fillComplete();
2548
2549}
2550
2551template <class SC, class LO, class GO, class NO>
2552void FE<SC,LO,GO,NO>::assemblyLaplaceVecField(int dim,
2553 std::string FEType,
2554 int degree,
2555 MatrixPtr_Type &A,
2556 bool callFillComplete){
2557
2558 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P1-disc" || FEType == "P0",std::logic_error, "Not implemented for P0 or P1-disc");
2559 UN FEloc = checkFE(dim,FEType);
2560
2561 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2562
2563 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2564
2565 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2566
2567 vec3D_dbl_ptr_Type dPhi;
2568 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2569
2570 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2571
2572 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2573
2574 SC detB;
2575 SC absDetB;
2576 SmallMatrix<SC> B(dim);
2577 SmallMatrix<SC> Binv(dim);
2578 GO glob_i, glob_j;
2579 vec_dbl_Type v_i(dim);
2580 vec_dbl_Type v_j(dim);
2581
2582
2583 for (UN T=0; T<elements->numberElements(); T++) {
2584
2585 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2586 detB = B.computeInverse(Binv);
2587 absDetB = std::fabs(detB);
2588
2589 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2590 applyBTinv( dPhi, dPhiTrans, Binv );
2591
2592 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2593 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2594 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2595 for (UN j=0; j < value.size(); j++) {
2596 for (UN w=0; w<dPhiTrans.size(); w++) {
2597 for (UN d=0; d<dim; d++)
2598 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
2599 }
2600 value[j] *= absDetB;
2601 if (setZeros_ && std::fabs(value[j]) < myeps_) {
2602 value[j] = 0.;
2603 }
2604 }
2605 for (UN d=0; d<dim; d++) {
2606 for (UN j=0; j < indices.size(); j++)
2607 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2608
2609 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2610 A->insertGlobalValues( row, indices(), value() );
2611 }
2612 }
2613 }
2614 if (callFillComplete)
2615 A->fillComplete();
2616}
2617//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.
2618template <class SC, class LO, class GO, class NO>
2619void FE<SC,LO,GO,NO>::assemblyLaplaceVecFieldV2(int dim,
2620 std::string FEType,
2621 int degree,
2622 MatrixPtr_Type &A,
2623 bool callFillComplete){
2624
2625 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2626 UN FEloc = checkFE(dim,FEType);
2627
2628 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2629
2630 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2631
2632 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2633
2634 vec3D_dbl_ptr_Type dPhi;
2635 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2636
2637 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2638
2639 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2640
2641 Teuchos::BLAS<int, SC> teuchosBLAS;
2642
2643 int nmbQuadPoints = dPhi->size();
2644 int nmbScalarDPhi = dPhi->at(0).size();
2645 int nmbAllDPhi = nmbScalarDPhi * dim;
2646 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2647 int sizeLocStiff = dim*dim;
2648 Teuchos::Array<SmallMatrix<double> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<double>(dim) );
2649 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2650
2651
2652 SC detB;
2653 SC absDetB;
2654 SmallMatrix<SC> B(dim);
2655 SmallMatrix<SC> Binv(dim);
2656 GO glob_i, glob_j;
2657 vec_dbl_Type v_i(dim);
2658 vec_dbl_Type v_j(dim);
2659
2660 for (UN T=0; T<elements->numberElements(); T++) {
2661
2662 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2663 detB = B.computeInverse(Binv);
2664 absDetB = std::fabs(detB);
2665
2666 Teuchos::Array<SmallMatrix<double> > allDPhiMatTrans( dPhiMat.size(), SmallMatrix<double>() );
2667
2668 for (int i=0; i<allDPhiMatTrans.size(); i++) {
2669 SmallMatrix<double> res = dPhiMat[i] * Binv;
2670 allDPhiMatTrans[i] = res;
2671 }
2672
2673 SmallMatrix<double> locStiffMat( nmbAllDPhi, 0. );
2674
2675 for (int p=0; p<nmbQuadPoints; p++){
2676
2677 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
2678
2679 int offset = p * nmbAllDPhi;
2680 int offsetInArray = 0;
2681 for (int i=0; i<nmbAllDPhi; i++) {
2682 fillMatrixArray( allDPhiMatTrans[ offset + i ], allDPhiBlas, "rows",offsetInArray );
2683 offsetInArray += sizeLocStiff;
2684 }
2685
2686 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
2687
2688 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);
2689
2690 for (int i=0; i<nmbAllDPhi; i++) {
2691 for (int j=0; j<nmbAllDPhi; j++) {
2692 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
2693 }
2694 }
2695
2696 delete [] allDPhiBlas;
2697 delete [] locStiffMatBlas;
2698
2699 }
2700
2701 for (UN i=0; i < nmbScalarDPhi; i++) {
2702 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
2703 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
2704 for (UN d=0; d<dim; d++) {
2705 for (UN j=0; j < nmbScalarDPhi; j++){
2706 value[ j * dim + d ] = absDetB * locStiffMat[dim * i + d][j];
2707 indices[ j * dim + d ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2708 }
2709 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2710 A->insertGlobalValues( row, indices(), value() );
2711 }
2712 }
2713 }
2714 if (callFillComplete)
2715 A->fillComplete();
2716}
2717
2733
2734template <class SC, class LO, class GO, class NO>
2736 int dim, std::string FEType, int degree, MultiVectorPtr_Type u_rep,
2737 BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec,
2738 ParameterListPtr_Type params, std::string assembleMode, bool callFillComplete,
2739 int FELocExternal) {
2740
2741 ElementsPtr_Type elements = this->domainVec_.at(0)->getElementsC();
2742
2743 // Only scalar laplace
2744 int dofs = 1;
2745
2746 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(0)->getPointsRepeated();
2747 MapConstPtr_Type map = this->domainVec_.at(0)->getMapRepeated();
2748
2749 vec_dbl_Type solution_u;
2750 vec_dbl_ptr_Type rhsVec;
2751
2752 int numNodes = 3;
2753 if (FEType == "P2") {
2754 numNodes = 6;
2755 }
2756 if (dim == 3) {
2757 numNodes = 4;
2758 if (FEType == "P2") {
2759 numNodes = 10;
2760 }
2761 }
2762
2763 // Tupel construction follows follwing pattern:
2764 // std::string: Physical Entity (i.e. Velocity) , std::string: Discretisation (i.e.
2765 // "P2"), int: Degrees of Freedom per Node, int: Number of Nodes per
2766 // element)
2767 tuple_disk_vec_ptr_Type problemDisk =
2768 Teuchos::rcp(new tuple_disk_vec_Type(0));
2769 tuple_ssii_Type temp("Solution", FEType, dofs, numNodes);
2770 problemDisk->push_back(temp);
2771
2772 // Construct an assembler for each element if not already done
2773 if (assemblyFEElements_.size() == 0) {
2774 initAssembleFEElements("NonLinearLaplace", problemDisk, elements, params, pointsRep, domainVec_.at(0)->getElementMap());
2775 } else if (assemblyFEElements_.size() != elements->numberElements()) {
2776 TEUCHOS_TEST_FOR_EXCEPTION(
2777 true, std::logic_error,
2778 "Number Elements not the same as number assembleFE elements.");
2779 }
2780
2781 MultiVectorPtr_Type resVec_u;
2782 BlockMultiVectorPtr_Type resVecRep;
2783
2784 if (assembleMode != "Rhs") {
2785 // add new or overwrite existing block (0,0) of system matrix
2786 // This is done in specific problem class for most other problems
2787 // Placing it here instead as more fitting
2788 auto A_block_zero_zero = Teuchos::rcp(
2789 new Matrix_Type(this->domainVec_.at(0)->getMapUnique(), this->domainVec_.at(0)->getApproxEntriesPerRow()));
2790
2791 A->addBlock(A_block_zero_zero, 0, 0);
2792 } else {
2793 // Or same for the residual vector
2794 resVec_u = Teuchos::rcp(new MultiVector_Type(map, 1));
2795 resVecRep = Teuchos::rcp(new BlockMultiVector_Type(1));
2796 resVecRep->addBlock(resVec_u, 0);
2797 }
2798 // Call assembly routines on each element
2799 for (UN T = 0; T < assemblyFEElements_.size(); T++) {
2800 vec_dbl_Type solution(0);
2801
2802 // Update solution on the element
2803 solution_u = getSolution(elements->getElement(T).getVectorNodeList(),
2804 u_rep, dofs);
2805 solution.insert(solution.end(), solution_u.begin(), solution_u.end());
2806 assemblyFEElements_[T]->updateSolution(solution);
2807
2808 if (assembleMode == "Jacobian") {
2809 SmallMatrixPtr_Type elementMatrix;
2810 assemblyFEElements_[T]->assembleJacobian();
2811 elementMatrix = assemblyFEElements_[T]->getJacobian();
2812 // Insert (additive) the local element Jacobian into the global
2813 // matrix
2814 assemblyFEElements_[T]
2815 ->advanceNewtonStep(); // n genereal non linear solver step
2816 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0,
2817 problemDisk);
2818 }
2819
2820 if (assembleMode == "Rhs") {
2821 assemblyFEElements_[T]->assembleRHS();
2822 rhsVec = assemblyFEElements_[T]->getRHS();
2823 // Name RHS comes from solving linear systems
2824 // For nonlinear systems RHS synonymous to residual
2825 // Insert (additive) the updated residual into the global residual
2826 // vector
2827 addFeBlockMv(resVecRep, rhsVec, elements->getElement(T), dofs);
2828 }
2829 }
2830 if (callFillComplete && assembleMode != "Rhs") {
2831 // Signal that editing A has finished. This causes the entries of A to
2832 // be redistributed across the MPI ranks
2833 A->getBlock(0, 0)->fillComplete(domainVec_.at(0)->getMapUnique(),
2834 domainVec_.at(0)->getMapUnique());
2835 }
2836 if (assembleMode == "Rhs") {
2837 // Export from overlapping residual to unique residual
2838 MultiVectorPtr_Type resVecUnique = Teuchos::rcp(
2839 new MultiVector_Type(domainVec_.at(0)->getMapUnique(), 1));
2840 resVecUnique->putScalar(0.);
2841 resVecUnique->exportFromVector(resVec_u, true, "Add");
2842 resVec->addBlock(resVecUnique, 0);
2843 }
2844}
2845
2846
2847template <class SC, class LO, class GO, class NO>
2848void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAndStressAceFEM(int dim,
2849 std::string FEType,
2850 MatrixPtr_Type &A,
2851 MultiVectorPtr_Type &f,
2852 MultiVectorPtr_Type u,
2853 ParameterListPtr_Type pList,
2854 double C,
2855 bool callFillComplete){
2856 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::runtime_error, "Not implemented for P0");
2857 UN FEloc = checkFE(dim,FEType);
2858
2859
2860 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2861 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2862
2863 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2864 vec3D_dbl_ptr_Type dPhi;
2865 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2866
2867 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2868
2869 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2870
2871 SC detB;
2872 SC absDetB;
2873 SmallMatrix<SC> B(dim);
2874 SmallMatrix<SC> Binv(dim);
2875
2876 Teuchos::BLAS<int,SC> teuchosBLAS;
2877
2878 int nmbQuadPoints = dPhi->size();
2879 int nmbScalarDPhi = dPhi->at(0).size();
2880 int nmbAllDPhi = nmbScalarDPhi * dim;
2881 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2882 int sizeLocStiff = dim*dim;
2883 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
2884
2885 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2886
2887 std::string material_model = pList->sublist("Parameter").get("Material model","Neo-Hooke");
2888
2889 double poissonRatio = pList->sublist("Parameter").get("Poisson Ratio",0.4);
2890 double mue = pList->sublist("Parameter").get("Mu",2.0e+6);
2891 double mue1 = pList->sublist("Parameter").get("Mu1",2.0e+6);
2892 double mue2 = pList->sublist("Parameter").get("Mu2",2.0e+6);
2893 // Berechne daraus nun E (Youngsches Modul) und die erste Lamé-Konstante \lambda
2894 double E = pList->sublist("Parameter").get("E",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2895 double E1 = pList->sublist("Parameter").get("E1",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2896 double E2 = pList->sublist("Parameter").get("E2",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2897
2898 if (material_model=="Saint Venant-Kirchhoff") {
2899 E = mue*2.*(1. + poissonRatio);
2900 E1 = mue1*2.*(1. + poissonRatio);
2901 E2 = mue2*2.*(1. + poissonRatio);
2902 }
2903
2904 // For StVK (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2905 double lambda = (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2906 double lambda1 = (poissonRatio*E1)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2907 double lambda2 = (poissonRatio*E2)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2908
2909 if (dim == 2){
2910 double* v;
2911 if(!material_model.compare("Saint Venant-Kirchhoff"))
2912 v = new double[154];
2913 else
2914 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Saint Venant-Kirchhoff in 2D.");
2915
2916 double** Pmat = new double*[2];
2917 for (int i=0; i<2; i++)
2918 Pmat[i] = new double[2];
2919
2920 double** F = new double*[2];
2921 for (int i=0; i<2; i++)
2922 F[i] = new double[2];
2923
2924 double**** Amat = new double***[2];
2925 for (int i=0; i<2; i++){
2926 Amat[i] = new double**[2];
2927 for (int j=0; j<2; j++) {
2928 Amat[i][j] = new double*[2];
2929 for (int k=0; k<2; k++)
2930 Amat[i][j][k] = new double[2];
2931 }
2932 }
2933
2934 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2935
2936 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
2937
2938 Teuchos::Array<int> indices(2);
2939 for (int T=0; T<elements->numberElements(); T++) {
2940
2941 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2942 detB = B.computeInverse(Binv);
2943 absDetB = std::fabs(detB);
2944
2945 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
2946
2947 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
2948 SmallMatrix<SC> res = dPhiMat[i] * Binv;
2949 all_dPhiMat_Binv[i] = res;
2950 }
2951
2952 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
2953 std::vector<SC> locStresses( nmbAllDPhi, 0. );
2954 int elementFlag = 0;
2955 for (int p=0; p<nmbQuadPoints; p++){
2956
2957 SmallMatrix<SC> Fmat( dim, 0. );
2958 SmallMatrix<SC> tmpForScaling( dim, 0. );
2959 Fmat[0][0] = 1.; Fmat[1][1] = 1.;
2960
2961 for (int i=0; i<nmbScalarDPhi; i++) {
2962 indices.at(0) = dim * elements->getElement(T).getNode(i);
2963 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
2964
2965 for (int j=0; j<dim; j++) {
2966 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
2967 SC v = uArray[indices.at(j)];
2968 tmpForScaling.scale( v );
2969 Fmat += tmpForScaling;
2970 }
2971 }
2972
2973 for (int i=0; i<Fmat.size(); i++) {
2974 for (int j=0; j<Fmat.size(); j++) {
2975 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
2976 }
2977 }
2978
2979 elementFlag = elements->getElement(T).getFlag();
2980 if (elementFlag == 1){
2981 lambda = lambda1;
2982 mue = mue1;
2983 E = E1;
2984 }
2985 else if (elementFlag == 2){
2986 lambda = lambda2;
2987 mue = mue2;
2988 E = E2;
2989 }
2990
2991 if ( !material_model.compare("Saint Venant-Kirchhoff") )
2992 stvk2d(v, &lambda, &mue, F, Pmat, Amat);
2993
2994 SmallMatrix<SC> Aloc(dim*dim);
2995 for (int i=0; i<2; i++) {
2996 for (int j=0; j<2; j++) {
2997 for (int k=0; k<2; k++) {
2998 for (int l=0; l<2; l++) {
2999 Aloc[ 2 * i + j ][ 2 * k + l ] = Amat[i][j][k][l];
3000 }
3001 }
3002 }
3003 }
3004
3005 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3006 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3007
3008 //jacobian
3009 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3010 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3011 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3012
3013 int offset = p * nmbAllDPhi;
3014 int offsetInArray = 0;
3015 for (int i=0; i<nmbAllDPhi; i++) {
3016 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3017 offsetInArray += sizeLocStiff;
3018 }
3019
3020 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3021
3022
3023 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3024
3025 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);
3026
3027 for (int i=0; i<nmbAllDPhi; i++) {
3028 for (int j=0; j<nmbAllDPhi; j++)
3029 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3030 }
3031
3032 delete [] resTmp;
3033 delete [] locStiffMatBlas;
3034
3035
3036 //stress
3037 double* fArray = new double[ sizeLocStiff ];
3038 for (int i=0; i<dim; i++) {
3039 for (int j=0; j<dim; j++) {
3040 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3041 }
3042 }
3043
3044 double* res = new double[ nmbAllDPhi ];
3045 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3046 for (int i=0; i<locStresses.size(); i++) {
3047 locStresses[i] += weights->at(p) * res[i];
3048 }
3049
3050 delete [] res;
3051 delete [] aceFEMFunc;
3052 delete [] allDPhiBlas;
3053 delete [] fArray;
3054 }
3055
3056 for (int i=0; i<nmbScalarDPhi; i++) {
3057 for (int d1=0; d1<dim; d1++) {
3058
3059 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
3060 SC v = absDetB * locStresses[ dim * i + d1 ];
3061 fValues[rowLO] += v;
3062
3063 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3064 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3065 LO counter = 0;
3066 for (UN j=0; j < nmbScalarDPhi; j++){
3067 for (UN d2=0; d2<dim; d2++) {
3068 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3069 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3070 counter++;
3071 }
3072 }
3073 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3074 A->insertGlobalValues( row, indices(), value() );
3075 }
3076 }
3077 }
3078
3079 delete [] v;
3080 for (int i=0; i<2; i++)
3081 delete [] Pmat[i];
3082 delete [] Pmat;
3083 for (int i=0; i<2; i++)
3084 delete [] F[i];
3085 delete [] F;
3086
3087 for (int i=0; i<2; i++){
3088 for (int j=0; j<2; j++) {
3089 for (int k=0; k<2; k++)
3090 delete [] Amat[i][j][k];
3091 delete [] Amat[i][j];
3092 }
3093 delete [] Amat[i];
3094 }
3095 delete [] Amat;
3096
3097
3098 }
3099 else if (dim == 3) {
3100 double* v;
3101 if (!material_model.compare("Neo-Hooke"))
3102 v = new double[466];
3103 else if(!material_model.compare("Mooney-Rivlin"))
3104 v = new double[476];
3105 else if(!material_model.compare("Saint Venant-Kirchhoff"))
3106 v = new double[279];
3107 else{
3108 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke, Mooney-Rivlin and Saint Venant-Kirchhoff.");
3109 }
3110
3111 double** Pmat = new double*[3];
3112 for (int i=0; i<3; i++)
3113 Pmat[i] = new double[3];
3114
3115 double** F = new double*[3];
3116 for (int i=0; i<3; i++)
3117 F[i] = new double[3];
3118
3119 double**** Amat = new double***[3];
3120 for (int i=0; i<3; i++){
3121 Amat[i] = new double**[3];
3122 for (int j=0; j<3; j++) {
3123 Amat[i][j] = new double*[3];
3124 for (int k=0; k<3; k++)
3125 Amat[i][j][k] = new double[3];
3126 }
3127 }
3128
3129 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3130
3131 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
3132
3133 Teuchos::Array<int> indices(3);
3134 for (int T=0; T<elements->numberElements(); T++) {
3135
3136 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
3137 detB = B.computeInverse(Binv);
3138 absDetB = std::fabs(detB);
3139
3140 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3141
3142 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3143 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3144 all_dPhiMat_Binv[i] = res;
3145 }
3146
3147 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
3148 std::vector<SC> locStresses( nmbAllDPhi, 0. );
3149 int elementFlag = 0;
3150 for (int p=0; p<nmbQuadPoints; p++){
3151
3152 SmallMatrix<SC> Fmat( dim, 0. );
3153 SmallMatrix<SC> tmpForScaling( dim, 0. );
3154 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3155
3156 for (int i=0; i<nmbScalarDPhi; i++) {
3157 indices.at(0) = dim * elements->getElement(T).getNode(i);
3158 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
3159 indices.at(2) = dim * elements->getElement(T).getNode(i) + 2;
3160
3161 for (int j=0; j<dim; j++) {
3162 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3163 SC v = uArray[indices.at(j)];
3164 tmpForScaling.scale( v );
3165 Fmat += tmpForScaling;
3166 }
3167 }
3168
3169 for (int i=0; i<Fmat.size(); i++) {
3170 for (int j=0; j<Fmat.size(); j++) {
3171 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3172 }
3173 }
3174
3175 elementFlag = elements->getElement(T).getFlag();
3176 if (elementFlag == 1){
3177 lambda = lambda1;
3178 mue = mue1;
3179 E = E1;
3180 }
3181 else if (elementFlag == 2){
3182 lambda = lambda2;
3183 mue = mue2;
3184 E = E2;
3185 }
3186
3187 if ( !material_model.compare("Neo-Hooke") )
3188 nh3d(v, &E, &poissonRatio, F, Pmat, Amat);
3189 else if ( !material_model.compare("Mooney-Rivlin") )
3190 mr3d(v, &E, &poissonRatio, &C, F, Pmat, Amat);
3191 else if ( !material_model.compare("Saint Venant-Kirchhoff") )
3192 stvk3d(v, &lambda, &mue, F, Pmat, Amat);
3193
3194 SmallMatrix<SC> Aloc(dim*dim);
3195 for (int i=0; i<3; i++) {
3196 for (int j=0; j<3; j++) {
3197 for (int k=0; k<3; k++) {
3198 for (int l=0; l<3; l++) {
3199 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
3200 }
3201 }
3202 }
3203 }
3204
3205 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3206 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3207
3208 //jacobian
3209 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3210 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3211 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3212
3213 int offset = p * nmbAllDPhi;
3214 int offsetInArray = 0;
3215 for (int i=0; i<nmbAllDPhi; i++) {
3216 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3217 offsetInArray += sizeLocStiff;
3218 }
3219
3220 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3221
3222
3223 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3224
3225 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);
3226
3227 for (int i=0; i<nmbAllDPhi; i++) {
3228 for (int j=0; j<nmbAllDPhi; j++)
3229 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3230 }
3231
3232 delete [] resTmp;
3233 delete [] locStiffMatBlas;
3234
3235
3236 //stress
3237 double* fArray = new double[ sizeLocStiff ];
3238 for (int i=0; i<dim; i++) {
3239 for (int j=0; j<dim; j++) {
3240 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3241 }
3242 }
3243
3244 double* res = new double[ nmbAllDPhi ];
3245 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3246 for (int i=0; i<locStresses.size(); i++) {
3247 locStresses[i] += weights->at(p) * res[i];
3248 }
3249
3250 delete [] res;
3251 delete [] aceFEMFunc;
3252 delete [] allDPhiBlas;
3253 delete [] fArray;
3254 }
3255
3256 for (int i=0; i<nmbScalarDPhi; i++) {
3257 for (int d1=0; d1<dim; d1++) {
3258
3259 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
3260 SC v = absDetB * locStresses[ dim * i + d1 ];
3261 fValues[rowLO] += v;
3262
3263 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3264 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3265 LO counter = 0;
3266 for (UN j=0; j < nmbScalarDPhi; j++){
3267 for (UN d2=0; d2<dim; d2++) {
3268 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3269 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3270
3271 counter++;
3272 }
3273 }
3274 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3275 A->insertGlobalValues( row, indices(), value() );
3276 }
3277 }
3278 }
3279
3280 delete [] v;
3281 for (int i=0; i<3; i++)
3282 delete [] Pmat[i];
3283 delete [] Pmat;
3284 for (int i=0; i<3; i++)
3285 delete [] F[i];
3286 delete [] F;
3287
3288 for (int i=0; i<3; i++){
3289 for (int j=0; j<3; j++) {
3290 for (int k=0; k<3; k++)
3291 delete [] Amat[i][j][k];
3292 delete [] Amat[i][j];
3293 }
3294 delete [] Amat[i];
3295 }
3296 delete [] Amat;
3297
3298 }
3299 if (callFillComplete)
3300 A->fillComplete();
3301
3302}
3303
3304
3305template <class SC, class LO, class GO, class NO>
3306void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAceFEM(int dim,
3307 std::string FEType,
3308 MatrixPtr_Type &A,
3309 MultiVectorPtr_Type u,
3310 std::string material_model,
3311 double E,
3312 double nu,
3313 double C,
3314 bool callFillComplete){
3315 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3316 UN FEloc = checkFE(dim,FEType);
3317
3318 vec2D_int_ptr_Type elements = domainVec_.at(FEloc)->getElements();
3319
3320 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3321
3322 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3323 vec3D_dbl_ptr_Type dPhi;
3324 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3325
3326 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
3327
3328 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3329
3330 SC detB;
3331 SC absDetB;
3332 SmallMatrix<SC> B(dim);
3333 SmallMatrix<SC> Binv(dim);
3334
3335 Teuchos::BLAS<int, SC> teuchosBLAS;
3336
3337 int nmbQuadPoints = dPhi->size();
3338 int nmbScalarDPhi = dPhi->at(0).size();
3339 int nmbAllDPhi = nmbScalarDPhi * dim;
3340 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
3341 int sizeLocStiff = dim*dim;
3342 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
3343
3344 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
3345
3346 if (dim == 2){
3347 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
3348 }
3349 else if (dim == 3) {
3350
3351 double* v;
3352 if (!material_model.compare("Neo-Hooke"))
3353 v = new double[466];
3354 else if(!material_model.compare("Mooney-Rivlin"))
3355 v = new double[476];
3356 else{
3357 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
3358 }
3359
3360
3361 double** Pmat = new double*[3];
3362 for (int i=0; i<3; i++)
3363 Pmat[i] = new double[3];
3364
3365 double** F = new double*[3];
3366 for (int i=0; i<3; i++)
3367 F[i] = new double[3];
3368
3369 double**** Amat = new double***[3];
3370 for (int i=0; i<3; i++){
3371 Amat[i] = new double**[3];
3372 for (int j=0; j<3; j++) {
3373 Amat[i][j] = new double*[3];
3374 for (int k=0; k<3; k++)
3375 Amat[i][j][k] = new double[3];
3376 }
3377 }
3378
3379 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3380
3381 Teuchos::Array<int> indices(3);
3382 for (int T=0; T<elements->size(); T++) {
3383
3384 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
3385 detB = B.computeInverse(Binv);
3386 absDetB = std::fabs(detB);
3387
3388 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3389
3390 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3391 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3392 all_dPhiMat_Binv[i] = res;
3393 }
3394
3395 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
3396
3397 for (int p=0; p<nmbQuadPoints; p++){
3398
3399 SmallMatrix<SC> Fmat( dim, 0. );
3400 SmallMatrix<SC> tmpForScaling( dim, 0. );
3401 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3402
3403 for (int i=0; i<nmbScalarDPhi; i++) {
3404 indices.at(0) = dim * elements->at(T).at(i);
3405 indices.at(1) = dim * elements->at(T).at(i) + 1;
3406 indices.at(2) = dim * elements->at(T).at(i) + 2;
3407
3408 for (int j=0; j<dim; j++) {
3409 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3410 SC v = uArray[indices.at(j)];
3411 tmpForScaling.scale( v );
3412 Fmat += tmpForScaling;
3413 }
3414 }
3415
3416 for (int i=0; i<Fmat.size(); i++) {
3417 for (int j=0; j<Fmat.size(); j++) {
3418 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3419 }
3420 }
3421 if ( !material_model.compare("Neo-Hooke") )
3422 nh3d(v, &E, &nu, F, Pmat, Amat);
3423 else if ( !material_model.compare("Mooney-Rivlin") )
3424 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
3425
3426 SmallMatrix<SC> Aloc(dim*dim);
3427 for (int i=0; i<3; i++) {
3428 for (int j=0; j<3; j++) {
3429 for (int k=0; k<3; k++) {
3430 for (int l=0; l<3; l++) {
3431 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
3432 }
3433 }
3434 }
3435 }
3436
3437 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3438 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3439 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3440 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3441 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3442
3443 int offset = p * nmbAllDPhi;
3444 int offsetInArray = 0;
3445 for (int i=0; i<nmbAllDPhi; i++) {
3446 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3447 offsetInArray += sizeLocStiff;
3448 }
3449
3450 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3451
3452 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3453
3454 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);
3455
3456 for (int i=0; i<nmbAllDPhi; i++) {
3457 for (int j=0; j<nmbAllDPhi; j++)
3458 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3459 }
3460
3461 delete [] aceFEMFunc;
3462 delete [] allDPhiBlas;
3463 delete [] resTmp;
3464 delete [] locStiffMatBlas;
3465
3466 }
3467 for (int i=0; i<nmbScalarDPhi; i++) {
3468 for (int d1=0; d1<dim; d1++) {
3469 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3470 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3471 LO counter = 0;
3472 for (UN j=0; j < nmbScalarDPhi; j++){
3473 for (UN d2=0; d2<dim; d2++) {
3474 indices[counter] = GO ( dim * map->getGlobalElement( elements->at(T).at(j) ) + d2 );
3475 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3476 counter++;
3477 }
3478 }
3479 GO row = GO ( dim * map->getGlobalElement( elements->at(T).at(i) ) + d1 );
3480 A->insertGlobalValues( row, indices(), value() );
3481 }
3482 }
3483 }
3484
3485 delete [] v;
3486 for (int i=0; i<3; i++)
3487 delete [] Pmat[i];
3488 delete [] Pmat;
3489 for (int i=0; i<3; i++)
3490 delete [] F[i];
3491 delete [] F;
3492
3493 for (int i=0; i<3; i++){
3494 for (int j=0; j<3; j++) {
3495 for (int k=0; k<3; k++)
3496 delete [] Amat[i][j][k];
3497 delete [] Amat[i][j];
3498 }
3499 delete [] Amat[i];
3500 }
3501 delete [] Amat;
3502
3503 }
3504 if (callFillComplete)
3505 A->fillComplete();
3506
3507}
3508
3509template <class SC, class LO, class GO, class NO>
3510void FE<SC,LO,GO,NO>::assemblyElasticityStressesAceFEM(int dim,
3511 std::string FEType,
3512 MultiVectorPtr_Type &f,
3513 MultiVectorPtr_Type u,
3514 std::string material_model,
3515 double E,
3516 double nu,
3517 double C,
3518 bool callFillComplete){
3519 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3520 UN FEloc = checkFE(dim,FEType);
3521
3522 vec2D_int_ptr_Type elements = domainVec_.at(FEloc)->getElements();
3523
3524 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3525
3526 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3527
3528 vec3D_dbl_ptr_Type dPhi;
3529 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3530
3531 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
3532
3533 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3534
3535 SC detB;
3536 SC absDetB;
3537 SmallMatrix<SC> B(dim);
3538 SmallMatrix<SC> Binv(dim);
3539
3540 Teuchos::BLAS<int, SC> teuchosBLAS;
3541
3542 int nmbQuadPoints = dPhi->size();
3543 int nmbScalarDPhi = dPhi->at(0).size();
3544 int nmbAllDPhi = nmbScalarDPhi * dim;
3545 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
3546 int sizeLocStiff = dim*dim;
3547 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
3548
3549 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
3550
3551 if (dim == 2){
3552 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
3553 }
3554 else if (dim == 3) {
3555
3556 double* v;
3557 if (!material_model.compare("Neo-Hooke"))
3558 v = new double[466];
3559 else if(!material_model.compare("Mooney-Rivlin"))
3560 v = new double[476];
3561 else{
3562 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
3563 }
3564
3565
3566 double** Pmat = new double*[3];
3567 for (int i=0; i<3; i++)
3568 Pmat[i] = new double[3];
3569
3570 double** F = new double*[3];
3571 for (int i=0; i<3; i++)
3572 F[i] = new double[3];
3573
3574 double**** Amat = new double***[3];
3575 for (int i=0; i<3; i++){
3576 Amat[i] = new double**[3];
3577 for (int j=0; j<3; j++) {
3578 Amat[i][j] = new double*[3];
3579 for (int k=0; k<3; k++)
3580 Amat[i][j][k] = new double[3];
3581 }
3582 }
3583
3584 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3585
3586 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
3587
3588 Teuchos::Array<int> indices(3);
3589 for (int T=0; T<elements->size(); T++) {
3590
3591 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
3592 detB = B.computeInverse(Binv);
3593 absDetB = std::fabs(detB);
3594
3595 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3596
3597 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3598 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3599 all_dPhiMat_Binv[i] = res;
3600 }
3601 std::vector<double> locStresses( nmbAllDPhi, 0. );
3602
3603 for (int p=0; p<nmbQuadPoints; p++){
3604
3605 SmallMatrix<SC> Fmat( dim, 0. );
3606 SmallMatrix<SC> tmpForScaling( dim, 0. );
3607 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3608
3609 for (int i=0; i<nmbScalarDPhi; i++) {
3610 indices.at(0) = dim * elements->at(T).at(i);
3611 indices.at(1) = dim * elements->at(T).at(i) + 1;
3612 indices.at(2) = dim * elements->at(T).at(i) + 2;
3613
3614 for (int j=0; j<dim; j++) {
3615 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3616 SC v = uArray[indices.at(j)];
3617 tmpForScaling.scale( v );
3618 Fmat += tmpForScaling;
3619 }
3620 }
3621
3622 for (int i=0; i<Fmat.size(); i++) {
3623 for (int j=0; j<Fmat.size(); j++) {
3624 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3625 }
3626 }
3627 if ( !material_model.compare("Neo-Hooke") )
3628 nh3d(v, &E, &nu, F, Pmat, Amat);
3629 else if ( !material_model.compare("Mooney-Rivlin") )
3630 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
3631
3632 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3633 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3634
3635 int offset = p * nmbAllDPhi;
3636 int offsetInArray = 0;
3637 for (int i=0; i<nmbAllDPhi; i++) {
3638 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3639 offsetInArray += sizeLocStiff;
3640 }
3641
3642
3643 double* fArray = new double[ sizeLocStiff ];
3644 for (int i=0; i<dim; i++) {
3645 for (int j=0; j<dim; j++) {
3646 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3647 }
3648 }
3649
3650 double* res = new double[ nmbAllDPhi ];
3651 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3652 for (int i=0; i<locStresses.size(); i++) {
3653 locStresses[i] += weights->at(p) * res[i];
3654 }
3655
3656 delete [] aceFEMFunc;
3657 delete [] allDPhiBlas;
3658 delete [] fArray;
3659 }
3660
3661
3662
3663 for (int i=0; i<nmbScalarDPhi; i++) {
3664 for (int d1=0; d1<dim; d1++) {
3665 LO row = dim * elements->at(T).at(i) + d1;
3666 SC v = absDetB * locStresses[ dim * i + d1 ];
3667 fValues[row] = v;
3668 }
3669 }
3670 }
3671
3672
3673 delete [] v;
3674 for (int i=0; i<3; i++)
3675 delete [] Pmat[i];
3676 delete [] Pmat;
3677 for (int i=0; i<3; i++)
3678 delete [] F[i];
3679 delete [] F;
3680
3681 for (int i=0; i<3; i++){
3682 for (int j=0; j<3; j++) {
3683 for (int k=0; k<3; k++)
3684 delete [] Amat[i][j][k];
3685 delete [] Amat[i][j];
3686 }
3687 delete [] Amat[i];
3688 }
3689 delete [] Amat;
3690
3691 }
3692}
3693
3695template <class SC, class LO, class GO, class NO>
3697 std::string FEType,
3698 MatrixPtr_Type &A,
3699 MultiVectorPtr_Type u,
3700 bool callFillComplete){
3701
3702 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3703 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3704
3705 UN FEloc = checkFE(dim,FEType);
3706
3707 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
3708
3709 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3710
3711 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3712
3713 vec3D_dbl_ptr_Type dPhi;
3714 vec2D_dbl_ptr_Type phi;
3715 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3716
3717 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
3718
3719 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1 ) +
3720 Helper::determineDegree( dim, FEType, Helper::Deriv0) +
3721 extraDeg;
3722
3723 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3724 Helper::getPhi(phi, weights, dim, FEType, deg);
3725 SC detB;
3726 SC absDetB;
3727 SmallMatrix<SC> B(dim);
3728 SmallMatrix<SC> Binv(dim);
3729 GO glob_i, glob_j;
3730 vec_dbl_Type v_i(dim);
3731 vec_dbl_Type v_j(dim);
3732
3733 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
3734 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3735
3736 for (UN T=0; T<elements->numberElements(); T++) {
3737
3738 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3739 detB = B.computeInverse(Binv);
3740 absDetB = std::fabs(detB);
3741
3742 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3743 applyBTinv( dPhi, dPhiTrans, Binv );
3744
3745 for (int w=0; w<phi->size(); w++){ //quads points
3746 for (int d=0; d<dim; d++) {
3747 uLoc[d][w] = 0.;
3748 for (int i=0; i < phi->at(0).size(); i++) {
3749 LO index = dim * elements->getElement(T).getNode(i) + d;
3750 uLoc[d][w] += uArray[index] * phi->at(w).at(i);
3751 }
3752 }
3753 }
3754
3755 for (UN i=0; i < phi->at(0).size(); i++) {
3756 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
3757 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
3758 for (UN j=0; j < value.size(); j++) {
3759 for (UN w=0; w<dPhiTrans.size(); w++) {
3760 for (UN d=0; d<dim; d++){
3761 value[j] += weights->at(w) * uLoc[d][w] * (*phi)[w][i] * dPhiTrans[w][j][d];
3762 }
3763
3764 }
3765 value[j] *= absDetB;
3766 if (setZeros_ && std::fabs(value[j]) < myeps_) {
3767 value[j] = 0.;
3768 }
3769
3770 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) );
3771 GO glob_j = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) );
3772 }
3773 for (UN d=0; d<dim; d++) {
3774 for (UN j=0; j < indices.size(); j++)
3775 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
3776
3777 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
3778 A->insertGlobalValues( row, indices(), value() );
3779 }
3780 }
3781 }
3782
3783
3784 if (callFillComplete)
3785 A->fillComplete();
3786}
3787
3789template <class SC, class LO, class GO, class NO>
3791 std::string FEType,
3792 MatrixPtr_Type &A,
3793 MultiVectorPtr_Type u,
3794 bool callFillComplete){
3795
3796 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3797 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3798 UN FEloc = checkFE(dim,FEType);
3799
3800 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
3801
3802 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3803
3804 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3805
3806 vec3D_dbl_ptr_Type dPhi;
3807 vec2D_dbl_ptr_Type phi;
3808 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3809
3810 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); //Elementwise assembly of u
3811
3812 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
3813
3814 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3815 Helper::getPhi(phi, weights, dim, FEType, deg);
3816
3817 SC detB;
3818 SC absDetB;
3819 SmallMatrix<SC> B(dim);
3820 SmallMatrix<SC> Binv(dim);
3821 GO glob_i, glob_j;
3822 vec_dbl_Type v_i(dim);
3823 vec_dbl_Type v_j(dim);
3824
3825 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3826
3827 for (UN T=0; T<elements->numberElements(); T++) {
3828
3829 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3830 detB = B.computeInverse(Binv);
3831 absDetB = std::fabs(detB);
3832
3833 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3834 applyBTinv( dPhi, dPhiTrans, Binv );
3835
3836 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)
3837
3838 for (int w=0; w<dPhiTrans.size(); w++){ //quads points
3839 for (int d1=0; d1<dim; d1++) {
3840 for (int i=0; i < dPhiTrans[0].size(); i++) {
3841 LO index = dim * elements->getElement(T).getNode(i) + d1;
3842 for (int d2=0; d2<dim; d2++)
3843 duLoc[w][d2][d1] += uArray[index] * dPhiTrans[w][i][d2];
3844 }
3845 }
3846 }
3847
3848 for (UN i=0; i < phi->at(0).size(); i++) {
3849 for (UN d1=0; d1<dim; d1++) {
3850 Teuchos::Array<SC> value( dim*phi->at(0).size(), 0. ); //These are value (W_ix,W_iy,W_iz)
3851 Teuchos::Array<GO> indices( dim*phi->at(0).size(), 0 );
3852 for (UN j=0; j < phi->at(0).size(); j++) {
3853 for (UN d2=0; d2<dim; d2++){
3854 for (UN w=0; w<phi->size(); w++) {
3855 value[ dim * j + d2 ] += weights->at(w) * duLoc[w][d2][d1] * (*phi)[w][i] * (*phi)[w][j];
3856 }
3857 value[ dim * j + d2 ] *= absDetB;
3858
3859 if (setZeros_ && std::fabs(value[ dim * j + d2 ]) < myeps_) {
3860 value[ dim * j + d2 ] = 0.;
3861 }
3862 }
3863 }
3864 for (UN j=0; j < phi->at(0).size(); j++){
3865 for (UN d2=0; d2<dim; d2++){
3866 indices[ dim * j + d2 ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3867 }
3868 }
3869
3870 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3871 A->insertGlobalValues( row, indices(), value() );
3872 }
3873 }
3874 }
3875 if (callFillComplete)
3876 A->fillComplete();
3877}
3878
3880template <class SC, class LO, class GO, class NO>
3882 std::string FEType,
3883 std::string FETypeV,
3884 MatrixPtr_Type &A,
3885 MultiVectorPtr_Type u,
3886 bool callFillComplete){
3887
3888 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3889 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3890
3891 UN FEloc = checkFE(dim,FEType);
3892
3893 ElementsPtr_Type elements = domainVec_.at(1)->getElementsC();
3894 ElementsPtr_Type elementsVel = domainVec_.at(0)->getElementsC();
3895
3896 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(1)->getPointsRepeated();
3897
3898 MapConstPtr_Type map = domainVec_.at(1)->getMapRepeated();
3899
3900 vec3D_dbl_ptr_Type dPhi;
3901 vec2D_dbl_ptr_Type phi,phiV;
3902 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3903
3904 UN degV = Helper::determineDegree( dim, FETypeV, Helper::Deriv0); //Elementwise assembly of u
3905 UN degP = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of p
3906 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) + degV + degP;
3907
3908 Helper::getDPhi(dPhi, weights, dim, FEType, deg); // Dphi for \nabla p
3909 Helper::getPhi(phi, weights, dim, FEType, deg); // phi for u
3910 Helper::getPhi(phiV, weights, dim, FETypeV, deg); // phi for p
3911
3912 SC detB;
3913 SC absDetB;
3914 SmallMatrix<SC> B(dim);
3915 SmallMatrix<SC> Binv(dim);
3916 GO glob_i, glob_j;
3917 vec_dbl_Type v_i(dim);
3918 vec_dbl_Type v_j(dim);
3919
3920 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
3921 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3922
3923 for (UN T=0; T<elements->numberElements(); T++) {
3924
3925 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3926 detB = B.computeInverse(Binv);
3927 absDetB = std::fabs(detB);
3928
3929 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3930 applyBTinv( dPhi, dPhiTrans, Binv );
3931
3932 for (int w=0; w<phiV->size(); w++){ //quads points
3933 for (int d=0; d<dim; d++) {
3934 uLoc[d][w] = 0.;
3935 for (int i=0; i < phiV->at(0).size(); i++) {
3936 LO index = dim * elementsVel->getElement(T).getNode(i) + d;
3937 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
3938 }
3939 }
3940 }
3941
3942 for (UN i=0; i < phi->at(0).size(); i++) {
3943 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
3944 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
3945 for (UN j=0; j < value.size(); j++) {
3946 for (UN w=0; w<dPhiTrans.size(); w++) {
3947 for (UN d=0; d<dim; d++){
3948 value[j] += weights->at(w) * uLoc[d][w]* dPhiTrans[w][j][d] * (*phi)[w][i] ;
3949 }
3950 }
3951 value[j] *= absDetB;
3952 indices[j] = GO ( map->getGlobalElement( elements->getElement(T).getNode(j) ) );
3953 }
3954
3955 GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
3956 A->insertGlobalValues( row, indices(), value() );
3957
3958 }
3959 }
3960
3961
3962 if (callFillComplete)
3963 A->fillComplete();
3964}
3965
3967template <class SC, class LO, class GO, class NO>
3969 std::string FEType1,
3970 std::string FEType2,
3971 int degree,
3972 MatrixPtr_Type &Bmat,
3973 MatrixPtr_Type &BTmat,
3974 MapConstPtr_Type map1,
3975 MapConstPtr_Type map2,
3976 bool callFillComplete) {
3977
3978
3979 UN FEloc1 = checkFE(dim,FEType1);
3980 UN FEloc2 = checkFE(dim,FEType2);
3981
3982 ElementsPtr_Type elements1 = domainVec_.at(FEloc1)->getElementsC();
3983 ElementsPtr_Type elements2 = domainVec_.at(FEloc2)->getElementsC();
3984
3985 vec2D_dbl_ptr_Type pointsRep1 = domainVec_.at(FEloc1)->getPointsRepeated();
3986
3987 MapConstPtr_Type mapping1 = domainVec_.at(FEloc1)->getMapRepeated();
3988 MapConstPtr_Type mapping2;
3989
3990 if (FEType2 == "P0")
3991 mapping2 = domainVec_.at(FEloc2)->getElementMap();
3992 else
3993 mapping2 = domainVec_.at(FEloc2)->getMapRepeated();
3994
3995 vec3D_dbl_ptr_Type dPhi;
3996 vec2D_dbl_ptr_Type phi;
3997 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3998
3999 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
4001
4002 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
4003
4004 // if (FEType2=="P1-disc-global")
4005 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
4006 if (FEType2=="P1-disc" && FEType1=="Q2" )
4007 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
4008 else
4009 Helper::getPhi(phi, weights, dim, FEType2, deg);
4010
4011 SC detB;
4012 SC absDetB;
4013 SmallMatrix<SC> B(dim);
4014 SmallMatrix<SC> Binv(dim);
4015 GO glob_i, glob_j;
4016 vec_dbl_Type v_i(dim);
4017 vec_dbl_Type v_j(dim);
4018
4019 for (UN T=0; T<elements1->numberElements(); T++) {
4020
4021 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
4022 detB = B.computeInverse(Binv);
4023 absDetB = std::fabs(detB);
4024
4025 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4026 applyBTinv( dPhi, dPhiTrans, Binv );
4027
4028 for (UN i=0; i < phi->at(0).size(); i++) {
4029 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( dPhiTrans[0].size(), 0. ) );
4030 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
4031
4032 for (UN j=0; j < valueVec[0].size(); j++) {
4033 for (UN w=0; w<dPhiTrans.size(); w++) {
4034 for (UN d=0; d<dim; d++)
4035 valueVec[d][j] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
4036 }
4037 for (UN d=0; d<dim; d++){
4038 valueVec[d][j] *= absDetB;
4039 if (setZeros_ && std::fabs(valueVec[d][j]) < myeps_) {
4040 valueVec[d][j] = 0.;
4041 }
4042 }
4043 }
4044 for (UN d=0; d<dim; d++) {
4045 for (UN j=0; j < indices.size(); j++)
4046 indices[j] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
4047
4048 GO row;
4049 if (FEType2=="P0")
4050 row = GO ( mapping2->getGlobalElement( T ) );
4051 else
4052 row = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
4053 Bmat->insertGlobalValues( row, indices(), valueVec[d]() );
4054 }
4055 }
4056
4057 // We compute value twice, maybe we should change this
4058 for (UN i=0; i < dPhiTrans[0].size(); i++) {
4059
4060 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( phi->at(0).size(), 0. ) );
4061 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
4062 for (UN j=0; j < valueVec[0].size(); j++) {
4063 for (UN w=0; w<dPhiTrans.size(); w++) {
4064 for (UN d=0; d<dim; d++)
4065 valueVec[d][j] += weights->at(w) * phi->at(w)[j] * dPhiTrans[w][i][d];
4066 }
4067 for (UN d=0; d<dim; d++){
4068 valueVec[d][j] *= absDetB;
4069 if (setZeros_ && std::fabs(valueVec[d][j]) < myeps_) {
4070 valueVec[d][j] = 0.;
4071 }
4072 }
4073 }
4074
4075 for (UN j=0; j < indices.size(); j++){
4076 if (FEType2=="P0")
4077 indices[j] = GO ( mapping2->getGlobalElement( T ) );
4078 else
4079 indices[j] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(j) ) );
4080 }
4081 for (UN d=0; d<dim; d++) {
4082 GO row = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(i) ) + d );
4083 BTmat->insertGlobalValues( row, indices(), valueVec[d]() );
4084 }
4085
4086 }
4087
4088 }
4089 if (callFillComplete) {
4090 Bmat->fillComplete( map1, map2 );
4091 BTmat->fillComplete( map2, map1 );
4092 }
4093
4094}
4095
4097template <class SC, class LO, class GO, class NO>
4099 std::string FEType1,
4100 std::string FEType2,
4101 int degree,
4102 MatrixPtr_Type &Bmat,
4103 MatrixPtr_Type &BTmat,
4104 MapConstPtr_Type map1,
4105 MapConstPtr_Type map2,
4106 bool callFillComplete) {
4107
4108
4109 UN FEloc1 = checkFE(dim,FEType1);
4110 UN FEloc2 = checkFE(dim,FEType2);
4111
4112 ElementsPtr_Type elements1 = domainVec_.at(FEloc1)->getElementsC();
4113 ElementsPtr_Type elements2 = domainVec_.at(FEloc2)->getElementsC();
4114
4115 vec2D_dbl_ptr_Type pointsRep1 = domainVec_.at(FEloc1)->getPointsRepeated();
4116
4117 MapConstPtr_Type mapping1 = domainVec_.at(FEloc1)->getMapRepeated();
4118 MapConstPtr_Type mapping2;
4119
4120 if (FEType2 == "P0")
4121 mapping2 = domainVec_.at(FEloc2)->getElementMap();
4122 else
4123 mapping2 = domainVec_.at(FEloc2)->getMapRepeated();
4124
4125 vec3D_dbl_ptr_Type dPhi;
4126 vec2D_dbl_ptr_Type phi;
4127 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4128
4129 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
4131
4132 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
4133
4134 // if (FEType2=="P1-disc-global")
4135 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
4136 if (FEType2=="P1-disc" && FEType1=="Q2" )
4137 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
4138 else
4139 Helper::getPhi(phi, weights, dim, FEType2, deg);
4140
4141 SC detB;
4142 SC absDetB;
4143 SmallMatrix<SC> B(dim);
4144 SmallMatrix<SC> Binv(dim);
4145 GO glob_i, glob_j;
4146 vec_dbl_Type v_i(dim);
4147 vec_dbl_Type v_j(dim);
4148
4149 Teuchos::Array<GO> colIndex( 1, 0 );
4150 Teuchos::Array<GO> rowIndex( 1, 0 );
4151 Teuchos::Array<SC> value(1, 0.);
4152
4153 for (UN T=0; T<elements1->numberElements(); T++) {
4154
4155 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
4156 detB = B.computeInverse(Binv);
4157 absDetB = std::fabs(detB);
4158
4159 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4160 applyBTinv( dPhi, dPhiTrans, Binv );
4161
4162 for (UN i=0; i < phi->at(0).size(); i++) {
4163 if (FEType2=="P0")
4164 rowIndex[0] = GO ( mapping2->getGlobalElement( T ) );
4165 else
4166 rowIndex[0] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
4167
4168 for (UN j=0; j < dPhiTrans[0].size(); j++) {
4169 for (UN d=0; d<dim; d++){
4170 value[0] = 0.;
4171 for (UN w=0; w<dPhiTrans.size(); w++)
4172 value[0] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
4173 value[0] *= absDetB;
4174 colIndex[0] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
4175 Bmat->insertGlobalValues( rowIndex[0], colIndex(), value() );
4176 BTmat->insertGlobalValues( colIndex[0], rowIndex(), value() );
4177
4178 }
4179 }
4180 }
4181
4182 }
4183 if (callFillComplete) {
4184 Bmat->fillComplete( map1, map2 );
4185 BTmat->fillComplete( map2, map1 );
4186 }
4187
4188}
4189
4191template <class SC, class LO, class GO, class NO>
4193 std::string FEType,
4194 MatrixPtr_Type &A,
4195 bool callFillComplete){
4196
4197 TEUCHOS_TEST_FOR_EXCEPTION(FEType != "P1" && FEType != "Q1",std::logic_error, "Only implemented for P1, Q1.");
4198 UN FEloc = checkFE(dim,FEType);
4199
4200 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4201
4202 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4203
4204 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4205
4206 vec2D_dbl_ptr_Type phi;
4207
4208 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4209
4210 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
4211
4212 Helper::getPhi( phi, weights, dim, FEType, deg );
4213
4214 SC detB;
4215 SC absDetB;
4216 SmallMatrix<SC> B(dim);
4217 GO glob_i, glob_j;
4218 vec_dbl_Type v_i(dim);
4219 vec_dbl_Type v_j(dim);
4220
4221 SC refElementSize;
4222 SC refElementScale;
4223 if(FEType=="P1"){
4224 if (dim==2) {
4225 refElementSize = 0.5;
4226 refElementScale = 1./9.;
4227 }
4228 else if(dim==3){
4229 refElementSize = 1./6.;
4230 refElementScale = 1./16.;
4231 }
4232 }
4233 else if(FEType=="Q1"){
4234 if(dim==3){
4235 refElementScale=1./64;
4236 refElementSize=8.;
4237 }
4238 else{
4239 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Q1 Only implemented for 3D.");
4240 }
4241 }
4242
4243 for (UN T=0; T<elements->numberElements(); T++) {
4244
4245 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4246 detB = B.computeDet( );
4247 absDetB = std::fabs(detB);
4248
4249 for (UN i=0; i < phi->at(0).size(); i++) {
4250 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
4251 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
4252 for (UN j=0; j < value.size(); j++) {
4253 for (UN w=0; w<phi->size(); w++) {
4254 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
4255 }
4256 value[j] *= absDetB;
4257 value[j] -= refElementSize * absDetB * refElementScale;
4258
4259 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
4260 }
4261
4262 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
4263 A->insertGlobalValues( row, indices(), value() );
4264 }
4265
4266 }
4267
4268 if (callFillComplete)
4269 A->fillComplete();
4270}
4271
4272
4273
4274template <class SC, class LO, class GO, class NO>
4276 std::string FEType,
4277 MatrixPtr_Type &A,
4278 CoeffFuncDbl_Type func,
4279 double* parameters,
4280 bool callFillComplete)
4281{
4282 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4283 int FEloc = this->checkFE(dim,FEType);
4284
4285 DomainConstPtr_Type domain = domainVec_.at(FEloc);
4286 ElementsPtr_Type elements = domain->getElementsC();
4287 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
4288 MapConstPtr_Type map = domain->getMapRepeated();
4289
4290 vec3D_dbl_ptr_Type dPhi;
4291 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4292 vec2D_dbl_ptr_Type quadPts;
4293
4294 // double val, value1_j, value2_j , value1_i, value2_i;
4295
4296 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4297
4298 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4299 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi, FEType);
4300
4301 // SC = double, GO = long, UN = int
4302 SC detB;
4303 SC absDetB;
4304 SmallMatrix<SC> B(dim);
4305 SmallMatrix<SC> Binv(dim);
4306 GO glob_i, glob_j;
4307
4308
4309 vec_dbl_ptr_Type dist = domain->getDistancesToInterface();
4310 if (dim == 2)
4311 {
4312 double val, value1_j, value2_j , value1_i, value2_i;
4313 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
4314
4315 double distance1, distance2, distance3;
4316 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
4317 for (int T = 0; T < elements->numberElements(); T++)
4318 {
4319 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4320 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4321 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4322
4323 distance1 = dist->at(elements->getElement(T).getNode(0));
4324 distance2 = dist->at(elements->getElement(T).getNode(1));
4325 distance3 = dist->at(elements->getElement(T).getNode(2));
4326
4327 distance_mean.at(0) = (distance1 + distance2 + distance3)/3.0; // Mittelwert
4328 double funcvalue = func(&distance_mean.at(0),parameters);
4329
4330 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4331 detB = B.computeInverse(Binv);
4332 absDetB = std::fabs(detB);
4333
4334 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4335 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4336 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4337
4338 for (int i = 0; i < dPhi->at(0).size(); i++)
4339 {
4340 Teuchos::Array<SC> value( 1, 0. );
4341 Teuchos::Array<GO> indices( 1, 0 );
4342
4343 for (int j = 0; j < dPhi->at(0).size(); j++)
4344 {
4345 val = 0.0;
4346 for (int k = 0; k < dPhi->size(); k++)
4347 {
4348
4349 value1_j = dPhiTrans.at(k).at(j).at(0);
4350 value2_j = dPhiTrans.at(k).at(j).at(1);
4351
4352 value1_i = dPhiTrans.at(k).at(i).at(0);
4353 value2_i = dPhiTrans.at(k).at(i).at(1);
4354
4355 val = val + funcvalue * weightsDPhi->at(k) * ( value1_j*value1_i + value2_j*value2_i );
4356 }
4357 val = absDetB * val;
4358 value[0] = val;
4359
4360 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4361 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4362 indices[0] = glob_j;
4363
4364
4365 A->insertGlobalValues(glob_i, indices(), value());
4366 glob_j++;
4367 indices[0] = glob_j;
4368 A->insertGlobalValues(glob_i+1, indices(), value());
4369 }
4370 }
4371 }
4372 if (callFillComplete)
4373 {
4374 A->fillComplete();
4375 }
4376 }
4377 else if(dim == 3)
4378 {
4379 double val, value1_j, value2_j ,value3_j, value1_i, value2_i ,value3_i;
4380
4381 long long glob_i, glob_j;
4382 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4383
4384 double distance1, distance2, distance3, distance4;
4385 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
4386 for (int T = 0; T < elements->numberElements(); T++)
4387 {
4388 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4389 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4390 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4391 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4392
4393 distance1 = dist->at(elements->getElement(T).getNode(0));
4394 distance2 = dist->at(elements->getElement(T).getNode(1));
4395 distance3 = dist->at(elements->getElement(T).getNode(2));
4396 distance4 = dist->at(elements->getElement(T).getNode(3));
4397
4398 distance_mean.at(0) = (distance1 + distance2 + distance3 + distance4)/4.0; //Mittelwert
4399 double funcvalue = func(&distance_mean.at(0),parameters);
4400
4401 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4402 detB = B.computeInverse(Binv);
4403 absDetB = std::fabs(detB);
4404
4405 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4406 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4407 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4408
4409 for (int i = 0; i < dPhi->at(0).size(); i++)
4410 {
4411 Teuchos::Array<SC> value( 1, 0. );
4412 Teuchos::Array<GO> indices( 1, 0 );
4413
4414 for (int j = 0; j < dPhi->at(0).size(); j++)
4415 {
4416 val = 0.0;
4417 for (int k = 0; k < dPhi->size(); k++)
4418 {
4419 value1_j = dPhiTrans.at(k).at(j).at(0);
4420 value2_j = dPhiTrans.at(k).at(j).at(1);
4421 value3_j = dPhiTrans.at(k).at(j).at(2);
4422
4423 value1_i = dPhiTrans.at(k).at(i).at(0);
4424 value2_i = dPhiTrans.at(k).at(i).at(1);
4425 value3_i = dPhiTrans.at(k).at(i).at(2);
4426
4427 val = val + funcvalue * weightsDPhi->at(k) * (value1_j*value1_i + value2_j*value2_i + value3_j*value3_i);
4428 }
4429 val = absDetB * val;
4430 value[0] = val;
4431
4432 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4433 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4434 indices[0] = glob_j;
4435 A->insertGlobalValues(glob_i, indices(), value());
4436 glob_j++;
4437 indices[0] = glob_j;
4438 A->insertGlobalValues(glob_i+1, indices(), value());
4439 glob_j++;
4440 indices[0] = glob_j;
4441 A->insertGlobalValues(glob_i+2, indices(), value());
4442
4443 }
4444 }
4445 }
4446 if (callFillComplete)
4447 {
4448 A->fillComplete();
4449 }
4450 }
4451
4452}
4453
4454
4455
4456template <class SC, class LO, class GO, class NO>
4458 std::string FEType,
4459 MatrixPtr_Type &A,
4460 CoeffFunc_Type func,
4461 int* parameters,
4462 bool callFillComplete)
4463{
4464 // 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.
4465 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4466 int FEloc = this->checkFE(dim,FEType);
4467
4468 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4469 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4470 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4471
4472 vec3D_dbl_ptr_Type dPhi;
4473 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4474 vec2D_dbl_ptr_Type quadPts;
4475
4476 // double value, value1_j, value2_j , value1_i, value2_i;
4477
4478 // inner( grad(u) + grad(u)^T , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
4479 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4480 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4481 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4482
4483 // SC = double, GO = long, UN = int
4484 SC detB;
4485 SC absDetB;
4486 SmallMatrix<SC> B(dim);
4487 SmallMatrix<SC> Binv(dim);
4488 GO glob_i, glob_j;
4489
4490 if (dim == 2)
4491 {
4492 double v11, v12, v21, v22, value1_j, value2_j , value1_i, value2_i;
4493 double e_11_j_1,e_12_j_1,e_21_j_1,e_22_j_1;
4494 double e_11_j_2,e_12_j_2,e_21_j_2,e_22_j_2;
4495 double e_11_i_1,e_12_i_1,e_21_i_1,e_22_i_1;
4496 double e_11_i_2,e_12_i_2,e_21_i_2,e_22_i_2;
4497
4498 SmallMatrix<double> tmpRes1(dim);
4499 SmallMatrix<double> tmpRes2(dim);
4500 SmallMatrix<double> e1i(dim);
4501 SmallMatrix<double> e2i(dim);
4502 SmallMatrix<double> e1j(dim);
4503 SmallMatrix<double> e2j(dim);
4504
4505 long long glob_i, glob_j;
4506 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
4507
4508 vec_dbl_Type xy(2);
4509 for (int T = 0; T < elements->numberElements(); T++)
4510 {
4511 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4512 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4513 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4514
4515 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
4516 detB = B.computeInverse(Binv);
4517 absDetB = std::fabs(detB);
4518
4519 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1)
4520 // Also \hat{grad_phi}.
4521 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4522 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4523
4524 for (int i = 0; i < dPhi->at(0).size(); i++)
4525 {
4526 Teuchos::Array<SC> value11( 1, 0. );
4527 Teuchos::Array<SC> value12( 1, 0. );
4528 Teuchos::Array<SC> value21( 1, 0. );
4529 Teuchos::Array<SC> value22( 1, 0. );
4530 Teuchos::Array<GO> indices( 1, 0 );
4531
4532 for (int j=0; j < dPhi->at(0).size(); j++)
4533 {
4534 v11 = 0.0;v12 = 0.0;v21 = 0.0;v22 = 0.0;
4535 for (int k = 0; k < dPhi->size(); k++)
4536 {
4537 // Mappen der Gausspunkte (definiert auf T_ref) auf T (bzw. \Omega)
4538 // xy = F(quadPts) = B*quadPts + b, mit b = p1 (affin lineare Transformation)
4539 xy[0]=0.; xy[1]=0.;
4540 for (int r=0; r<2; r++) {
4541 xy[0] += B[0][r]*quadPts->at(k).at(r);
4542 xy[1] += B[1][r]*quadPts->at(k).at(r);
4543 }
4544 xy[0] += p1[0];
4545 xy[1] += p1[1];
4546
4547 value1_j = dPhiTrans.at(k).at(j).at(0);
4548 value2_j = dPhiTrans.at(k).at(j).at(1);
4549
4550 value1_i = dPhiTrans.at(k).at(i).at(0);
4551 value2_i = dPhiTrans.at(k).at(i).at(1);
4552
4553 tmpRes1[0][0] = value1_j;
4554 tmpRes1[0][1] = value2_j;
4555 tmpRes1[1][0] = 0.;
4556 tmpRes1[1][1] = 0.;
4557
4558 tmpRes2[0][0] = value1_j;
4559 tmpRes2[0][1] = 0.;
4560 tmpRes2[1][0] = value2_j;
4561 tmpRes2[1][1] = 0.;
4562
4563 tmpRes1.add(tmpRes2,e1j/*result*/);
4564
4565 e1i[0][0] = value1_i;
4566 e1i[0][1] = value2_i;
4567
4568
4569 tmpRes1[0][0] = 0.;
4570 tmpRes1[0][1] = 0.;
4571 tmpRes1[1][0] = value1_j;
4572 tmpRes1[1][1] = value2_j;
4573
4574 tmpRes2[0][0] = 0.;
4575 tmpRes2[0][1] = value1_j;
4576 tmpRes2[1][0] = 0.;
4577 tmpRes2[1][1] = value2_j;
4578
4579 tmpRes1.add(tmpRes2,e2j/*result*/);
4580
4581 e2i[1][0] = value1_i;
4582 e2i[1][1] = value2_i;
4583
4584 double funcvalue = func(&xy.at(0),parameters);
4585 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
4586 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
4587 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
4588 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
4589
4590 }
4591
4592 v11 = absDetB * v11;
4593 v12 = absDetB * v12;
4594 v21 = absDetB * v21;
4595 v22 = absDetB * v22;
4596
4597 value11[0] = v11;
4598 value12[0] = v12;
4599 value21[0] = v21;
4600 value22[0] = v22;
4601
4602 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4603 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4604 indices[0] = glob_j;
4605
4606 A->insertGlobalValues(glob_i, indices(), value11());
4607 A->insertGlobalValues(glob_i+1, indices(), value21());
4608 glob_j++;
4609 indices[0] = glob_j;
4610 A->insertGlobalValues(glob_i, indices(), value12());
4611 A->insertGlobalValues(glob_i+1, indices(), value22());
4612 }
4613 }
4614 }
4615 if (callFillComplete)
4616 {
4617 A->fillComplete();
4618 }
4619 }
4620 else if(dim == 3)
4621 {
4622 double v11, v12, v13, v21, v22, v23, v31, v32, v33, value1_j, value2_j, value3_j , value1_i, value2_i, value3_i;
4623
4624 SmallMatrix<double> e1i(dim);
4625 SmallMatrix<double> e2i(dim);
4626 SmallMatrix<double> e3i(dim);
4627 SmallMatrix<double> e1j(dim);
4628 SmallMatrix<double> e2j(dim);
4629 SmallMatrix<double> e3j(dim);
4630
4631 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4632 vec_dbl_Type xyz(3);
4633
4634 for (int T = 0; T < elements->numberElements(); T++)
4635 {
4636 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4637 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4638 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4639 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4640
4641 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4642 detB = B.computeInverse(Binv);
4643 absDetB = std::fabs(detB);
4644
4645 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4646 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4647 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4648
4649 for (int i = 0; i < dPhi->at(0).size(); i++)
4650 {
4651 Teuchos::Array<SC> value11( 1, 0. );
4652 Teuchos::Array<SC> value12( 1, 0. );
4653 Teuchos::Array<SC> value13( 1, 0. );
4654 Teuchos::Array<SC> value21( 1, 0. );
4655 Teuchos::Array<SC> value22( 1, 0. );
4656 Teuchos::Array<SC> value23( 1, 0. );
4657 Teuchos::Array<SC> value31( 1, 0. );
4658 Teuchos::Array<SC> value32( 1, 0. );
4659 Teuchos::Array<SC> value33( 1, 0. );
4660 Teuchos::Array<GO> indices( 1, 0 );
4661
4662 for (int j = 0; j < dPhi->at(0).size(); j++)
4663 {
4664 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;
4665 for (int k = 0; k < dPhi->size(); k++)
4666 {
4667
4668 xyz[0]=0.; xyz[1]=0.; xyz[2]=0.;
4669 for (int r = 0; r < 3; r++)
4670 {
4671 xyz[0] += B[0][r]*quadPts->at(k).at(r);
4672 xyz[1] += B[1][r]*quadPts->at(k).at(r);
4673 xyz[2] += B[2][r]*quadPts->at(k).at(r);
4674 }
4675 xyz[0] += p1[0];
4676 xyz[1] += p1[1];
4677 xyz[2] += p1[2];
4678
4679
4680
4681 value1_j = dPhiTrans.at(k).at(j).at(0);
4682 value2_j = dPhiTrans.at(k).at(j).at(1);
4683 value3_j = dPhiTrans.at(k).at(j).at(2);
4684
4685
4686 value1_i = dPhiTrans.at(k).at(i).at(0);
4687 value2_i = dPhiTrans.at(k).at(i).at(1);
4688 value3_i = dPhiTrans.at(k).at(i).at(2);
4689
4690
4691 e1j[0][0] = 2.*value1_j;
4692 e1j[0][1] = value2_j;
4693 e1j[0][2] = value3_j;
4694 e1j[1][0] = value2_j;
4695 e1j[2][0] = value3_j;
4696
4697 e1i[0][0] = value1_i;
4698 e1i[0][1] = value2_i;
4699 e1i[0][2] = value3_i;
4700
4701
4702 e2j[1][0] = value1_j;
4703 e2j[1][1] = 2.*value2_j;
4704 e2j[1][2] = value3_j;
4705 e2j[0][1] = value1_j;
4706 e2j[2][1] = value3_j;
4707
4708 e2i[1][0] = value1_i;
4709 e2i[1][1] = value2_i;
4710 e2i[1][2] = value3_i;
4711
4712
4713 e3j[2][0] = value1_j;
4714 e3j[2][1] = value2_j;
4715 e3j[2][2] = 2.*value3_j;
4716 e3j[0][2] = value1_j;
4717 e3j[1][2] = value2_j;
4718
4719 e3i[2][0] = value1_i;
4720 e3i[2][1] = value2_i;
4721 e3i[2][2] = value3_i;
4722
4723 double funcvalue = func(&xyz.at(0),parameters);
4724
4725 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
4726 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
4727 v13 = v13 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e3j);
4728
4729 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
4730 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
4731 v23 = v23 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e3j);
4732
4733 v31 = v31 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e1j);
4734 v32 = v32 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e2j);
4735 v33 = v33 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e3j);
4736
4737
4738 }
4739 v11 = absDetB * v11;
4740 v12 = absDetB * v12;
4741 v13 = absDetB * v13;
4742 v21 = absDetB * v21;
4743 v22 = absDetB * v22;
4744 v23 = absDetB * v23;
4745 v31 = absDetB * v31;
4746 v32 = absDetB * v32;
4747 v33 = absDetB * v33;
4748
4749 value11[0] = v11;
4750 value12[0] = v12;
4751 value13[0] = v13;
4752 value21[0] = v21;
4753 value22[0] = v22;
4754 value23[0] = v23;
4755 value31[0] = v31;
4756 value32[0] = v32;
4757 value33[0] = v33;
4758
4759 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4760 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4761 indices[0] = glob_j;
4762 A->insertGlobalValues(glob_i, indices(), value11());
4763 A->insertGlobalValues(glob_i+1, indices(), value21());
4764 A->insertGlobalValues(glob_i+2, indices(), value31());
4765
4766 glob_j++;
4767 indices[0] = glob_j;
4768 A->insertGlobalValues(glob_i, indices(), value12());
4769 A->insertGlobalValues(glob_i+1, indices(), value22());
4770 A->insertGlobalValues(glob_i+2, indices(), value32());
4771
4772 glob_j++;
4773 indices[0] = glob_j;
4774 A->insertGlobalValues(glob_i, indices(), value13());
4775 A->insertGlobalValues(glob_i+1, indices(), value23());
4776 A->insertGlobalValues(glob_i+2, indices(), value33());
4777 }
4778 }
4779 }
4780 if (callFillComplete)
4781 {
4782 A->fillComplete();
4783 }
4784 }
4785
4786}
4787
4788
4789
4790template <class SC, class LO, class GO, class NO>
4792 std::string FEType,
4793 MatrixPtr_Type &A,
4794 double lambda,
4795 double mu,
4796 bool callFillComplete)
4797{
4798 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4799 int FEloc = this->checkFE(dim,FEType);
4800
4801 // Hole Elemente und Knotenliste
4802 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4803 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4804 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4805
4806 vec3D_dbl_ptr_Type dPhi;
4807 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4808 vec2D_dbl_ptr_Type quadPts;
4809
4810 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4811
4812 // Hole die grad_phi, hier DPhi
4813 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4814 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4815
4816 // Definiere die Basisfunktion \phi_i bzw. \phi_j
4817 // vec_dbl_Type basisValues_i(dim,0.), basisValues_j(dim,0.);
4818
4819 // SC = double, GO = long, UN = int
4820 SC detB;
4821 SC absDetB;
4822 SmallMatrix<SC> B(dim);
4823 SmallMatrix<SC> Binv(dim);
4824 GO glob_i, glob_j;
4825
4826 // Fuer Zwischenergebniss
4827 SC res;
4828
4829 // Fuer die Berechnung der Spur
4830 double res_trace_i, res_trace_j;
4831
4832 if (dim == 2)
4833 {
4834
4835 double v11, v12, v21, v22;
4836 // Setzte Vektoren der Groesse 2 und initialisiere mit 0.0 (double)
4837 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
4838
4839 // Matrizen der Groesse (2x2) in denen die einzelnen Epsilon-Tensoren berechnet werden.
4840 // Siehe unten fuer mehr.
4841 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
4842 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
4843
4844 for (int T = 0; T < elements->numberElements(); T++)
4845 {
4846 // Hole die Eckknoten des Dreiecks
4847 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4848 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4849 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4850
4851 // Berechne die Transormationsmatrix B fuer das jeweilige Element (2D)
4852 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4853 detB = B.computeInverse(Binv);
4854 absDetB = std::fabs(detB);
4855
4856 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1).
4857 // Also \hat{grad_phi}.
4858 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4859 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4860
4861 for (int i = 0; i < dPhi->at(0).size(); i++)
4862 {
4863 Teuchos::Array<SC> value11( 1, 0. );
4864 Teuchos::Array<SC> value12( 1, 0. );
4865 Teuchos::Array<SC> value21( 1, 0. );
4866 Teuchos::Array<SC> value22( 1, 0. );
4867 Teuchos::Array<GO> indices( 1, 0 );
4868
4869 for (int j = 0; j < dPhi->at(0).size(); j++)
4870 {
4871 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
4872 for (int k = 0; k < dPhi->size(); k++)
4873 {
4874 // In epsilonValuesMat1_i (2x2 Matrix) steht fuer die Ansatzfunktion i bzw. \phi_i
4875 // der epsilonTensor fuer eine skalare Ansatzfunktion fuer die Richtung 1 (vgl. Mat1).
4876 // Also in Mat1_i wird dann also phi_i = (phi_scalar_i, 0) gesetzt und davon \eps berechnet.
4877
4878 // Stelle \hat{grad_phi_i} = basisValues_i auf, also B^(-T)*grad_phi_i
4879 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
4880
4881 // \eps(v) = \eps(phi_i)
4882 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
4883 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
4884
4885 // Siehe oben, nur fuer j
4886 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4887
4888 // \eps(u) = \eps(phi_j)
4889 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
4890 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
4891
4892 // Nun berechnen wir \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
4893 // Das Ergebniss steht in res.
4894 // Berechne zudem noch die Spur der Epsilon-Tensoren tr(\eps(u)) (j) und tr(\eps(v)) (i)
4895 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
4896 epsilonValuesMat1_i.trace(res_trace_i);
4897 epsilonValuesMat1_j.trace(res_trace_j);
4898 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4899
4900 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
4901 epsilonValuesMat1_i.trace(res_trace_i);
4902 epsilonValuesMat2_j.trace(res_trace_j);
4903 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4904
4905 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
4906 epsilonValuesMat2_i.trace(res_trace_i);
4907 epsilonValuesMat1_j.trace(res_trace_j);
4908 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4909
4910 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
4911 epsilonValuesMat2_i.trace(res_trace_i);
4912 epsilonValuesMat2_j.trace(res_trace_j);
4913 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4914
4915
4916 }
4917 // Noch mit der abs(det(B)) skalieren
4918 v11 = absDetB * v11;
4919 v12 = absDetB * v12;
4920 v21 = absDetB * v21;
4921 v22 = absDetB * v22;
4922
4923 value11[0] = v11;
4924 value12[0] = v12;
4925 value21[0] = v21;
4926 value22[0] = v22;
4927
4928 // Hole die globale Zeile und Spalte in der die Eintraege hingeschrieben werden sollen
4929 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4930 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4931 indices[0] = glob_j;
4932 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
4933 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
4934 glob_j++;
4935 indices[0] = glob_j;
4936 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
4937 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
4938 }
4939 }
4940 }
4941 if (callFillComplete)
4942 {
4943 A->fillComplete();
4944 }
4945 }
4946 else if(dim == 3)
4947 {
4948
4949 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
4950
4951 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4952 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
4953 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
4954
4955 for (int T = 0; T < elements->numberElements(); T++)
4956 {
4957 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4958 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4959 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4960 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4961
4962 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4963 detB = B.computeInverse(Binv);
4964 absDetB = std::fabs(detB);
4965
4966 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4967 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4968 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4969
4970 for (int i = 0; i < dPhi->at(0).size(); i++)
4971 {
4972 Teuchos::Array<SC> value11( 1, 0. );
4973 Teuchos::Array<SC> value12( 1, 0. );
4974 Teuchos::Array<SC> value13( 1, 0. );
4975 Teuchos::Array<SC> value21( 1, 0. );
4976 Teuchos::Array<SC> value22( 1, 0. );
4977 Teuchos::Array<SC> value23( 1, 0. );
4978 Teuchos::Array<SC> value31( 1, 0. );
4979 Teuchos::Array<SC> value32( 1, 0. );
4980 Teuchos::Array<SC> value33( 1, 0. );
4981 Teuchos::Array<GO> indices( 1, 0 );
4982
4983 for (int j = 0; j < dPhi->at(0).size(); j++)
4984 {
4985 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;
4986 for (int k = 0; k < dPhi->size(); k++)
4987 {
4988
4989 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
4990
4991 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
4992 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
4993 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
4994
4995
4996 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4997
4998 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
4999 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
5000 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
5001
5002 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
5003 epsilonValuesMat1_i.trace(res_trace_i);
5004 epsilonValuesMat1_j.trace(res_trace_j);
5005 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5006
5007 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
5008 epsilonValuesMat1_i.trace(res_trace_i);
5009 epsilonValuesMat2_j.trace(res_trace_j);
5010 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5011
5012 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
5013 epsilonValuesMat1_i.trace(res_trace_i);
5014 epsilonValuesMat3_j.trace(res_trace_j);
5015 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5016
5017 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
5018 epsilonValuesMat2_i.trace(res_trace_i);
5019 epsilonValuesMat1_j.trace(res_trace_j);
5020 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5021
5022 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5023 epsilonValuesMat2_i.trace(res_trace_i);
5024 epsilonValuesMat2_j.trace(res_trace_j);
5025 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5026
5027 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
5028 epsilonValuesMat2_i.trace(res_trace_i);
5029 epsilonValuesMat3_j.trace(res_trace_j);
5030 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5031
5032 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
5033 epsilonValuesMat3_i.trace(res_trace_i);
5034 epsilonValuesMat1_j.trace(res_trace_j);
5035 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5036
5037 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
5038 epsilonValuesMat3_i.trace(res_trace_i);
5039 epsilonValuesMat2_j.trace(res_trace_j);
5040 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5041
5042 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
5043 epsilonValuesMat3_i.trace(res_trace_i);
5044 epsilonValuesMat3_j.trace(res_trace_j);
5045 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5046
5047 }
5048 v11 = absDetB * v11;
5049 v12 = absDetB * v12;
5050 v13 = absDetB * v13;
5051 v21 = absDetB * v21;
5052 v22 = absDetB * v22;
5053 v23 = absDetB * v23;
5054 v31 = absDetB * v31;
5055 v32 = absDetB * v32;
5056 v33 = absDetB * v33;
5057
5058 value11[0] = v11;
5059 value12[0] = v12;
5060 value13[0] = v13;
5061 value21[0] = v21;
5062 value22[0] = v22;
5063 value23[0] = v23;
5064 value31[0] = v31;
5065 value32[0] = v32;
5066 value33[0] = v33;
5067
5068 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5069 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5070 indices[0] = glob_j;
5071 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5072 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5073 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
5074 glob_j++;
5075 indices[0] = glob_j;
5076 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5077 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5078 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
5079 glob_j++;
5080 indices[0] = glob_j;
5081 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
5082 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
5083 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
5084 }
5085 }
5086 }
5087 if (callFillComplete)
5088 {
5089 A->fillComplete();
5090 }
5091 }
5092}
5093
5094// Determine the change of emodule depending on concentration
5095template <class SC, class LO, class GO, class NO>
5096void FE<SC,LO,GO,NO>::determineEMod(std::string FEType, MultiVectorPtr_Type solution,MultiVectorPtr_Type &eModVec, DomainConstPtr_Type domain, ParameterListPtr_Type params){
5097
5098
5099 ElementsPtr_Type elements = domain->getElementsC();
5100
5101 int dim = domain->getDimension();
5102 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5103
5104 //MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
5105
5106 Teuchos::ArrayRCP< const SC > uArray = solution->getData(0);
5107 Teuchos::ArrayRCP< SC > eModVecA = eModVec->getDataNonConst(0);
5108
5109 double E0 = params->sublist("Parameter Solid").get("E",3.0e+6);
5110 double E1 = params->sublist("Parameter Solid").get("E1",3.0e+5);
5111 double c1 = params->sublist("Parameter Solid").get("c1",1.0);
5112 double eModMax =E1;
5113 double eModMin = E0;
5114
5115 int nodesElement = elements->getElement(0).getVectorNodeList().size();
5116 for (UN T=0; T<elements->numberElements(); T++) {
5117
5118 /*buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
5119 detB = B.computeInverse(Binv);
5120 absDetB = std::fabs(detB);*/
5121
5122 double uLoc = 0.;
5123
5124 for(int i=0; i< nodesElement;i++){
5125 LO index = elements->getElement(T).getNode(i) ;
5126 uLoc += 1./nodesElement*uArray[index];
5127 }
5128
5129 eModVecA[T] = E0-(E0-E1)*(uLoc/(uLoc+c1));
5130 if(eModVecA[T] > eModMax )
5131 eModMax = eModVecA[T];
5132 if(eModVecA[T] < eModMin)
5133 eModMin = eModVecA[T];
5134 }
5135 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MIN, eModMin, Teuchos::outArg (eModMin));
5136 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MAX, eModMax, Teuchos::outArg (eModMax));
5137
5138 if(domain->getComm()->getRank()==0)
5139 std::cout << " ################# eMOD Min: " << eModMin << " \t eModMax: " << eModMax<< " ############# " << std::endl;
5140
5141
5142}
5143
5144
5146template <class SC, class LO, class GO, class NO>
5148 std::string FEType,
5149 MatrixPtr_Type &A,
5150 MultiVectorPtr_Type eModVec,
5151 double nu,
5152 bool callFillComplete)
5153{
5154 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
5155 int FEloc = this->checkFE(dim,FEType);
5156 // Hole Elemente und Knotenliste
5157 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5158 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5159 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
5160
5161 vec3D_dbl_ptr_Type dPhi;
5162 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
5163 vec2D_dbl_ptr_Type quadPts;
5164
5165 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
5166
5167 // Hole die grad_phi, hier DPhi
5168 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
5169 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
5170
5171 SC detB;
5172 SC absDetB;
5173 SmallMatrix<SC> B(dim);
5174 SmallMatrix<SC> Binv(dim);
5175 GO glob_i, glob_j;
5176
5177 // Fuer Zwischenergebniss
5178 SC res;
5179
5180 // Fuer die Berechnung der Spur
5181 double res_trace_i, res_trace_j;
5182
5183 Teuchos::ArrayRCP< const SC > E = eModVec->getData(0);
5184 double lambda;
5185 double mu ;
5186
5187 if (dim == 2)
5188 {
5189
5190 double v11, v12, v21, v22;
5191 // Setzte Vektoren der Groesse 2 und initialisiere mit 0.0 (double)
5192 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
5193
5194 // Matrizen der Groesse (2x2) in denen die einzelnen Epsilon-Tensoren berechnet werden.
5195 // Siehe unten fuer mehr.
5196 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
5197 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
5198
5199 for (int T = 0; T < elements->numberElements(); T++)
5200 {
5202 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
5203 mu = E[T] / (2.*(1.+nu));
5204
5205 // Hole die Eckknoten des Dreiecks
5206 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5207 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5208 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5209
5210 // Berechne die Transormationsmatrix B fuer das jeweilige Element (2D)
5211 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5212 detB = B.computeInverse(Binv);
5213 absDetB = std::fabs(detB);
5214
5215 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1).
5216 // Also \hat{grad_phi}.
5217 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5218 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5219
5220 for (int i = 0; i < dPhi->at(0).size(); i++)
5221 {
5222 Teuchos::Array<SC> value11( 1, 0. );
5223 Teuchos::Array<SC> value12( 1, 0. );
5224 Teuchos::Array<SC> value21( 1, 0. );
5225 Teuchos::Array<SC> value22( 1, 0. );
5226 Teuchos::Array<GO> indices( 1, 0 );
5227
5228 for (int j = 0; j < dPhi->at(0).size(); j++)
5229 {
5230 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
5231 for (int k = 0; k < dPhi->size(); k++)
5232 {
5233 // In epsilonValuesMat1_i (2x2 Matrix) steht fuer die Ansatzfunktion i bzw. \phi_i
5234 // der epsilonTensor fuer eine skalare Ansatzfunktion fuer die Richtung 1 (vgl. Mat1).
5235 // Also in Mat1_i wird dann also phi_i = (phi_scalar_i, 0) gesetzt und davon \eps berechnet.
5236
5237 // Stelle \hat{grad_phi_i} = basisValues_i auf, also B^(-T)*grad_phi_i
5238 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
5239
5240 // \eps(v) = \eps(phi_i)
5241 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
5242 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
5243
5244 // Siehe oben, nur fuer j
5245 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
5246
5247 // \eps(u) = \eps(phi_j)
5248 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
5249 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
5250
5251 // Nun berechnen wir \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
5252 // Das Ergebniss steht in res.
5253 // Berechne zudem noch die Spur der Epsilon-Tensoren tr(\eps(u)) (j) und tr(\eps(v)) (i)
5254 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
5255 epsilonValuesMat1_i.trace(res_trace_i);
5256 epsilonValuesMat1_j.trace(res_trace_j);
5257 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5258
5259 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
5260 epsilonValuesMat1_i.trace(res_trace_i);
5261 epsilonValuesMat2_j.trace(res_trace_j);
5262 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5263
5264 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
5265 epsilonValuesMat2_i.trace(res_trace_i);
5266 epsilonValuesMat1_j.trace(res_trace_j);
5267 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5268
5269 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5270 epsilonValuesMat2_i.trace(res_trace_i);
5271 epsilonValuesMat2_j.trace(res_trace_j);
5272 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5273
5274
5275 }
5276 // Noch mit der abs(det(B)) skalieren
5277 v11 = absDetB * v11;
5278 v12 = absDetB * v12;
5279 v21 = absDetB * v21;
5280 v22 = absDetB * v22;
5281
5282 value11[0] = v11;
5283 value12[0] = v12;
5284 value21[0] = v21;
5285 value22[0] = v22;
5286
5287 // Hole die globale Zeile und Spalte in der die Eintraege hingeschrieben werden sollen
5288 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5289 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5290 indices[0] = glob_j;
5291 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5292 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5293 glob_j++;
5294 indices[0] = glob_j;
5295 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5296 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5297 }
5298 }
5299 }
5300 if (callFillComplete)
5301 {
5302 A->fillComplete();
5303 }
5304 }
5305 else if(dim == 3)
5306 {
5307
5308 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
5309
5310 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
5311 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
5312 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
5313
5314 for (int T = 0; T < elements->numberElements(); T++)
5315 {
5316 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
5317 mu = E[T] / (2.*(1.+nu));
5318
5319 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5320 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5321 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5322 p4 = pointsRep->at(elements->getElement(T).getNode(3));
5323
5324 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5325 detB = B.computeInverse(Binv);
5326 absDetB = std::fabs(detB);
5327
5328 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5329 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5330 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5331
5332 for (int i = 0; i < dPhi->at(0).size(); i++)
5333 {
5334
5335 Teuchos::Array<SC> value11( 1, 0. );
5336 Teuchos::Array<SC> value12( 1, 0. );
5337 Teuchos::Array<SC> value13( 1, 0. );
5338 Teuchos::Array<SC> value21( 1, 0. );
5339 Teuchos::Array<SC> value22( 1, 0. );
5340 Teuchos::Array<SC> value23( 1, 0. );
5341 Teuchos::Array<SC> value31( 1, 0. );
5342 Teuchos::Array<SC> value32( 1, 0. );
5343 Teuchos::Array<SC> value33( 1, 0. );
5344 Teuchos::Array<GO> indices( 1, 0 );
5345
5346 for (int j = 0; j < dPhi->at(0).size(); j++)
5347 {
5348 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;
5349 for (int k = 0; k < dPhi->size(); k++)
5350 {
5351
5352 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
5353
5354 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
5355 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
5356 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
5357
5358
5359 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
5360
5361 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
5362 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
5363 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
5364
5365 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
5366 epsilonValuesMat1_i.trace(res_trace_i);
5367 epsilonValuesMat1_j.trace(res_trace_j);
5368 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5369
5370 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
5371 epsilonValuesMat1_i.trace(res_trace_i);
5372 epsilonValuesMat2_j.trace(res_trace_j);
5373 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5374
5375 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
5376 epsilonValuesMat1_i.trace(res_trace_i);
5377 epsilonValuesMat3_j.trace(res_trace_j);
5378 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5379
5380 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
5381 epsilonValuesMat2_i.trace(res_trace_i);
5382 epsilonValuesMat1_j.trace(res_trace_j);
5383 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5384
5385 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5386 epsilonValuesMat2_i.trace(res_trace_i);
5387 epsilonValuesMat2_j.trace(res_trace_j);
5388 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5389
5390 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
5391 epsilonValuesMat2_i.trace(res_trace_i);
5392 epsilonValuesMat3_j.trace(res_trace_j);
5393 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5394
5395 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
5396 epsilonValuesMat3_i.trace(res_trace_i);
5397 epsilonValuesMat1_j.trace(res_trace_j);
5398 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5399
5400 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
5401 epsilonValuesMat3_i.trace(res_trace_i);
5402 epsilonValuesMat2_j.trace(res_trace_j);
5403 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5404
5405 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
5406 epsilonValuesMat3_i.trace(res_trace_i);
5407 epsilonValuesMat3_j.trace(res_trace_j);
5408 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5409
5410 }
5411 v11 = absDetB * v11;
5412 v12 = absDetB * v12;
5413 v13 = absDetB * v13;
5414 v21 = absDetB * v21;
5415 v22 = absDetB * v22;
5416 v23 = absDetB * v23;
5417 v31 = absDetB * v31;
5418 v32 = absDetB * v32;
5419 v33 = absDetB * v33;
5420
5421 value11[0] = v11;
5422 value12[0] = v12;
5423 value13[0] = v13;
5424 value21[0] = v21;
5425 value22[0] = v22;
5426 value23[0] = v23;
5427 value31[0] = v31;
5428 value32[0] = v32;
5429 value33[0] = v33;
5430
5431 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5432 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5433 indices[0] = glob_j;
5434 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5435 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5436 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
5437 glob_j++;
5438 indices[0] = glob_j;
5439 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5440 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5441 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
5442 glob_j++;
5443 indices[0] = glob_j;
5444 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
5445 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
5446 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
5447 }
5448 }
5449 }
5450 if (callFillComplete)
5451 {
5452 A->fillComplete();
5453 }
5454 }
5455}
5456
5458template <class SC, class LO, class GO, class NO>
5460 std::string FEType,
5461 MatrixPtr_Type &A,
5462 MultiVectorPtr_Type w,
5463 bool callFillComplete)
5464{
5465
5466 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
5467 int FEloc = this->checkFE(dim,FEType);
5468
5469 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5470 ElementsPtr_Type elements = domain->getElementsC();
5471 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5472 MapConstPtr_Type map = domain->getMapRepeated();
5473
5474 vec3D_dbl_ptr_Type dPhi;
5475 vec2D_dbl_ptr_Type phi;
5476 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5477 vec2D_dbl_ptr_Type quadPts;
5478
5479 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); // Fuer diskretes (\grad \cdot w) in den Gausspuntken
5480 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
5481
5482 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
5483 Helper::getPhi(phi, weights, dim, FEType, deg);
5484 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType);
5485
5486 // SC = double, GO = long, UN = int
5487 SC detB;
5488 SC absDetB;
5489 SmallMatrix<SC> B(dim);
5490 SmallMatrix<SC> Binv(dim);
5491 GO glob_i, glob_j;
5492
5493 // Der nichtlineare Teil als Array
5494 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
5495
5496 if (dim == 2)
5497 {
5498 double val;
5499 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
5500
5501 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
5502 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5503 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
5504
5505 for (int T = 0; T < elements->numberElements(); T++)
5506 {
5507 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5508 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5509 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5510
5511 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5512 detB = B.computeInverse(Binv);
5513 absDetB = std::fabs(detB);
5514
5515 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5516 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5517 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5518
5519 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 berechnen,
5520 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
5521 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5522 {
5523 w11[0][k] = 0.0;
5524 w22[0][k] = 0.0;
5525 for(int i = 0; i < dPhiTrans[0].size(); i++)
5526 {
5527 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5528 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5529 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
5530 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
5531
5532 // TEST
5533 // LO indexTest1 = dim * i + 0;
5534 // LO indexTest2 = dim * i + 1;
5535 // w11[0][k] += wTest[indexTest1] * dPhiTrans[k][i][0];
5536 // w22[0][k] += wTest[indexTest2] * dPhiTrans[k][i][1];
5537 }
5538 }
5539
5540 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5541 {
5542 divergenz[0][k] = w11[0][k] + w22[0][k];
5543 // if(T == 0)
5544 // {
5545 // std::cout << "k: " << k << " Divergenz: " << divergenz[0][k] << '\n';
5546 // }
5547 }
5548
5549
5550 for (int i = 0; i < dPhi->at(0).size(); i++)
5551 {
5552 Teuchos::Array<SC> value( 1, 0. );
5553 Teuchos::Array<GO> indices( 1, 0 );
5554
5555 for (int j = 0; j < dPhi->at(0).size(); j++)
5556 {
5557 val = 0.0;
5558 for (int k = 0; k < dPhi->size(); k++)
5559 {
5560 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
5561 }
5562 val = absDetB * val;
5563 value[0] = val;
5564
5565 // if(T == 0)
5566 // {
5567 // std::cout << "i: " << i << " j: " << j << " val: " << val << '\n';
5568 // }
5569
5570 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5571 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5572 indices[0] = glob_j;
5573
5574 A->insertGlobalValues(glob_i, indices(), value());
5575 glob_j++;
5576 indices[0] = glob_j;
5577 A->insertGlobalValues(glob_i+1, indices(), value());
5578 }
5579 }
5580 }
5581 if (callFillComplete)
5582 {
5583 A->fillComplete();
5584 }
5585 }
5586 else if(dim == 3)
5587 {
5588 double val;
5589
5590 // long long glob_i, glob_j;
5591 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
5592
5593 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
5594 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5595 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
5596 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
5597
5598 for (int T = 0; T < elements->numberElements(); T++)
5599 {
5600 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5601 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5602 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5603 p4 = pointsRep->at(elements->getElement(T).getNode(3));
5604
5605 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5606 detB = B.computeInverse(Binv);
5607 absDetB = std::fabs(detB);
5608
5609 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5610 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5611 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5612
5613 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 + w33 berechnen,
5614 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
5615 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5616 {
5617 w11[0][k] = 0.0;
5618 w22[0][k] = 0.0;
5619 w33[0][k] = 0.0;
5620 for(int i = 0; i < dPhiTrans[0].size(); i++)
5621 {
5622 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5623 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5624 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
5625 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
5626 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
5627 w33[0][k] += wArray[index3] * dPhiTrans[k][i][2];
5628 }
5629 }
5630
5631 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5632 {
5633 divergenz[0][k] = w11[0][k] + w22[0][k] + w33[0][k];
5634 }
5635
5636 for (int i = 0; i < dPhi->at(0).size(); i++)
5637 {
5638 Teuchos::Array<SC> value( 1, 0. );
5639 Teuchos::Array<GO> indices( 1, 0 );
5640
5641 for (int j = 0; j < dPhi->at(0).size(); j++)
5642 {
5643 val = 0.0;
5644 for (int k = 0; k < dPhi->size(); k++)
5645 {
5646 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
5647 }
5648 val = absDetB * val;
5649 value[0] = val;
5650
5651 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5652 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5653 indices[0] = glob_j;
5654 A->insertGlobalValues(glob_i, indices(), value());
5655 glob_j++;
5656 indices[0] = glob_j;
5657 A->insertGlobalValues(glob_i+1, indices(), value());
5658 glob_j++;
5659 indices[0] = glob_j;
5660 A->insertGlobalValues(glob_i+2, indices(), value());
5661
5662 }
5663 }
5664 }
5665 if (callFillComplete)
5666 {
5667 A->fillComplete();
5668 }
5669 }
5670}
5671
5672template <class SC, class LO, class GO, class NO>
5673void FE<SC,LO,GO,NO>::assemblyDummyCoupling(int dim,
5674 std::string FEType,
5675 MatrixPtr_Type &C,
5676 int FEloc, // 0 = Fluid, 2 = Struktur
5677 bool callFillComplete)
5678{
5679 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5680
5681 MapConstPtr_Type mapInterfaceVecField = domain->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
5682 MapConstPtr_Type mapGlobalInterfaceVecField = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
5683
5684 MapConstPtr_Type mapFieldPartial = domain->getGlobalInterfaceMapVecFieldPartial();
5685
5686 Teuchos::Array<SC> value( 1, 0. );
5687 value[0] = 1.0; // da Einheitsmatrix
5688 Teuchos::Array<GO> indices( 1, 0 );
5689
5690 GO dofGlobal, dofLocal;
5691
5692 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
5693 {
5694 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5695 if ( mapFieldPartial->getLocalElement( dofGlobal ) == Teuchos::OrdinalTraits<LO>::invalid() ) {
5696 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
5697 dofGlobal = mapInterfaceVecField->getGlobalElement( k );
5698 indices[0] = dofGlobal;
5699 C->insertGlobalValues(dofGlobal, indices(), value());
5700 }
5701 }
5702
5703 if (callFillComplete)
5704 C->fillComplete(mapInterfaceVecField, mapInterfaceVecField);
5705
5706}
5707
5708template <class SC, class LO, class GO, class NO>
5709void FE<SC,LO,GO,NO>::assemblyFSICoupling(int dim,
5710 std::string FEType,
5711 MatrixPtr_Type &C,
5712 MatrixPtr_Type &C_T,
5713 int FEloc1, // 0 = Fluid, 2 = Struktur
5714 int FEloc2, // 0 = Fluid, 2 = Struktur
5715 MapConstPtr_Type map1, // DomainMap: InterfaceMapVecFieldUnique = Spalten von C_T
5716 MapConstPtr_Type map2, // RangeMap: this->getDomain(0)->getMapVecFieldUnique() = Zeilen von C_T
5717 bool callFillComplete)
5718{
5719 // int FEloc = this->checkFE(dim,FEType);
5720
5721 DomainConstPtr_Type domain1 = domainVec_.at(FEloc1);
5722
5723 MapConstPtr_Type mapInterfaceVecField = domain1->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
5724
5725 MapConstPtr_Type mapGlobalInterfaceVecField;
5726 MapConstPtr_Type mapFieldPartial;
5727 if (FEloc1!=FEloc2){
5728 mapFieldPartial = domain1->getOtherGlobalInterfaceMapVecFieldPartial();
5729 mapGlobalInterfaceVecField = domain1->getOtherGlobalInterfaceMapVecFieldUnique();
5730 }
5731 else{
5732 mapFieldPartial = domain1->getGlobalInterfaceMapVecFieldPartial();
5733 mapGlobalInterfaceVecField = domain1->getGlobalInterfaceMapVecFieldUnique();
5734 }
5735
5736 Teuchos::Array<SC> value( 1, 0. );
5737 value[0] = 1.0; // da Einheitsmatrix
5738 Teuchos::Array<GO> indices( 1, 0 );
5739
5740 GO dofGlobal, dofLocal;
5741 if (mapFieldPartial.is_null()) {
5742 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
5743 {
5744 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
5745 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5746 dofLocal = mapInterfaceVecField->getGlobalElement(k);
5747
5748 indices[0] = dofLocal;
5749 C_T->insertGlobalValues(dofGlobal, indices(), value());
5750 indices[0] = dofGlobal;
5751 C->insertGlobalValues(dofLocal, indices(), value());
5752
5753 }
5754 }
5755 else{
5756 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++) {
5757 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5758 if ( mapFieldPartial->getLocalElement( dofGlobal ) != Teuchos::OrdinalTraits<LO>::invalid() ) {
5759
5760 dofLocal = mapInterfaceVecField->getGlobalElement(k);
5761
5762 indices[0] = dofLocal;
5763 C_T->insertGlobalValues(dofGlobal, indices(), value());
5764 indices[0] = dofGlobal;
5765 C->insertGlobalValues(dofLocal, indices(), value());
5766 }
5767 }
5768 }
5769
5770 if (callFillComplete)
5771 {
5772 // Erstes Argument: Domain (=Spalten von C_T)
5773 // Zweites Arguement: Range (=Zeilen von C_T)
5774 C_T->fillComplete(map1, map2);
5775 C->fillComplete(map2, map1);
5776 }
5777}
5778
5779
5780template <class SC, class LO, class GO, class NO>
5781void FE<SC,LO,GO,NO>::assemblyGeometryCoupling(int dim,
5782 std::string FEType,
5783 MatrixPtr_Type &C,
5784 int FEloc, // 0 = Fluid, 2 = Struktur, 4 = 0 = Geometrie
5785 MapConstPtr_Type map1, // Fluid-Interface-Map
5786 MapConstPtr_Type map2, // DomainMap: this->getDomain(2)->getMapVecFieldUnique() = Spalten von C
5787 MapConstPtr_Type map3, // RangeMap: this->getDomain(4)->getMapVecFieldUnique() = Zeilen von C
5788 bool callFillComplete)
5789{
5790
5791 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5792
5793 MapConstPtr_Type mapInt = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
5794 MapConstPtr_Type mapOtherInt = domain->getOtherGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung von other. For FELoc=0 or =4, otherInterface has solid dofs
5795 MapConstPtr_Type mapPartInt = domain->getGlobalInterfaceMapVecFieldPartial();
5796 MapConstPtr_Type mapOtherPartInt = domain->getOtherGlobalInterfaceMapVecFieldPartial();
5797 Teuchos::Array<SC> value( 1, 0. );
5798 value[0] = 1.0; // da Einheitsmatrix
5799 Teuchos::Array<GO> indices( 1, 0 );
5800
5801 GO dofRow;
5802 if (mapPartInt.is_null()) {
5803 for(int k = 0; k < mapInt->getNodeNumElements(); k++){
5804 dofRow = mapInt->getGlobalElement(k);
5805 indices[0] = mapOtherInt->getGlobalElement(k);
5806 C->insertGlobalValues(dofRow, indices(), value());
5807 }
5808 }
5809 else{
5810 for(int k = 0; k < mapPartInt->getNodeNumElements(); k++){
5811 dofRow = mapPartInt->getGlobalElement(k);
5812 indices[0] = mapOtherPartInt->getGlobalElement(k);
5813 C->insertGlobalValues(dofRow, indices(), value());
5814 }
5815 }
5816 if (callFillComplete)
5817 {
5818 // (Domain, Range)
5819 C->fillComplete(map2, map3);
5820 }
5821}
5822
5823
5824template <class SC, class LO, class GO, class NO>
5825void FE<SC,LO,GO,NO>::assemblyShapeDerivativeVelocity(int dim,
5826 std::string FEType1, // P2
5827 std::string FEType2, // P1
5828 MatrixPtr_Type &D,
5829 int FEloc, // 0 = Fluid (Velocity)
5830 MultiVectorPtr_Type u, // Geschwindigkeit
5831 MultiVectorPtr_Type w, // Beschleunigung Gitter
5832 MultiVectorPtr_Type p, // Druck
5833 double dt, // Zeitschrittweite
5834 double rho, // Dichte vom Fluid
5835 double nu, // Viskositaet vom Fluid
5836 bool callFillComplete)
5837{
5838 // int FEloc = this->checkFE(dim,FEType1);
5839
5840 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5841 ElementsPtr_Type elements = domain->getElementsC();
5842 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5843 MapConstPtr_Type map = domain->getMapRepeated();
5844
5845 vec3D_dbl_ptr_Type dPhiU;
5846 vec2D_dbl_ptr_Type phiU;
5847 vec2D_dbl_ptr_Type phiP;
5848 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5849 vec2D_dbl_ptr_Type quadPts;
5850
5851 // Hoechste Quadraturordnung angeben (= Zusaetzlicher Term wg. non-conservativ); bei P2/P1 hier Ordnung 6
5852 UN extraDeg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv1);
5853 UN deg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv0) + extraDeg;
5854
5855 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
5856 Helper::getPhi(phiU, weights, dim, FEType1, deg);
5857 Helper::getPhi(phiP, weights, dim, FEType2, deg);
5858 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType1);
5859
5860 // SC = double, GO = long, UN = int
5861 SC detB;
5862 SC absDetB;
5863 SmallMatrix<SC> B(dim);
5864 SmallMatrix<SC> Binv(dim);
5865 GO glob_i, glob_j;
5866
5867 // Der nichtlineare Teil als Array
5868 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
5869 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
5870 Teuchos::ArrayRCP< const SC > pArray = p->getData(0);
5871
5872 if (dim == 2)
5873 {
5874 double val11, val12, val21, val22;
5875 double valDK1_11, valDK1_12, valDK1_21, valDK1_22;
5876 double valDK2_11, valDK2_12, valDK2_21, valDK2_22;
5877 double valDN_11, valDN_12, valDN_21, valDN_22;
5878 double valDW_11, valDW_12, valDW_21, valDW_22;
5879 double valDP_11, valDP_12, valDP_21, valDP_22;
5880 double valDM_11, valDM_12, valDM_21, valDM_22;
5881 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
5882
5883 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
5884 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
5885 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
5886 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
5887 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
5888 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
5889 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
5890 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
5891 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
5892 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
5893 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
5894 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
5895 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
5896 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
5897 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
5898 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5899 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
5900 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
5901 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
5902 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
5903
5904 for (int T = 0; T < elements->numberElements(); T++)
5905 {
5906 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5907 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5908 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5909
5910 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
5911 detB = B.computeInverse(Binv);
5912 absDetB = std::fabs(detB);
5913
5914 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5915 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
5916 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
5917
5918 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
5919 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
5920 {
5921 u1Loc[0][k] = 0.0;
5922 u2Loc[0][k] = 0.0;
5923 w1Loc[0][k] = 0.0;
5924 w2Loc[0][k] = 0.0;
5925 for(int i = 0; i < phiU->at(0).size(); i++)
5926 {
5927 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5928 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5929 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
5930 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
5931 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
5932 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
5933
5934 }
5935 }
5936
5937 // Diskreten Vektor p berechnen
5938 // Beachte: phiP->size() = phiU->size()
5939 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
5940 {
5941 pLoc[0][k] = 0.0;
5942 for(int i = 0; i < phiP->at(0).size(); i++)
5943 {
5944 // Die ersten Eintraege in der Elementliste sind P1
5945 // Alternativ elements2 holen
5946 LO index = elements->getElement(T).getNode(i) + 0;
5947 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
5948
5949 }
5950 }
5951
5952 // Diskrete Grad-Vektoren berechnen,
5953 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
5954 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5955 {
5956 u11[0][k] = 0.0;
5957 u12[0][k] = 0.0;
5958 u21[0][k] = 0.0;
5959 u22[0][k] = 0.0;
5960 w11[0][k] = 0.0;
5961 w12[0][k] = 0.0;
5962 w21[0][k] = 0.0;
5963 w22[0][k] = 0.0;
5964 for(int i = 0; i < dPhiTransU[0].size(); i++)
5965 {
5966 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5967 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5968 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
5969 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
5970 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
5971 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
5972 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
5973 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
5974 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
5975 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
5976
5977 }
5978 }
5979
5980 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
5981 // Beachte: phiP->size() = phiU->size()
5982 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5983 {
5984 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
5985 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
5986 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
5987 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
5988 }
5989
5990
5991 for (int i = 0; i < dPhiU->at(0).size(); i++)
5992 {
5993 Teuchos::Array<SC> value11( 1, 0. ); // x-x
5994 Teuchos::Array<SC> value12( 1, 0. ); // x-y
5995 Teuchos::Array<SC> value21( 1, 0. ); // y-x
5996 Teuchos::Array<SC> value22( 1, 0. ); // y-y
5997 Teuchos::Array<GO> indices( 1, 0 );
5998
5999 for (int j = 0; j < dPhiU->at(0).size(); j++)
6000 {
6001 // DK1
6002 valDK1_11 = 0.0;
6003 valDK1_12 = 0.0;
6004 valDK1_21 = 0.0;
6005 valDK1_22 = 0.0;
6006
6007 // DK2
6008 valDK2_11 = 0.0;
6009 valDK2_12 = 0.0;
6010 valDK2_21 = 0.0;
6011 valDK2_22 = 0.0;
6012
6013 // DN
6014 valDN_11 = 0.0;
6015 valDN_12 = 0.0;
6016 valDN_21 = 0.0;
6017 valDN_22 = 0.0;
6018
6019 // DW
6020 valDW_11 = 0.0;
6021 valDW_12 = 0.0;
6022 valDW_21 = 0.0;
6023 valDW_22 = 0.0;
6024
6025 // DP
6026 valDP_11 = 0.0;
6027 valDP_12 = 0.0;
6028 valDP_21 = 0.0;
6029 valDP_22 = 0.0;
6030
6031 // DM
6032 valDM_11 = 0.0;
6033 valDM_12 = 0.0;
6034 valDM_21 = 0.0;
6035 valDM_22 = 0.0;
6036
6037 for (int k = 0; k < dPhiU->size(); k++)
6038 {
6039 // DK1
6040 valDK1_11 = valDK1_11 + weights->at(k) *
6041 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6042 u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6043 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6044 valDK1_12 = valDK1_12 + weights->at(k) *
6045 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6046 u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6047 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6048 valDK1_21 = valDK1_21 + weights->at(k) *
6049 ( u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6050 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6051 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
6052 valDK1_22 = valDK1_22 + weights->at(k) *
6053 ( u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6054 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6055 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
6056
6057 // DK2
6058 valDK2_11 = valDK2_11 + weights->at(k) *
6059 ( -sigma12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6060 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6061 valDK2_12 = valDK2_12 + weights->at(k) *
6062 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6063 -sigma11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6064 valDK2_21 = valDK2_21 + weights->at(k) *
6065 ( -sigma22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6066 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6067 valDK2_22 = valDK2_22 + weights->at(k) *
6068 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6069 -sigma21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6070
6071 // DN
6072 valDN_11 = valDN_11 + weights->at(k) *
6073 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) +
6074 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
6075 valDN_12 = valDN_12 + weights->at(k) *
6076 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) -
6077 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
6078 valDN_21 = valDN_21 + weights->at(k) *
6079 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) +
6080 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
6081 valDN_22 = valDN_22 + weights->at(k) *
6082 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) -
6083 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
6084
6085 // DW
6086 valDW_11 = valDW_11 + weights->at(k) *
6087 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6088 valDW_12 = valDW_12 + weights->at(k) *
6089 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6090 valDW_21 = valDW_21 + weights->at(k) *
6091 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6092 valDW_22 = valDW_22 + weights->at(k) *
6093 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6094
6095 // DP
6096 valDP_11 = valDP_11 + weights->at(k) *
6097 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
6098 valDP_12 = valDP_12 + weights->at(k) *
6099 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
6100 valDP_21 = valDP_21 + weights->at(k) *
6101 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
6102 valDP_22 = valDP_22 + weights->at(k) *
6103 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
6104
6105 // DM
6106 valDM_11 = valDM_11 + weights->at(k) *
6107 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
6108 valDM_12 = valDM_12 + weights->at(k) *
6109 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
6110 valDM_21 = valDM_21 + weights->at(k) *
6111 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
6112 valDM_22 = valDM_22 + weights->at(k) *
6113 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
6114 }
6115
6116 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;
6117 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;
6118 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;
6119 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;
6120
6121 val11 = absDetB * val11;
6122 val12 = absDetB * val12;
6123 val21 = absDetB * val21;
6124 val22 = absDetB * val22;
6125
6126 value11[0] = val11; // x-x
6127 value12[0] = val12; // x-y
6128 value21[0] = val21; // y-x
6129 value22[0] = val22; // y-y
6130
6131 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6132 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6133 indices[0] = glob_j;
6134
6135 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
6136 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6137 glob_j++;
6138 indices[0] = glob_j;
6139 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
6140 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6141 }
6142 }
6143 }
6144 if (callFillComplete)
6145 {
6146 D->fillComplete();
6147 }
6148 }
6149 else if(dim == 3)
6150 {
6151 double val11, val12, val13, val21, val22, val23, val31, val32, val33;
6152 double valDK1_11, valDK1_12, valDK1_13, valDK1_21, valDK1_22, valDK1_23, valDK1_31, valDK1_32, valDK1_33;
6153 double valDK2_11, valDK2_12, valDK2_13, valDK2_21, valDK2_22, valDK2_23, valDK2_31, valDK2_32, valDK2_33;
6154 double valDN_11, valDN_12, valDN_13, valDN_21, valDN_22, valDN_23, valDN_31, valDN_32, valDN_33;
6155 double valDW_11, valDW_12, valDW_13, valDW_21, valDW_22, valDW_23, valDW_31, valDW_32, valDW_33;
6156 double valDP_11, valDP_12, valDP_13, valDP_21, valDP_22, valDP_23, valDP_31, valDP_32, valDP_33;
6157 double valDM_11, valDM_12, valDM_13, valDM_21, valDM_22, valDM_23, valDM_31, valDM_32, valDM_33;
6158 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6159
6160 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6161 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6162 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6163 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
6164 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
6165 vec2D_dbl_Type u3Loc(1, vec_dbl_Type(weights->size(), -1.));
6166 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
6167 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
6168 vec2D_dbl_Type w3Loc(1, vec_dbl_Type(weights->size(), -1.));
6169 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
6170 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6171 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6172 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
6173 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6174 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6175 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
6176 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
6177 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
6178 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
6179 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
6180 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
6181 vec2D_dbl_Type w13(1, vec_dbl_Type(weights->size(), -1.));
6182 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
6183 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
6184 vec2D_dbl_Type w23(1, vec_dbl_Type(weights->size(), -1.));
6185 vec2D_dbl_Type w31(1, vec_dbl_Type(weights->size(), -1.));
6186 vec2D_dbl_Type w32(1, vec_dbl_Type(weights->size(), -1.));
6187 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
6188 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
6189 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
6190 vec2D_dbl_Type sigma13(1, vec_dbl_Type(weights->size(), -1.));
6191 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
6192 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
6193 vec2D_dbl_Type sigma23(1, vec_dbl_Type(weights->size(), -1.));
6194 vec2D_dbl_Type sigma31(1, vec_dbl_Type(weights->size(), -1.));
6195 vec2D_dbl_Type sigma32(1, vec_dbl_Type(weights->size(), -1.));
6196 vec2D_dbl_Type sigma33(1, vec_dbl_Type(weights->size(), -1.));
6197
6198 for (int T = 0; T < elements->numberElements(); T++)
6199 {
6200 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6201 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6202 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6203 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6204
6205 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6206 detB = B.computeInverse(Binv);
6207 absDetB = std::fabs(detB);
6208
6209 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6210 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6211 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6212
6213 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
6214 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
6215 {
6216 u1Loc[0][k] = 0.0;
6217 u2Loc[0][k] = 0.0;
6218 u3Loc[0][k] = 0.0;
6219 w1Loc[0][k] = 0.0;
6220 w2Loc[0][k] = 0.0;
6221 w3Loc[0][k] = 0.0;
6222 for(int i = 0; i < phiU->at(0).size(); i++)
6223 {
6224 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
6225 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
6226 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
6227 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
6228 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
6229 u3Loc[0][k] += uArray[index3] * phiU->at(k).at(i);
6230 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
6231 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
6232 w3Loc[0][k] += wArray[index3] * phiU->at(k).at(i);
6233 }
6234 }
6235
6236 // Diskreten Vektor p berechnen
6237 // Beachte: phiP->size() = phiU->size()
6238 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
6239 {
6240 pLoc[0][k] = 0.0;
6241 for(int i = 0; i < phiP->at(0).size(); i++)
6242 {
6243 // Die ersten Eintraege in der Elementliste sind P1
6244 LO index = elements->getElement(T).getNode(i) + 0;
6245 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
6246 }
6247 }
6248
6249 // Diskrete Grad-Vektoren berechnen,
6250 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6251 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6252 {
6253 u11[0][k] = 0.0;
6254 u12[0][k] = 0.0;
6255 u13[0][k] = 0.0;
6256 u21[0][k] = 0.0;
6257 u22[0][k] = 0.0;
6258 u23[0][k] = 0.0;
6259 u31[0][k] = 0.0;
6260 u32[0][k] = 0.0;
6261 u33[0][k] = 0.0;
6262 w11[0][k] = 0.0;
6263 w12[0][k] = 0.0;
6264 w13[0][k] = 0.0;
6265 w21[0][k] = 0.0;
6266 w22[0][k] = 0.0;
6267 w23[0][k] = 0.0;
6268 w31[0][k] = 0.0;
6269 w32[0][k] = 0.0;
6270 w33[0][k] = 0.0;
6271 for(int i = 0; i < dPhiTransU[0].size(); i++)
6272 {
6273 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
6274 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
6275 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
6276 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6277 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6278 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
6279 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6280 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6281 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
6282 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
6283 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
6284 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
6285 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
6286 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
6287 w13[0][k] += wArray[index1] * dPhiTransU[k][i][2];
6288 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
6289 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
6290 w23[0][k] += wArray[index2] * dPhiTransU[k][i][2];
6291 w31[0][k] += wArray[index3] * dPhiTransU[k][i][0];
6292 w32[0][k] += wArray[index3] * dPhiTransU[k][i][1];
6293 w33[0][k] += wArray[index3] * dPhiTransU[k][i][2];
6294 }
6295 }
6296
6297 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
6298 // Beachte: phiP->size() = phiU->size()
6299 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6300 {
6301 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
6302 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
6303 sigma13[0][k] = rho * nu * (u13[0][k] + u31[0][k]);
6304 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
6305 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
6306 sigma23[0][k] = rho * nu * (u23[0][k] + u32[0][k]);
6307 sigma31[0][k] = rho * nu * (u31[0][k] + u13[0][k]);
6308 sigma32[0][k] = rho * nu * (u32[0][k] + u23[0][k]);
6309 sigma33[0][k] = rho * nu * (u33[0][k] + u33[0][k]) - pLoc[0][k];
6310 }
6311
6312
6313 for (int i = 0; i < dPhiU->at(0).size(); i++)
6314 {
6315 Teuchos::Array<SC> value11( 1, 0. ); // x-x
6316 Teuchos::Array<SC> value12( 1, 0. ); // x-y
6317 Teuchos::Array<SC> value13( 1, 0. ); // x-z
6318 Teuchos::Array<SC> value21( 1, 0. ); // y-x
6319 Teuchos::Array<SC> value22( 1, 0. ); // y-y
6320 Teuchos::Array<SC> value23( 1, 0. ); // y-z
6321 Teuchos::Array<SC> value31( 1, 0. ); // z-x
6322 Teuchos::Array<SC> value32( 1, 0. ); // z-y
6323 Teuchos::Array<SC> value33( 1, 0. ); // z-z
6324 Teuchos::Array<GO> indices( 1, 0 );
6325
6326 for (int j = 0; j < dPhiU->at(0).size(); j++)
6327 {
6328 // DK1
6329 valDK1_11 = 0.0;
6330 valDK1_12 = 0.0;
6331 valDK1_13 = 0.0;
6332 valDK1_21 = 0.0;
6333 valDK1_22 = 0.0;
6334 valDK1_23 = 0.0;
6335 valDK1_31 = 0.0;
6336 valDK1_32 = 0.0;
6337 valDK1_33 = 0.0;
6338
6339 // DK2
6340 valDK2_11 = 0.0;
6341 valDK2_12 = 0.0;
6342 valDK2_13 = 0.0;
6343 valDK2_21 = 0.0;
6344 valDK2_22 = 0.0;
6345 valDK2_23 = 0.0;
6346 valDK2_31 = 0.0;
6347 valDK2_32 = 0.0;
6348 valDK2_33 = 0.0;
6349
6350 // DN
6351 valDN_11 = 0.0;
6352 valDN_12 = 0.0;
6353 valDN_13 = 0.0;
6354 valDN_21 = 0.0;
6355 valDN_22 = 0.0;
6356 valDN_23 = 0.0;
6357 valDN_31 = 0.0;
6358 valDN_32 = 0.0;
6359 valDN_33 = 0.0;
6360
6361 // DW
6362 valDW_11 = 0.0;
6363 valDW_12 = 0.0;
6364 valDW_13 = 0.0;
6365 valDW_21 = 0.0;
6366 valDW_22 = 0.0;
6367 valDW_23 = 0.0;
6368 valDW_31 = 0.0;
6369 valDW_32 = 0.0;
6370 valDW_33 = 0.0;
6371
6372 // DP
6373 valDP_11 = 0.0;
6374 valDP_12 = 0.0;
6375 valDP_13 = 0.0;
6376 valDP_21 = 0.0;
6377 valDP_22 = 0.0;
6378 valDP_23 = 0.0;
6379 valDP_31 = 0.0;
6380 valDP_32 = 0.0;
6381 valDP_33 = 0.0;
6382
6383 // DM
6384 valDM_11 = 0.0;
6385 valDM_12 = 0.0;
6386 valDM_13 = 0.0;
6387 valDM_21 = 0.0;
6388 valDM_22 = 0.0;
6389 valDM_23 = 0.0;
6390 valDM_31 = 0.0;
6391 valDM_32 = 0.0;
6392 valDM_33 = 0.0;
6393
6394 for (int k = 0; k < dPhiU->size(); k++)
6395 {
6396 // DK1
6397 valDK1_11 = valDK1_11 + weights->at(k) *
6398 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6399 ( u11[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6400 ( u11[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6401 valDK1_12 = valDK1_12 + weights->at(k) *
6402 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6403 ( u12[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6404 ( u12[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6405 valDK1_13 = valDK1_13 + weights->at(k) *
6406 ( 2 * u13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6407 ( u13[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6408 ( u13[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6409 valDK1_21 = valDK1_21 + weights->at(k) *
6410 ( ( u21[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6411 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6412 ( u21[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6413 valDK1_22 = valDK1_22 + weights->at(k) *
6414 ( ( u22[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6415 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6416 ( u22[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6417 valDK1_23 = valDK1_23 + weights->at(k) *
6418 ( ( u23[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6419 2 * u23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6420 ( u23[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6421 valDK1_31 = valDK1_31 + weights->at(k) *
6422 ( ( u31[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6423 ( u31[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6424 2 * u31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6425 valDK1_32 = valDK1_32 + weights->at(k) *
6426 ( ( u32[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6427 ( u32[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6428 2 * u32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6429 valDK1_33 = valDK1_33 + weights->at(k) *
6430 ( ( u33[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6431 ( u33[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6432 2 * u33[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6433
6434 // DK2
6435 valDK2_11 = valDK2_11 + weights->at(k) *
6436 ( ( -sigma12[0][k] * dPhiTransU[k][j][1] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6437 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6438 sigma13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6439 valDK2_12 = valDK2_12 + weights->at(k) *
6440 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6441 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6442 sigma13[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6443 valDK2_13 = valDK2_13 + weights->at(k) *
6444 ( sigma11[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6445 sigma12[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6446 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6447 valDK2_21 = valDK2_21 + weights->at(k) *
6448 ( ( -sigma22[0][k] * dPhiTransU[k][j][1] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6449 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6450 sigma23[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6451 valDK2_22 = valDK2_22 + weights->at(k) *
6452 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6453 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6454 sigma23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6455 valDK2_23 = valDK2_23 + weights->at(k) *
6456 ( sigma21[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6457 sigma22[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6458 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma22[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6459 valDK2_31 = valDK2_31 + weights->at(k) *
6460 ( ( -sigma32[0][k] * dPhiTransU[k][j][1] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6461 sigma32[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6462 sigma33[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6463 valDK2_32 = valDK2_32 + weights->at(k) *
6464 ( sigma31[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6465 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6466 sigma33[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6467 valDK2_33 = valDK2_33 + weights->at(k) *
6468 ( sigma31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6469 sigma32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6470 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6471
6472 // DN
6473 double ZN_11; // Die Z_i fuer das DN wie in der Masterarbeit definiert
6474 double ZN_12;
6475 double ZN_13;
6476 double ZN_21;
6477 double ZN_22;
6478 double ZN_23;
6479 double ZN_31;
6480 double ZN_32;
6481 double ZN_33;
6482 ZN_11 = - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
6483 ZN_12 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][0];
6484 ZN_13 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][0];
6485 ZN_21 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][1];
6486 ZN_22 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
6487 ZN_23 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][1];
6488 ZN_31 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][2];
6489 ZN_32 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][2];
6490 ZN_33 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1];
6491
6492 valDN_11 = valDN_11 + weights->at(k) *
6493 ( ZN_11 * u11[0][k] * phiU->at(k).at(i) +
6494 ZN_12 * u12[0][k] * phiU->at(k).at(i) +
6495 ZN_13 * u13[0][k] * phiU->at(k).at(i) );
6496 valDN_12 = valDN_12 + weights->at(k) *
6497 ( ZN_21 * u11[0][k] * phiU->at(k).at(i) +
6498 ZN_22 * u12[0][k] * phiU->at(k).at(i) +
6499 ZN_23 * u13[0][k] * phiU->at(k).at(i) );
6500 valDN_13 = valDN_13 + weights->at(k) *
6501 ( ZN_31 * u11[0][k] * phiU->at(k).at(i) +
6502 ZN_32 * u12[0][k] * phiU->at(k).at(i) +
6503 ZN_33 * u13[0][k] * phiU->at(k).at(i) );
6504 valDN_21 = valDN_21 + weights->at(k) *
6505 ( ZN_11 * u21[0][k] * phiU->at(k).at(i) +
6506 ZN_12 * u22[0][k] * phiU->at(k).at(i) +
6507 ZN_13 * u23[0][k] * phiU->at(k).at(i) );
6508 valDN_22 = valDN_22 + weights->at(k) *
6509 ( ZN_21 * u21[0][k] * phiU->at(k).at(i) +
6510 ZN_22 * u22[0][k] * phiU->at(k).at(i) +
6511 ZN_23 * u23[0][k] * phiU->at(k).at(i) );
6512 valDN_23 = valDN_23 + weights->at(k) *
6513 ( ZN_31 * u21[0][k] * phiU->at(k).at(i) +
6514 ZN_32 * u22[0][k] * phiU->at(k).at(i) +
6515 ZN_33 * u23[0][k] * phiU->at(k).at(i) );
6516 valDN_31 = valDN_31 + weights->at(k) *
6517 ( ZN_11 * u31[0][k] * phiU->at(k).at(i) +
6518 ZN_12 * u32[0][k] * phiU->at(k).at(i) +
6519 ZN_13 * u33[0][k] * phiU->at(k).at(i) );
6520 valDN_32 = valDN_32 + weights->at(k) *
6521 ( ZN_21 * u31[0][k] * phiU->at(k).at(i) +
6522 ZN_22 * u32[0][k] * phiU->at(k).at(i) +
6523 ZN_23 * u33[0][k] * phiU->at(k).at(i) );
6524 valDN_33 = valDN_33 + weights->at(k) *
6525 ( ZN_31 * u31[0][k] * phiU->at(k).at(i) +
6526 ZN_32 * u32[0][k] * phiU->at(k).at(i) +
6527 ZN_33 * u33[0][k] * phiU->at(k).at(i) );
6528
6529 // DW
6530 valDW_11 = valDW_11 + weights->at(k) *
6531 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6532 valDW_12 = valDW_12 + weights->at(k) *
6533 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6534 valDW_13 = valDW_13 + weights->at(k) *
6535 ( u13[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6536 valDW_21 = valDW_21 + weights->at(k) *
6537 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6538 valDW_22 = valDW_22 + weights->at(k) *
6539 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6540 valDW_23 = valDW_23 + weights->at(k) *
6541 ( u23[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6542 valDW_31 = valDW_31 + weights->at(k) *
6543 ( u31[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6544 valDW_32 = valDW_32 + weights->at(k) *
6545 ( u32[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6546 valDW_33 = valDW_33 + weights->at(k) *
6547 ( u33[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6548
6549 // DP
6550 double ZP_1; // Die Z_i fuer das DP wie in der Masterarbeit definiert
6551 double ZP_2;
6552 double ZP_3;
6553 ZP_1 = -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] -
6554 w31[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][0];
6555 ZP_2 = w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] -
6556 w32[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][1];
6557 ZP_3 = w11[0][k] * dPhiTransU[k][j][2] - w13[0][k] * dPhiTransU[k][j][0] +
6558 w22[0][k] * dPhiTransU[k][j][2] - w23[0][k] * dPhiTransU[k][j][1];
6559
6560 valDP_11 = valDP_11 + weights->at(k) *
6561 ( ZP_1 * u1Loc[0][k] * phiU->at(k).at(i) );
6562 valDP_12 = valDP_12 + weights->at(k) *
6563 ( ZP_2 * u1Loc[0][k] * phiU->at(k).at(i) );
6564 valDP_13 = valDP_13 + weights->at(k) *
6565 ( ZP_3 * u1Loc[0][k] * phiU->at(k).at(i) );
6566 valDP_21 = valDP_21 + weights->at(k) *
6567 ( ZP_1 * u2Loc[0][k] * phiU->at(k).at(i) );
6568 valDP_22 = valDP_22 + weights->at(k) *
6569 ( ZP_2 * u2Loc[0][k] * phiU->at(k).at(i) );
6570 valDP_23 = valDP_23 + weights->at(k) *
6571 ( ZP_3 * u2Loc[0][k] * phiU->at(k).at(i) );
6572 valDP_31 = valDP_31 + weights->at(k) *
6573 ( ZP_1 * u3Loc[0][k] * phiU->at(k).at(i) );
6574 valDP_32 = valDP_32 + weights->at(k) *
6575 ( ZP_2 * u3Loc[0][k] * phiU->at(k).at(i) );
6576 valDP_33 = valDP_33 + weights->at(k) *
6577 ( ZP_3 * u3Loc[0][k] * phiU->at(k).at(i) );
6578
6579 // DM
6580 valDM_11 = valDM_11 + weights->at(k) *
6581 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
6582 valDM_12 = valDM_12 + weights->at(k) *
6583 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
6584 valDM_13 = valDM_13 + weights->at(k) *
6585 ( dPhiTransU[k][j][2] * u1Loc[0][k] * phiU->at(k).at(i) );
6586 valDM_21 = valDM_21 + weights->at(k) *
6587 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
6588 valDM_22 = valDM_22 + weights->at(k) *
6589 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
6590 valDM_23 = valDM_23 + weights->at(k) *
6591 ( dPhiTransU[k][j][2] * u2Loc[0][k] * phiU->at(k).at(i) );
6592 valDM_31 = valDM_31 + weights->at(k) *
6593 ( dPhiTransU[k][j][0] * u3Loc[0][k] * phiU->at(k).at(i) );
6594 valDM_32 = valDM_32 + weights->at(k) *
6595 ( dPhiTransU[k][j][1] * u3Loc[0][k] * phiU->at(k).at(i) );
6596 valDM_33 = valDM_33 + weights->at(k) *
6597 ( dPhiTransU[k][j][2] * u3Loc[0][k] * phiU->at(k).at(i) );
6598 }
6599
6600 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;
6601 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;
6602 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;
6603 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;
6604 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;
6605 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;
6606 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;
6607 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;
6608 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;
6609
6610 val11 = absDetB * val11;
6611 val12 = absDetB * val12;
6612 val13 = absDetB * val13;
6613 val21 = absDetB * val21;
6614 val22 = absDetB * val22;
6615 val23 = absDetB * val23;
6616 val31 = absDetB * val31;
6617 val32 = absDetB * val32;
6618 val33 = absDetB * val33;
6619
6620 value11[0] = val11; // x-x
6621 value12[0] = val12; // x-y
6622 value13[0] = val13; // x-z
6623 value21[0] = val21; // y-x
6624 value22[0] = val22; // y-y
6625 value23[0] = val23; // y-z
6626 value31[0] = val31; // z-x
6627 value32[0] = val32; // z-y
6628 value33[0] = val33; // z-z
6629
6630
6631 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6632 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6633 indices[0] = glob_j;
6634
6635 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
6636 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6637 D->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
6638 glob_j++;
6639 indices[0] = glob_j;
6640 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
6641 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6642 D->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
6643 glob_j++;
6644 indices[0] = glob_j;
6645 D->insertGlobalValues(glob_i, indices(), value13()); // x-z
6646 D->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
6647 D->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
6648 }
6649 }
6650 }
6651 if (callFillComplete)
6652 {
6653 D->fillComplete();
6654 }
6655 }
6656
6657}
6658
6659
6660template <class SC, class LO, class GO, class NO>
6661void FE<SC,LO,GO,NO>::assemblyShapeDerivativeDivergence(int dim,
6662 std::string FEType1,
6663 std::string FEType2,
6664 MatrixPtr_Type &DB,
6665 int FEloc1, // 1 = Fluid-Pressure
6666 int FEloc2, // 0 = Fluid-Velocity
6667 MapConstPtr_Type map1_unique, // Pressure-Map
6668 MapConstPtr_Type map2_unique, // Velocity-Map unique als VecField
6669 MultiVectorPtr_Type u, // Geschwindigkeit
6670 bool callFillComplete)
6671{
6672 DomainConstPtr_Type domain1 = domainVec_.at(FEloc1);
6673 ElementsPtr_Type elements = domain1->getElementsC();
6674 vec2D_dbl_ptr_Type pointsRep = domain1->getPointsRepeated();
6675 MapConstPtr_Type map1_rep = domain1->getMapRepeated();
6676
6677 // Fuer die Fluid-Velocity-Map
6678 DomainConstPtr_Type domain2 = domainVec_.at(FEloc2);
6679 MapConstPtr_Type map2_rep = domain2->getMapRepeated();
6680 ElementsPtr_Type elements2 = domain2->getElementsC();
6681
6682 vec3D_dbl_ptr_Type dPhiU;
6683 vec2D_dbl_ptr_Type phiU;
6684 vec2D_dbl_ptr_Type phiP;
6685 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6686 vec2D_dbl_ptr_Type quadPts;
6687
6688 UN extraDeg = Helper::determineDegree( dim, FEType1, Helper::Deriv1);
6689 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv0) + 2*extraDeg;
6690
6691
6692 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
6693 Helper::getPhi(phiU, weights, dim, FEType1, deg);
6694 Helper::getPhi(phiP, weights, dim, FEType2, deg);
6695 Helper::getQuadratureValues(dim, deg, quadPts, weights, FEType1);
6696
6697 // SC = double, GO = long, UN = int
6698 SC detB;
6699 SC absDetB;
6700 SmallMatrix<SC> B(dim);
6701 SmallMatrix<SC> Binv(dim);
6702 GO glob_i, glob_j;
6703
6704 // Der nichtlineare Teil als Array
6705 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
6706
6707 if (dim == 2)
6708 {
6709 double val1, val2;
6710 double valDB_1, valDB_2;
6711 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
6712
6713 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6714 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6715 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6716 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6717 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6718 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6719 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6720
6721 for (int T = 0; T < elements->numberElements(); T++)
6722 {
6723 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6724 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6725 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6726
6727 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6728 detB = B.computeInverse(Binv);
6729 absDetB = std::fabs(detB);
6730
6731 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6732 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6733 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6734
6735 // Diskrete Grad-Vektoren berechnen,
6736 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6737 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6738 {
6739 u11[0][k] = 0.0;
6740 u12[0][k] = 0.0;
6741 u21[0][k] = 0.0;
6742 u22[0][k] = 0.0;
6743 for(int i = 0; i < dPhiTransU[0].size(); i++)
6744 {
6745 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
6746 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
6747 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6748 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6749 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6750 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6751
6752 }
6753 }
6754
6755 for (int i = 0; i < phiP->at(0).size(); i++)
6756 {
6757 Teuchos::Array<SC> value1( 1, 0. ); // p-x
6758 Teuchos::Array<SC> value2( 1, 0. ); // p-y
6759 Teuchos::Array<GO> indices( 1, 0 );
6760
6761 for (int j = 0; j < dPhiU->at(0).size(); j++)
6762 {
6763 valDB_1 = 0.0;
6764 valDB_2 = 0.0;
6765
6766 for (int k = 0; k < dPhiU->size(); k++)
6767 {
6768 // DB
6769 valDB_1 = valDB_1 + weights->at(k) *
6770 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) );
6771 valDB_2 = valDB_2 + weights->at(k) *
6772 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] ) );
6773 }
6774
6775 val1 = valDB_1;
6776 val2 = valDB_2;
6777
6778 val1 = absDetB * val1;
6779 val2 = absDetB * val2;
6780
6781 value1[0] = val1; // p-x
6782 value2[0] = val2; // p-y
6783
6784 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
6785 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
6786 indices[0] = glob_j;
6787
6788 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
6789 glob_j++;
6790 indices[0] = glob_j;
6791 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
6792 }
6793 }
6794 }
6795 if (callFillComplete)
6796 {
6797 DB->fillComplete(map2_unique, map1_unique);
6798 }
6799 }
6800 else if(dim == 3)
6801 {
6802 double val1, val2, val3;
6803 double valDB_1, valDB_2, valDB_3;
6804 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6805
6806 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6807 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6808 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6809 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6810 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6811 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
6812 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6813 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6814 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
6815 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
6816 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
6817 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
6818
6819 for (int T = 0; T < elements->numberElements(); T++)
6820 {
6821 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6822 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6823 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6824 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6825
6826 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6827 detB = B.computeInverse(Binv);
6828 absDetB = std::fabs(detB);
6829
6830 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6831 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6832 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6833
6834 // Diskrete Grad-Vektoren berechnen,
6835 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6836 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6837 {
6838 u11[0][k] = 0.0;
6839 u12[0][k] = 0.0;
6840 u13[0][k] = 0.0;
6841 u21[0][k] = 0.0;
6842 u22[0][k] = 0.0;
6843 u23[0][k] = 0.0;
6844 u31[0][k] = 0.0;
6845 u32[0][k] = 0.0;
6846 u33[0][k] = 0.0;
6847
6848 for(int i = 0; i < dPhiTransU[0].size(); i++)
6849 {
6850 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
6851 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
6852 LO index3 = dim * elements2->getElement(T).getNode(i) + 2; // z
6853 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6854 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6855 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
6856 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6857 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6858 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
6859 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
6860 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
6861 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
6862 }
6863 }
6864
6865 for (int i = 0; i < phiP->at(0).size(); i++)
6866 {
6867 Teuchos::Array<SC> value1( 1, 0. ); // p-x
6868 Teuchos::Array<SC> value2( 1, 0. ); // p-y
6869 Teuchos::Array<SC> value3( 1, 0. ); // p-z
6870 Teuchos::Array<GO> indices( 1, 0 );
6871
6872 for (int j = 0; j < dPhiU->at(0).size(); j++)
6873 {
6874 valDB_1 = 0.0;
6875 valDB_2 = 0.0;
6876 valDB_3 = 0.0;
6877
6878 for (int k = 0; k < dPhiU->size(); k++)
6879 {
6880 // DB
6881 valDB_1 = valDB_1 + weights->at(k) *
6882 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] -
6883 u31[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) );
6884 valDB_2 = valDB_2 + weights->at(k) *
6885 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] -
6886 u32[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) );
6887 valDB_3 = valDB_3 + weights->at(k) *
6888 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][2] - u13[0][k] * dPhiTransU[k][j][0] +
6889 u22[0][k] * dPhiTransU[k][j][2] - u23[0][k] * dPhiTransU[k][j][1] ) );
6890 }
6891
6892 val1 = valDB_1;
6893 val2 = valDB_2;
6894 val3 = valDB_3;
6895
6896 val1 = absDetB * val1;
6897 val2 = absDetB * val2;
6898 val3 = absDetB * val3;
6899
6900 value1[0] = val1; // p-x
6901 value2[0] = val2; // p-y
6902 value3[0] = val3; // p-z
6903
6904 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
6905 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
6906 indices[0] = glob_j;
6907
6908 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
6909 glob_j++;
6910 indices[0] = glob_j;
6911 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
6912 glob_j++;
6913 indices[0] = glob_j;
6914 DB->insertGlobalValues(glob_i, indices(), value3()); // p-z
6915 }
6916 }
6917 }
6918 if (callFillComplete)
6919 {
6920 DB->fillComplete(map2_unique, map1_unique);
6921 }
6922 }
6923
6924}
6925
6926template <class SC, class LO, class GO, class NO>
6927void FE<SC,LO,GO,NO>::assemblySurfaceIntegralExternal(int dim,
6928 std::string FEType,
6929 MultiVectorPtr_Type f,
6930 MultiVectorPtr_Type d_rep,
6931 std::vector<SC>& funcParameter,
6932 RhsFunc_Type func,
6933 ParameterListPtr_Type params,
6934 int FEloc) {
6935
6936 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
6937
6938 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
6939
6940 SC elScaling;
6941 SmallMatrix<SC> B(dim);
6942 vec_dbl_Type b(dim);
6943 f->putScalar(0.);
6944 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
6945
6946 int flagSurface = params->sublist("Parameter Solid").get("Flag Surface",5);
6947
6948 std::vector<double> valueFunc(dim);
6949
6950 SC* paramsFunc = &(funcParameter[0]);
6951
6952 // The second last entry is a placeholder for the surface element flag. It will be set below
6953 for (UN T=0; T<elements->numberElements(); T++) {
6954 FiniteElement fe = elements->getElement( T );
6955 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
6956 for (int surface=0; surface<fe.numSubElements(); surface++) {
6957 FiniteElement feSub = subEl->getElement( surface );
6958 if(subEl->getDimension() == dim-1 ){
6959
6960 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
6961
6962
6963 vec_dbl_Type solution_d = getSolution(nodeList, d_rep,dim);
6964 vec2D_dbl_Type nodes;
6965 nodes = getCoordinates(nodeList, pointsRep);
6966
6967
6968 double positions[18];
6969 int count =0;
6970 for(int i=0;i<6;i++)
6971 for(int j=0;j<3;j++){
6972 positions[count] = nodes[i][j];
6973 count++;
6974
6975 }
6976
6977
6978 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
6979 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
6980 func( &p1[0], &valueFunc[0], paramsFunc);
6981
6982 if(valueFunc[0] != 0.){
6983
6984 double *residuumVector;
6985 #ifdef FEDD_HAVE_ACEGENINTERFACE
6986
6987 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1., 35, &positions[0], &solution_d[0]);
6988 pt.computeTangentResidual();
6989 residuumVector = pt.getResiduum();
6990 #endif
6991
6992 for(int i=0; i< nodeList.size() ; i++){
6993 for(int d=0; d<dim; d++)
6994 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
6995 }
6996
6997 // free(residuumVector);
6998 }
6999
7000 }
7001 }
7002 }
7003 //f->scale(-1.);
7004
7005}
7006
7009
7010template <class SC, class LO, class GO, class NO>
7012 std::string FEType,
7013 MultiVectorPtr_Type f,
7014 MultiVectorPtr_Type d_rep,
7015 MatrixPtr_Type &Kext,
7016 std::vector<SC>& funcParameter,
7017 RhsFunc_Type func,
7018 ParameterListPtr_Type params,
7019 int FEloc) {
7020
7021 // degree of function funcParameter[0]
7022
7023 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7024
7025 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7026
7027 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7028 SC elScaling;
7029 SmallMatrix<SC> B(dim);
7030 vec_dbl_Type b(dim);
7031 f->putScalar(0.);
7032 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
7033
7034 std::vector<double> valueFunc(dim);
7035
7036 SC* paramsFunc = &(funcParameter[0]);
7037
7038 // The second last entry is a placeholder for the surface element flag. It will be set below
7039 for (UN T=0; T<elements->numberElements(); T++) {
7040 FiniteElement fe = elements->getElement( T );
7041 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
7042 for (int surface=0; surface<fe.numSubElements(); surface++) {
7043 FiniteElement feSub = subEl->getElement( surface );
7044 if(subEl->getDimension() == dim-1 ){
7045 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
7046
7047 vec_dbl_Type solution_d = getSolution(nodeList, d_rep,dim);
7048 vec2D_dbl_Type nodes;
7049 nodes = getCoordinates(nodeList, pointsRep);
7050
7051
7052 double positions[18];
7053 int count =0;
7054 for(int i=0;i<6;i++){
7055 for(int j=0;j<3;j++){
7056 positions[count] = nodes[i][j];
7057 count++;
7058
7059 }
7060 }
7061
7062 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
7063 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
7064 func( &p1[0], &valueFunc[0], paramsFunc);
7065
7066 if(valueFunc[0] != 0.){
7067
7068 double *residuumVector;
7069 double **stiffMat;
7070
7071 #ifdef FEDD_HAVE_ACEGENINTERFACE
7072 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1.0, 35, &positions[0], &solution_d[0]);
7073 pt.computeTangentResidual();
7074
7075 residuumVector = pt.getResiduum();
7076 stiffMat = pt.getStiffnessMatrix();
7077 #endif
7078
7079
7080
7081 int dofs1 = dim;
7082 int numNodes1 =nodeList.size();
7083
7084 SmallMatrix_Type elementMatrixPrint(18,0.);
7085 for(int i=0; i< 18 ; i++){
7086 for(int j=0; j< 18; j++){
7087 if(std::fabs(stiffMat[i][j]) >1e-13)
7088 elementMatrixPrint[i][j] = stiffMat[i][j];
7089
7090 }
7091 }
7092
7093 SmallMatrix_Type elementMatrixWrite(18,0.);
7094
7095 SmallMatrix_Type elementMatrixIDsRow(18,0.);
7096 SmallMatrix_Type elementMatrixIDsCol(18,0.);
7097
7098
7099 for (UN i=0; i < numNodes1 ; i++) {
7100 for(int di=0; di<dim; di++){
7101 Teuchos::Array<SC> value1( numNodes1*dim, 0. );
7102 Teuchos::Array<GO> columnIndices1( numNodes1*dim, 0 );
7103 GO row =GO (dim* map->getGlobalElement( nodeList[i] )+di);
7104 LO rowLO = dim*i+di;
7105 // Zeilenweise werden die Einträge global assembliert
7106 for (UN j=0; j <numNodes1; j++){
7107 for(int d=0; d<dim; d++){
7108 columnIndices1[dim*j+d] = GO ( dim * map->getGlobalElement( nodeList[j] ) + d );
7109 value1[dim*j+d] = stiffMat[rowLO][dim*j+d];
7110 }
7111 }
7112 Kext->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
7113 }
7114 }
7115
7116
7117
7118 for(int i=0; i< nodeList.size() ; i++){
7119 for(int d=0; d<dim; d++){
7120 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
7121 }
7122 }
7123
7124
7125 }
7126
7127
7128 }
7129 }
7130 }
7131 //f->scale(-1.);
7132 Kext->fillComplete(domainVec_.at(FEloc)->getMapVecFieldUnique(),domainVec_.at(FEloc)->getMapVecFieldUnique());
7133 // Kext->writeMM("K_ext1");
7134}
7135
7137template <class SC, class LO, class GO, class NO>
7138void FE<SC,LO,GO,NO>::computeSurfaceNormal(int dim,
7139 vec2D_dbl_ptr_Type pointsRep,
7140 vec_int_Type nodeList,
7141 vec_dbl_Type &v_E,
7142 double &norm_v_E)
7143{
7144
7145 vec_dbl_Type p1(dim),p2(dim);
7146
7147 if(dim==2){
7148 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
7149 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
7150 norm_v_E = std::sqrt(std::pow(v_E[0],2)+std::pow(v_E[1],2));
7151
7152 }
7153 else if(dim==3){
7154
7155 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
7156 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
7157 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
7158
7159 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
7160 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
7161 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
7162
7163 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
7164 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
7165 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
7166
7167 norm_v_E = std::sqrt(std::pow(v_E[0],2)+std::pow(v_E[1],2)+std::pow(v_E[2],2));
7168
7169 }
7170
7171}
7172
7173template <class SC, class LO, class GO, class NO>
7174void FE<SC,LO,GO,NO>::assemblySurfaceIntegral(int dim,
7175 std::string FEType,
7176 MultiVectorPtr_Type f,
7177 std::string fieldType,
7178 RhsFunc_Type func,
7179 std::vector<SC>& funcParameter) {
7180
7181 // degree of function funcParameter[0]
7182 //TEUCHOS_TEST_FOR_EXCEPTION( funcParameter[funcParameter.size()-1] > 0., std::logic_error, "We only support constant functions for now.");
7183 UN FEloc = checkFE(dim,FEType);
7184
7185 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7186
7187 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7188
7189 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7190 vec2D_dbl_ptr_Type phi;
7191 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7192
7193 UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // Degree from function set/determined externally
7194 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
7195
7196 Helper::getPhi(phi, weights, dim-1, FEType, deg);
7197
7198 vec2D_dbl_ptr_Type quadPoints;
7199 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7200 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
7201 w.reset();
7202
7203 SC elScaling;
7204 SmallMatrix<SC> B(dim);
7205 vec_dbl_Type b(dim);
7206 f->putScalar(0.);
7207 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
7208 int parameters;
7209
7210
7211 std::vector<double> valueFunc(dim);
7212 // The second last entry is a placeholder for the surface element flag. It will be set below
7213 SC* params = &(funcParameter[0]);
7214 for (UN T=0; T<elements->numberElements(); T++) {
7215 FiniteElement fe = elements->getElement( T );
7216 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
7217 for (int surface=0; surface<fe.numSubElements(); surface++) {
7218 FiniteElement feSub = subEl->getElement( surface );
7219 if(subEl->getDimension() == dim-1){
7220 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
7221 params[ funcParameter.size() - 1 ] = feSub.getFlag();
7222
7223 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
7224
7225 vec_dbl_Type v_E(dim,1.);
7226 double norm_v_E=1.;
7227
7228 Helper::computeSurfaceNormal(dim, pointsRep,nodeList,v_E,norm_v_E);
7229
7230 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
7231 elScaling = B.computeScaling( );
7232 // loop over basis functions
7233 for (UN i=0; i < phi->at(0).size(); i++) {
7234 Teuchos::Array<SC> value(0);
7235 if ( fieldType == "Scalar" )
7236 value.resize( 1, 0. );
7237 else if ( fieldType == "Vector" )
7238 value.resize( dim, 0. );
7239 // loop over basis functions quadrature points
7240 for (UN w=0; w<phi->size(); w++) {
7241 vec_dbl_Type x(dim,0.); //coordinates
7242 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7243 for (int l=0; l<dim-1; l++){
7244 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
7245 }
7246 x[k] += b[k];
7247 }
7248
7249 func( &x[0], &valueFunc[0], params);
7250 if ( fieldType == "Scalar" )
7251 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7252 else if ( fieldType == "Vector" ){
7253 for (int j=0; j<value.size(); j++){
7254 value[j] += weights->at(w) * valueFunc[j]*v_E[j]/norm_v_E * (*phi)[w][i];
7255 }
7256 }
7257 }
7258
7259 for (int j=0; j<value.size(); j++)
7260 value[j] *= elScaling;
7261
7262 if ( fieldType== "Scalar" )
7263 valuesF[ nodeList[ i ] ] += value[0];
7264
7265
7266 else if ( fieldType== "Vector" ){
7267 for (int j=0; j<value.size(); j++)
7268 valuesF[ dim * nodeList[ i ] + j ] += value[j];
7269 }
7270 }
7271 }
7272 }
7273 }
7274 f->scale(-1.); // Generally the pressure is definied in opposite direction of the normal
7275}
7276
7277template <class SC, class LO, class GO, class NO>
7278void FE<SC,LO,GO,NO>::assemblySurfaceIntegralFlag(int dim,
7279 std::string FEType,
7280 MultiVectorPtr_Type f,
7281 std::string fieldType,
7282 BC_func_Type func,
7283 std::vector<SC>& funcParameter) {
7284
7285// degree of function funcParameter[0]
7286 TEUCHOS_TEST_FOR_EXCEPTION(funcParameter[0]!=0,std::logic_error, "We only support constant functions for now.");
7287
7288 UN FEloc = checkFE(dim,FEType);
7289
7290 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7291
7292 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7293
7294 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7295 vec2D_dbl_ptr_Type phi;
7296 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7297 UN degFunc = funcParameter[0] + 1.e-14;
7298 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
7299
7300 Helper::getPhi(phi, weights, dim-1, FEType, deg);
7301
7302 vec2D_dbl_ptr_Type quadPoints;
7303 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7304 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
7305 w.reset();
7306
7307 SC elScaling;
7308 SmallMatrix<SC> B(dim);
7309 vec_dbl_Type b(dim);
7310 f->putScalar(0.);
7311 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
7312 int parameters;
7313
7314 std::vector<double> valueFunc(dim);
7315 SC* params = &(funcParameter[1]);
7316 for (UN T=0; T<elements->numberElements(); T++) {
7317 FiniteElement fe = elements->getElement( T );
7318 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
7319 for (int surface=0; surface<fe.numSubElements(); surface++) {
7320 FiniteElement feSub = subEl->getElement( surface );
7321 if (params[1] == feSub.getFlag()){
7322 FiniteElement feSub = subEl->getElement( surface );
7323 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
7324 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
7325 elScaling = B.computeScaling( );
7326 // loop over basis functions
7327 for (UN i=0; i < phi->at(0).size(); i++) {
7328 Teuchos::Array<SC> value(0);
7329 if ( fieldType == "Scalar" )
7330 value.resize( 1, 0. );
7331 else if ( fieldType == "Vector" )
7332 value.resize( dim, 0. );
7333 // loop over basis functions quadrature points
7334 for (UN w=0; w<phi->size(); w++) {
7335 vec_dbl_Type x(dim,0.); //coordinates
7336 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7337 for (int l=0; l<dim-1; l++)
7338 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
7339 x[k] += b[k];
7340 }
7341
7342 func( &x[0], &valueFunc[0], params[0], params);
7343// func( &x[0], &valueFunc[0], params);
7344 if ( fieldType == "Scalar" )
7345 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7346 else if ( fieldType == "Vector" ){
7347 for (int j=0; j<value.size(); j++){
7348 value[j] += weights->at(w) * valueFunc[j] * (*phi)[w][i];
7349 }
7350 }
7351 }
7352
7353 for (int j=0; j<value.size(); j++)
7354 value[j] *= elScaling;
7355
7356 if ( fieldType== "Scalar" )
7357 valuesF[ nodeList[ i ] ] += value[0];
7358
7359
7360 else if ( fieldType== "Vector" ){
7361 for (int j=0; j<value.size(); j++)
7362 valuesF[ dim * nodeList[ i ] + j ] += value[j];
7363 }
7364 }
7365 }
7366 }
7367
7368 }
7369}
7370
7371template <class SC, class LO, class GO, class NO>
7372void FE<SC,LO,GO,NO>::assemblyRHS( int dim,
7373 std::string FEType,
7374 MultiVectorPtr_Type a,
7375 std::string fieldType,
7376 RhsFunc_Type func,
7377 std::vector<SC>& funcParameter
7378 ) {
7379
7380 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7381
7382 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
7383 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
7384 UN FEloc;
7385 FEloc = checkFE(dim,FEType);
7386
7387 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7388
7389 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7390
7391 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7392 vec2D_dbl_ptr_Type phi;
7393 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7394
7395 // last parameter should alwayss be the degree
7396 //UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // TODO: [JK] Can we remove this?
7397 // inner( f(x), phi(x) ) requires the integration degree of the basis function + some
7398 // extra user-provided degree that accounts for the heterogeneity of f(x).
7399 UN degFunc = 2; // TODO: [JK] Hard coded for now, but needs to be passed by the user. See GitHub issue #66.
7400 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv0) + degFunc;
7401
7402 vec2D_dbl_ptr_Type quadPoints;
7403 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
7404
7405
7406 Helper::getPhi(phi, weights, dim, FEType, deg);
7407
7408 SC detB;
7409 SC absDetB;
7410 SmallMatrix<SC> B(dim);
7411 GO glob_i, glob_j;
7412 vec_dbl_Type v_i(dim);
7413 vec_dbl_Type v_j(dim);
7414
7415 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
7416 int parameters;
7417 double x;
7418 //for now just const!
7419 std::vector<double> valueFunc(dim);
7420 SC* paras = &(funcParameter[0]);
7421
7422 func( &x, &valueFunc[0], paras );
7423 SC value;
7424
7425 for (UN T=0; T<elements->numberElements(); T++) {
7426
7427 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
7428 detB = B.computeDet( );
7429 absDetB = std::fabs(detB);
7430
7431 vec2D_dbl_Type quadPointsTrans(weights->size(),vec_dbl_Type(dim));
7432 for(int i=0; i< weights->size(); i++){
7433 for(int j=0; j< dim ; j++){
7434 for(int k=0; k< dim; k++){
7435 quadPointsTrans[i][j] += B[j][k]* quadPoints->at(i).at(k) ;
7436 }
7437 quadPointsTrans[i][j] += pointsRep->at(elements->getElement(T).getNode(0)).at(j);
7438 }
7439 }
7440 for (UN i=0; i < phi->at(0).size(); i++) {
7441 if ( !fieldType.compare("Scalar") ) {
7442 value = Teuchos::ScalarTraits<SC>::zero();
7443 for (UN w=0; w<weights->size(); w++){
7444 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
7445 value += weights->at(w) * phi->at(w).at(i)*valueFunc[0];
7446 }
7447 value *= absDetB;
7448 LO row = (LO) elements->getElement(T).getNode(i);
7449 valuesRhs[row] += value;
7450 }
7451 else if( !fieldType.compare("Vector") ) {
7452 for (UN d=0; d<dim; d++) {
7453 value = Teuchos::ScalarTraits<SC>::zero();
7454 for (UN w=0; w<weights->size(); w++){
7455 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
7456 value += weights->at(w) * phi->at(w).at(i)*valueFunc[d];
7457 }
7458 value *= absDetB;
7459 SC v_i = value;
7460 LO row = (LO) ( dim * elements->getElement(T).getNode(i) + d );
7461 valuesRhs[row] += v_i;
7462 }
7463 }
7464 else
7465 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
7466 }
7467 }
7468}
7469
7474template <class SC, class LO, class GO, class NO>
7476 std::string FEType,
7477 MatrixPtr_Type a,
7478 MatrixPtr_Type aT)
7479 {
7480
7481 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7482
7483 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "Matrix is null." );
7484
7485 UN FEloc;
7486 FEloc = checkFE(dim,FEType);
7487
7488 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7489
7490 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7491
7492 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7493 vec2D_dbl_ptr_Type phi;
7494 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7495 // last parameter should alwayss be the degree
7496 UN deg = 2;
7497
7498 vec2D_dbl_ptr_Type quadPoints;
7499 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
7500
7501 Helper::getPhi(phi, weights, dim, FEType, deg);
7502
7503 SC detB;
7504 SC absDetB;
7505 SmallMatrix<SC> B(dim);
7506 GO glob_i, glob_j;
7507 vec_dbl_Type v_i(dim);
7508 vec_dbl_Type v_j(dim);
7509
7510
7511 for (UN T=0; T<elements->numberElements(); T++) {
7512
7513 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
7514 detB = B.computeDet( );
7515 absDetB = std::fabs(detB);
7516
7517 for (UN i=0; i < phi->at(0).size(); i++) {
7518 Teuchos::Array<SC> value( 1, 0. );
7519 for (UN w=0; w<weights->size(); w++){
7520 value[0] += weights->at(w) * phi->at(w).at(i)*1.0;
7521 }
7522 value[0] *= absDetB;
7523 LO row = (LO) elements->getElement(T).getNode(i);
7524 Teuchos::Array<GO> columnIndices( 1, 0 ); // We only have on column
7525
7526 a->insertGlobalValues( row, columnIndices(), value() ); // Automatically adds entries if a value already exists
7527 columnIndices[0] = row;
7528 aT->insertGlobalValues( 0, columnIndices(), value() ); // Automatically adds entries if a value already exists
7529 }
7530 }
7531 a->fillComplete();
7532 //a->print();
7533
7534}
7535
7536
7537template <class SC, class LO, class GO, class NO>
7538void FE<SC,LO,GO,NO>::assemblyRHSDegTest( int dim,
7539 std::string FEType,
7540 MultiVectorPtr_Type a,
7541 std::string fieldType,
7542 RhsFunc_Type func,
7543 std::vector<SC>& funcParameter,
7544 int degree) {
7545 // TODO: [JK] What is the aim of this function? It is not called by any problems, only by a test.
7546 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7547
7548 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
7549 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
7550
7551 UN FEloc = checkFE(dim,FEType);
7552
7553 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7554
7555 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7556
7557 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7558 vec2D_dbl_ptr_Type phi;
7559 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7560 Helper::getPhi(phi, weights, dim, FEType, degree);
7561
7562 vec2D_dbl_ptr_Type quadPoints;
7563 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7564 Helper::getQuadratureValues(dim, degree, quadPoints, w, FEType);
7565 w.reset();
7566
7567
7568 SC detB;
7569 SC absDetB;
7570 SmallMatrix<SC> B(dim);
7571 vec_dbl_Type b(dim);
7572 GO glob_i, glob_j;
7573 vec_dbl_Type v_i(dim);
7574 vec_dbl_Type v_j(dim);
7575
7576 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
7577 int parameters;
7578 double x;
7579 //for now just const!
7580 std::vector<double> valueFunc(dim);
7581 SC* params = &(funcParameter[1]);
7582 for (UN T=0; T<elements->numberElements(); T++) {
7583
7584 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, b, FEType);
7585 detB = B.computeDet( );
7586 absDetB = std::fabs(detB);
7587
7588 for (UN i=0; i < phi->at(0).size(); i++) {
7589 Teuchos::Array<SC> value(1);
7590 for (UN w=0; w<weights->size(); w++){
7591 vec_dbl_Type x(dim,0.); //coordinates
7592 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7593 for (int l=0; l<dim; l++)
7594 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ] + b[k];
7595 }
7596
7597 func( &x[0], &valueFunc[0], params);
7598 if ( !fieldType.compare("Scalar") ) {
7599 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7600 }
7601 else if( !fieldType.compare("Vector") ) {
7602 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No test for field type Vector." );
7603 }
7604 else
7605 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
7606
7607 }
7608 value[0] *= absDetB;
7609 LO row = (LO) elements->getElement(T).getNode(i);
7610 valuesRhs[row] += value[0];
7611
7612 }
7613 }
7614}
7615
7616
7617template <class SC, class LO, class GO, class NO>
7618void FE<SC,LO,GO,NO>::buildFullDPhi(vec3D_dbl_ptr_Type dPhi, Teuchos::Array<SmallMatrix<double> >& dPhiMat){
7619
7620 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.");
7621
7622 int dim = dPhi->at(0).at(0).size();
7623 int nmbBasisFunc = dPhi->at(0).size();
7624 int nmbTotalBasisFunc = nmbBasisFunc * dim;
7625 if (dim==2) {
7626 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
7627 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
7628 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
7629 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
7630 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
7631 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
7632
7633 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
7634 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
7635 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
7636 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
7637 }
7638 }
7639 }
7640 else if(dim==3){
7641 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
7642 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
7643 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
7644 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
7645 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][2] = dPhi->at(p).at(i).at(2);
7646 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
7647 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
7648 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][2] = 0.;
7649 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][0] = 0.;
7650 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][1] = 0.;
7651 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][2] = 0.;
7652
7653 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
7654 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
7655 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][2] = 0.;
7656 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
7657 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
7658 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][2] = dPhi->at(p).at(i).at(2);
7659 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][0] = 0.;
7660 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][1] = 0.;
7661 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][2] = 0.;
7662
7663 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][0] = 0.;
7664 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][1] = 0.;
7665 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][2] = 0.;
7666 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][0] = 0.;
7667 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][1] = 0.;
7668 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][2] = 0.;
7669 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][0] = dPhi->at(p).at(i).at(0);
7670 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][1] = dPhi->at(p).at(i).at(1);
7671 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][2] = dPhi->at(p).at(i).at(2);
7672 }
7673 }
7674 }
7675}
7676
7677template <class SC, class LO, class GO, class NO>
7678void FE<SC,LO,GO,NO>::fillMatrixArray(SmallMatrix<double> &matIn, double* matArrayOut, std::string order,int offset){
7679 if (!order.compare("cols")) {
7680 for (int j=0; j<matIn.size(); j++) {
7681 for (int i=0; i<matIn.size(); i++) {
7682 matArrayOut[ j * matIn.size() + i + offset ] = matIn[i][j]; //Spalten der Matrix werden hintereinander in array geschrieben
7683 }
7684 }
7685 }
7686 else if(!order.compare("rows")) {
7687 for (int i=0; i<matIn.size(); i++) {
7688 for (int j=0; j<matIn.size(); j++) {
7689 matArrayOut[ i * matIn.size() + j + offset ] = matIn[i][j]; //Zeilen der Matrix werden hintereinander in array geschrieben
7690 }
7691 }
7692 }
7693 else
7694 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Unknown ordering for matrix to array conversion. Choose rows or cols.");
7695}
7696
7697template <class SC, class LO, class GO, class NO>
7698void FE<SC,LO,GO,NO>::epsilonTensor(vec_dbl_Type &basisValues, SmallMatrix<SC> &epsilonValues, int activeDof){
7699
7700 for (int i=0; i<epsilonValues.size(); i++) {
7701 for (int j=0; j<epsilonValues.size(); j++) {
7702 epsilonValues[i][j] = 0.;
7703 if (i==activeDof) {
7704 epsilonValues[i][j] += 0.5*basisValues.at(j);
7705 }
7706 if (j==activeDof) {
7707 epsilonValues[i][j] += 0.5*basisValues.at(i);
7708 }
7709 }
7710 }
7711}
7712
7713template <class SC, class LO, class GO, class NO>
7714int FE<SC,LO,GO,NO>::checkFE(int dim,
7715 std::string FEType){
7716
7717 int FEloc;
7718 std::vector<int> matches;
7719 for (int i = 0; i < domainVec_.size(); i++) {
7720 if (domainVec_.at(i)->getDimension() == dim)
7721 matches.push_back(i);
7722 }
7723
7724 bool found = false;
7725 for (int i = 0; i < matches.size();i++) {
7726 if (domainVec_.at( matches.at(i) )->getFEType() == FEType) {
7727 FEloc = matches.at(i);
7728 found = true;
7729 }
7730 }
7731
7732 TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error ,"Combination of dimenson(2/3) and FE Type(P1/P2) not defined yet. Use addFE(domain)");
7733
7734 return FEloc;
7735}
7736
7737
7738/*************************************************************
7739 * AceGen 6.921 MacOSX (29 Jan 19) *
7740 * Co. J. Korelc 2013 12 Feb 19 12:07:04 *
7741 **************************************************************
7742 User : Full professional version
7743 Notebook : nh3d_C
7744 Evaluation time : 6 s Mode : Optimal
7745 Number of formulae : 181 Method: Automatic
7746 Subroutine : nh3d size: 4928
7747 Total size of Mathematica code : 4928 subexpressions
7748 Total size of C code : 10178 bytes */
7749/******************* S U B R O U T I N E *********************/
7750template <class SC, class LO, class GO, class NO>
7751void FE<SC,LO,GO,NO>::nh3d(double* v, double (*E), double (*Nu), double** F , double** Pmat, double**** Amat)
7752{
7753 v[356]=2e0*F[0][2];
7754 v[354]=2e0*F[0][1];
7755 v[323]=(*E)/(1e0+(*Nu));
7756 v[3]=((*Nu)*v[323])/(1e0-2e0*(*Nu));
7757 v[5]=v[323]/2e0;
7758 v[36]=v[5]/2e0;
7759 v[65]=2e0*F[0][1];
7760 v[86]=2e0*F[0][2];
7761 v[57]=2e0*F[1][0];
7762 v[66]=2e0*F[1][1];
7763 v[87]=2e0*F[1][2];
7764 v[58]=2e0*F[2][0];
7765 v[67]=2e0*F[2][1];
7766 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
7767 v[335]=(v[18]*v[18]);
7768 v[88]=2e0*F[2][2];
7769 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
7770 v[334]=(v[24]*v[24]);
7771 v[325]=v[18]*v[24];
7772 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
7773 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
7774 v[228]=-(F[2][1]*v[18]);
7775 v[225]=F[2][2]*v[18];
7776 v[217]=-(F[1][1]*v[18]);
7777 v[214]=F[1][2]*v[18];
7778 v[194]=-(F[2][0]*v[18]);
7779 v[185]=-(F[1][0]*v[18]);
7780 v[268]=F[2][1]*v[22];
7781 v[264]=-(F[2][2]*v[22]);
7782 v[255]=F[1][1]*v[22];
7783 v[251]=-(F[1][2]*v[22]);
7784 v[190]=-(F[2][0]*v[22]);
7785 v[181]=-(F[1][0]*v[22]);
7786 v[172]=-(F[0][0]*v[22]);
7787 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
7788 v[324]=-(v[20]*v[22]);
7789 v[327]=2e0*(v[324]+v[325]);
7790 v[94]=v[20]*v[88];
7791 v[92]=v[20]*v[87];
7792 v[90]=v[20]*v[86];
7793 v[138]=v[15]*v[20]-v[335];
7794 v[270]=F[2][0]*v[24];
7795 v[260]=-(F[2][2]*v[24]);
7796 v[257]=F[1][0]*v[24];
7797 v[247]=-(F[1][2]*v[24]);
7798 v[244]=F[0][0]*v[24];
7799 v[232]=-(F[0][2]*v[24]);
7800 v[222]=-(F[2][1]*v[24]);
7801 v[211]=-(F[1][1]*v[24]);
7802 v[198]=-(F[0][1]*v[24]);
7803 v[168]=v[18]*v[22]-v[15]*v[24];
7804 v[331]=2e0*v[168];
7805 v[329]=2e0*v[168];
7806 v[326]=2e0*v[168];
7807 v[38]=-(v[22]*v[22]);
7808 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
7809 v[333]=v[20]*v[26]-v[334];
7810 v[351]=2e0*F[0][0]*v[333];
7811 v[236]=v[22]*v[24]-v[18]*v[26];
7812 v[332]=2e0*v[236];
7813 v[330]=2e0*v[236];
7814 v[328]=2e0*v[236];
7815 v[99]=v[26]*v[58];
7816 v[97]=v[26]*v[57];
7817 v[93]=v[26]*v[67];
7818 v[91]=v[26]*v[66];
7819 v[89]=v[26]*v[65];
7820 v[148]=v[15]*v[26]+v[38];
7821 v[29]=v[148]*v[20]+2e0*v[22]*v[325]-v[15]*v[334]-v[26]*v[335];
7822 v[336]=1e0/Power(v[29],2);
7823 v[32]=-v[5]+v[3]*std::log(std::sqrt(v[29]));
7824 v[337]=(v[3]/4e0-v[32]/2e0)*v[336];
7825 v[137]=v[337]*(F[2][1]*v[326]+F[2][0]*v[327]-v[335]*v[88]+v[15]*v[94]);
7826 v[147]=v[137]*v[138];
7827 v[136]=v[337]*(F[2][2]*v[329]+F[2][0]*v[330]+v[38]*v[67]+v[15]*v[93]);
7828 v[156]=v[136]*v[148];
7829 v[135]=v[337]*(F[2][2]*v[327]+F[2][1]*v[328]-v[334]*v[58]+v[20]*v[99]);
7830 v[165]=v[135]*v[333];
7831 v[134]=v[337]*(F[1][1]*v[326]+F[1][0]*v[327]-v[335]*v[87]+v[15]*v[92]);
7832 v[144]=v[134]*v[138];
7833 v[133]=v[337]*(F[1][2]*v[331]+F[1][0]*v[332]+v[38]*v[66]+v[15]*v[91]);
7834 v[153]=v[133]*v[148];
7835 v[132]=v[337]*(F[1][2]*v[327]+F[1][1]*v[328]-v[334]*v[57]+v[20]*v[97]);
7836 v[162]=v[132]*v[333];
7837 v[131]=v[337]*(F[0][0]*v[327]+F[0][1]*v[329]-v[335]*v[86]+v[15]*v[90]);
7838 v[130]=v[337]*(F[0][2]*v[331]+F[0][0]*v[332]+v[38]*v[65]+v[15]*v[89]);
7839 v[128]=v[337]*(F[0][2]*v[327]+F[0][1]*v[330]+v[351]);
7840 v[37]=v[32]/(2e0*v[29]);
7841 v[355]=v[37]*(2e0*v[172]+v[15]*v[86]);
7842 v[353]=v[37]*(2e0*v[232]+v[89]);
7843 v[352]=v[37]*(2e0*v[198]+v[90]);
7844 v[349]=-2e0*(F[1][0]*v[20]+v[217])*v[37];
7845 v[348]=-(v[37]*(2e0*v[185]+v[15]*v[66]));
7846 v[347]=-2e0*(F[2][0]*v[20]+v[228])*v[37];
7847 v[346]=-(v[37]*(2e0*v[194]+v[15]*v[67]));
7848 v[345]=-(v[37]*(2e0*v[251]+v[97]));
7849 v[344]=-(v[37]*(2e0*v[181]+v[15]*v[87]));
7850 v[343]=-(v[37]*(2e0*v[264]+v[99]));
7851 v[342]=-(v[37]*(2e0*v[190]+v[15]*v[88]));
7852 v[341]=-(v[37]*(2e0*v[247]+v[91]));
7853 v[340]=-(v[37]*(2e0*v[211]+v[92]));
7854 v[339]=-(v[37]*(2e0*v[260]+v[93]));
7855 v[338]=-(v[37]*(2e0*v[222]+v[94]));
7856 v[272]=v[137]*v[328]+v[37]*(2e0*v[268]+2e0*v[270]-2e0*v[18]*v[88]);
7857 v[267]=v[136]*v[328]+v[343];
7858 v[263]=v[135]*v[328]+v[339];
7859 v[259]=v[134]*v[328]+v[37]*(2e0*v[255]+2e0*v[257]-2e0*v[18]*v[87]);
7860 v[254]=v[133]*v[328]+v[345];
7861 v[250]=v[132]*v[328]+v[341];
7862 v[246]=v[131]*v[328]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[244]-2e0*v[18]*v[86]);
7863 v[241]=v[130]*v[328]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
7864 v[231]=v[137]*v[327]+v[347];
7865 v[227]=v[136]*v[327]+v[37]*(2e0*v[225]+2e0*v[270]-2e0*v[22]*v[67]);
7866 v[224]=v[135]*v[327]+v[338];
7867 v[301]=2e0*F[1][0]*v[165]+F[1][2]*v[224]+F[1][1]*v[263];
7868 v[279]=2e0*F[0][0]*v[165]+F[0][2]*v[224]+F[0][1]*v[263];
7869 v[220]=v[134]*v[327]+v[349];
7870 v[216]=v[133]*v[327]+v[37]*(2e0*v[214]+2e0*v[257]-2e0*v[22]*v[66]);
7871 v[213]=v[132]*v[327]+v[340];
7872 v[276]=2e0*F[0][0]*v[162]+F[0][2]*v[213]+F[0][1]*v[250];
7873 v[209]=v[131]*v[327]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
7874 v[196]=v[137]*v[326]+v[346];
7875 v[314]=2e0*F[1][2]*v[147]+F[1][1]*v[196]+F[1][0]*v[231];
7876 v[296]=2e0*F[0][2]*v[147]+F[0][1]*v[196]+F[0][0]*v[231];
7877 v[192]=v[136]*v[326]+v[342];
7878 v[308]=2e0*F[1][1]*v[156]+F[1][2]*v[192]+F[1][0]*v[267];
7879 v[288]=2e0*F[0][1]*v[156]+F[0][2]*v[192]+F[0][0]*v[267];
7880 v[188]=v[135]*v[326]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[24]*v[58]);
7881 v[187]=v[134]*v[326]+v[348];
7882 v[293]=2e0*F[0][2]*v[144]+F[0][1]*v[187]+F[0][0]*v[220];
7883 v[183]=v[133]*v[326]+v[344];
7884 v[285]=2e0*F[0][1]*v[153]+F[0][2]*v[183]+F[0][0]*v[254];
7885 v[179]=v[132]*v[326]+v[37]*(2e0*v[214]+2e0*v[255]-2e0*v[24]*v[57]);
7886 v[178]=v[131]*v[326]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
7887 v[167]=v[137]*v[333]-v[338];
7888 v[303]=2e0*F[1][0]*v[167]+F[1][2]*v[231]+F[1][1]*v[272];
7889 v[281]=2e0*F[0][0]*v[167]+F[0][2]*v[231]+F[0][1]*v[272];
7890 v[166]=v[136]*v[333]-v[339];
7891 v[302]=2e0*F[1][0]*v[166]+F[1][2]*v[227]+F[1][1]*v[267];
7892 v[280]=2e0*F[0][0]*v[166]+F[0][2]*v[227]+F[0][1]*v[267];
7893 v[164]=v[134]*v[333]-v[340];
7894 v[278]=2e0*F[0][0]*v[164]+F[0][2]*v[220]+F[0][1]*v[259];
7895 v[163]=v[133]*v[333]-v[341];
7896 v[277]=2e0*F[0][0]*v[163]+F[0][2]*v[216]+F[0][1]*v[254];
7897 v[157]=v[137]*v[148]-v[342];
7898 v[309]=2e0*F[1][1]*v[157]+F[1][2]*v[196]+F[1][0]*v[272];
7899 v[289]=2e0*F[0][1]*v[157]+F[0][2]*v[196]+F[0][0]*v[272];
7900 v[155]=v[135]*v[148]-v[343];
7901 v[307]=2e0*F[1][1]*v[155]+F[1][2]*v[188]+F[1][0]*v[263];
7902 v[287]=2e0*F[0][1]*v[155]+F[0][2]*v[188]+F[0][0]*v[263];
7903 v[154]=v[134]*v[148]-v[344];
7904 v[286]=2e0*F[0][1]*v[154]+F[0][2]*v[187]+F[0][0]*v[259];
7905 v[284]=F[0][2]*v[179]+F[0][0]*v[250]+2e0*F[0][1]*(v[132]*v[148]-v[345]);
7906 v[146]=v[136]*v[138]-v[346];
7907 v[313]=2e0*F[1][2]*v[146]+F[1][1]*v[192]+F[1][0]*v[227];
7908 v[295]=2e0*F[0][2]*v[146]+F[0][1]*v[192]+F[0][0]*v[227];
7909 v[145]=v[135]*v[138]-v[347];
7910 v[312]=2e0*F[1][2]*v[145]+F[1][1]*v[188]+F[1][0]*v[224];
7911 v[294]=2e0*F[0][2]*v[145]+F[0][1]*v[188]+F[0][0]*v[224];
7912 v[292]=F[0][1]*v[183]+F[0][0]*v[216]+2e0*F[0][2]*(v[133]*v[138]-v[348]);
7913 v[291]=F[0][1]*v[179]+F[0][0]*v[213]+(v[132]*v[138]-v[349])*v[356];
7914 v[35]=v[36]+v[138]*v[37];
7915 v[310]=2e0*v[35];
7916 v[40]=v[36]+v[148]*v[37];
7917 v[304]=2e0*v[40];
7918 v[43]=v[36]+v[333]*v[37];
7919 v[297]=2e0*v[43];
7920 v[44]=v[326]*v[37];
7921 v[319]=2e0*F[2][1]*v[157]+F[2][2]*v[196]+F[2][0]*v[272]+v[44];
7922 v[306]=2e0*F[1][1]*v[154]+F[1][2]*v[187]+F[1][0]*v[259]+v[44];
7923 v[283]=F[0][2]*v[178]+F[0][0]*v[246]+v[354]*(v[131]*v[148]+v[355])+v[44];
7924 v[45]=v[327]*v[37];
7925 v[317]=2e0*F[2][0]*v[167]+F[2][2]*v[231]+F[2][1]*v[272]+v[45];
7926 v[300]=2e0*F[1][0]*v[164]+F[1][2]*v[220]+F[1][1]*v[259]+v[45];
7927 v[275]=F[0][2]*v[209]+F[0][1]*v[246]+2e0*F[0][0]*(v[131]*v[333]+v[352])+v[45];
7928 v[46]=v[328]*v[37];
7929 v[316]=2e0*F[2][0]*v[166]+F[2][2]*v[227]+F[2][1]*v[267]+v[46];
7930 v[299]=2e0*F[1][0]*v[163]+F[1][2]*v[216]+F[1][1]*v[254]+v[46];
7931 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]*
7932 (2e0*F[0][2]*v[18]+2e0*v[244]-2e0*v[22]*v[65]));
7933 Pmat[0][0]=F[0][0]*v[297]+F[0][2]*v[45]+F[0][1]*v[46];
7934 Pmat[0][1]=F[0][1]*v[304]+F[0][2]*v[44]+F[0][0]*v[46];
7935 Pmat[0][2]=F[0][2]*v[310]+F[0][1]*v[44]+F[0][0]*v[45];
7936 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[45]+F[1][1]*v[46];
7937 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[44]+F[1][0]*v[46];
7938 Pmat[1][2]=2e0*F[1][2]*v[35]+F[1][1]*v[44]+F[1][0]*v[45];
7939 Pmat[2][0]=F[2][0]*v[297]+F[2][2]*v[45]+F[2][1]*v[46];
7940 Pmat[2][1]=F[2][1]*v[304]+F[2][2]*v[44]+F[2][0]*v[46];
7941 Pmat[2][2]=F[2][2]*v[310]+F[2][1]*v[44]+F[2][0]*v[45];
7942 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]
7943 );
7944 Amat[0][0][0][1]=v[274];
7945 Amat[0][0][0][2]=v[275];
7946 Amat[0][0][1][0]=v[276];
7947 Amat[0][0][1][1]=v[277];
7948 Amat[0][0][1][2]=v[278];
7949 Amat[0][0][2][0]=v[279];
7950 Amat[0][0][2][1]=v[280];
7951 Amat[0][0][2][2]=v[281];
7952 Amat[0][1][0][0]=v[274];
7953 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]);
7954 Amat[0][1][0][2]=v[283];
7955 Amat[0][1][1][0]=v[284];
7956 Amat[0][1][1][1]=v[285];
7957 Amat[0][1][1][2]=v[286];
7958 Amat[0][1][2][0]=v[287];
7959 Amat[0][1][2][1]=v[288];
7960 Amat[0][1][2][2]=v[289];
7961 Amat[0][2][0][0]=v[275];
7962 Amat[0][2][0][1]=v[283];
7963 Amat[0][2][0][2]=F[0][1]*v[178]+F[0][0]*v[209]+v[310]+v[131]*v[138]*v[356];
7964 Amat[0][2][1][0]=v[291];
7965 Amat[0][2][1][1]=v[292];
7966 Amat[0][2][1][2]=v[293];
7967 Amat[0][2][2][0]=v[294];
7968 Amat[0][2][2][1]=v[295];
7969 Amat[0][2][2][2]=v[296];
7970 Amat[1][0][0][0]=v[276];
7971 Amat[1][0][0][1]=v[284];
7972 Amat[1][0][0][2]=v[291];
7973 Amat[1][0][1][0]=2e0*F[1][0]*v[162]+F[1][2]*v[213]+F[1][1]*v[250]+v[297];
7974 Amat[1][0][1][1]=v[299];
7975 Amat[1][0][1][2]=v[300];
7976 Amat[1][0][2][0]=v[301];
7977 Amat[1][0][2][1]=v[302];
7978 Amat[1][0][2][2]=v[303];
7979 Amat[1][1][0][0]=v[277];
7980 Amat[1][1][0][1]=v[285];
7981 Amat[1][1][0][2]=v[292];
7982 Amat[1][1][1][0]=v[299];
7983 Amat[1][1][1][1]=2e0*F[1][1]*v[153]+F[1][2]*v[183]+F[1][0]*v[254]+v[304];
7984 Amat[1][1][1][2]=v[306];
7985 Amat[1][1][2][0]=v[307];
7986 Amat[1][1][2][1]=v[308];
7987 Amat[1][1][2][2]=v[309];
7988 Amat[1][2][0][0]=v[278];
7989 Amat[1][2][0][1]=v[286];
7990 Amat[1][2][0][2]=v[293];
7991 Amat[1][2][1][0]=v[300];
7992 Amat[1][2][1][1]=v[306];
7993 Amat[1][2][1][2]=2e0*F[1][2]*v[144]+F[1][1]*v[187]+F[1][0]*v[220]+v[310];
7994 Amat[1][2][2][0]=v[312];
7995 Amat[1][2][2][1]=v[313];
7996 Amat[1][2][2][2]=v[314];
7997 Amat[2][0][0][0]=v[279];
7998 Amat[2][0][0][1]=v[287];
7999 Amat[2][0][0][2]=v[294];
8000 Amat[2][0][1][0]=v[301];
8001 Amat[2][0][1][1]=v[307];
8002 Amat[2][0][1][2]=v[312];
8003 Amat[2][0][2][0]=2e0*F[2][0]*v[165]+F[2][2]*v[224]+F[2][1]*v[263]+v[297];
8004 Amat[2][0][2][1]=v[316];
8005 Amat[2][0][2][2]=v[317];
8006 Amat[2][1][0][0]=v[280];
8007 Amat[2][1][0][1]=v[288];
8008 Amat[2][1][0][2]=v[295];
8009 Amat[2][1][1][0]=v[302];
8010 Amat[2][1][1][1]=v[308];
8011 Amat[2][1][1][2]=v[313];
8012 Amat[2][1][2][0]=v[316];
8013 Amat[2][1][2][1]=2e0*F[2][1]*v[156]+F[2][2]*v[192]+F[2][0]*v[267]+v[304];
8014 Amat[2][1][2][2]=v[319];
8015 Amat[2][2][0][0]=v[281];
8016 Amat[2][2][0][1]=v[289];
8017 Amat[2][2][0][2]=v[296];
8018 Amat[2][2][1][0]=v[303];
8019 Amat[2][2][1][1]=v[309];
8020 Amat[2][2][1][2]=v[314];
8021 Amat[2][2][2][0]=v[317];
8022 Amat[2][2][2][1]=v[319];
8023 Amat[2][2][2][2]=2e0*F[2][2]*v[147]+F[2][1]*v[196]+F[2][0]*v[231]+v[310];
8024}
8025
8026
8027/*************************************************************
8028 * AceGen 6.921 MacOSX (29 Jan 19) *
8029 * Co. J. Korelc 2013 12 Feb 19 12:06:46 *
8030 **************************************************************
8031 User : Full professional version
8032 Notebook : mr3d_C
8033 Evaluation time : 7 s Mode : Optimal
8034 Number of formulae : 190 Method: Automatic
8035 Subroutine : mr3d size: 5215
8036 Total size of Mathematica code : 5215 subexpressions
8037 Total size of C code : 10798 bytes */
8038
8039/******************* S U B R O U T I N E *********************/
8040template <class SC, class LO, class GO, class NO>
8041void FE<SC,LO,GO,NO>::mr3d(double* v,double (*E),double (*Nu),double (*C)
8042 ,double** F,double** Pmat,double**** Amat)
8043{
8044 v[366]=2e0*F[0][2];
8045 v[364]=2e0*F[0][1];
8046 v[4]=(*E)/(2e0+2e0*(*Nu));
8047 v[139]=((*C)*v[4])/2e0;
8048 v[5]=(*E)/(3e0-6e0*(*Nu));
8049 v[57]=2e0*F[0][0];
8050 v[150]=v[139]*v[57];
8051 v[66]=2e0*F[0][1];
8052 v[165]=v[139]*v[66];
8053 v[87]=2e0*F[0][2];
8054 v[167]=v[139]*v[87];
8055 v[58]=2e0*F[1][0];
8056 v[155]=v[139]*v[58];
8057 v[67]=2e0*F[1][1];
8058 v[170]=v[139]*v[67];
8059 v[88]=2e0*F[1][2];
8060 v[172]=v[139]*v[88];
8061 v[59]=2e0*F[2][0];
8062 v[159]=v[139]*v[59];
8063 v[68]=2e0*F[2][1];
8064 v[175]=v[139]*v[68];
8065 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
8066 v[345]=(v[18]*v[18]);
8067 v[89]=2e0*F[2][2];
8068 v[177]=v[139]*v[89];
8069 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
8070 v[344]=(v[24]*v[24]);
8071 v[335]=v[18]*v[24];
8072 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
8073 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
8074 v[239]=-(F[2][1]*v[18]);
8075 v[236]=F[2][2]*v[18];
8076 v[228]=-(F[1][1]*v[18]);
8077 v[225]=F[1][2]*v[18];
8078 v[205]=-(F[2][0]*v[18]);
8079 v[196]=-(F[1][0]*v[18]);
8080 v[279]=F[2][1]*v[22];
8081 v[275]=-(F[2][2]*v[22]);
8082 v[266]=F[1][1]*v[22];
8083 v[262]=-(F[1][2]*v[22]);
8084 v[201]=-(F[2][0]*v[22]);
8085 v[192]=-(F[1][0]*v[22]);
8086 v[183]=-(F[0][0]*v[22]);
8087 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
8088 v[334]=-(v[20]*v[22]);
8089 v[337]=2e0*(v[334]+v[335]);
8090 v[95]=v[20]*v[89];
8091 v[93]=v[20]*v[88];
8092 v[91]=v[20]*v[87];
8093 v[140]=v[15]*v[20]-v[345];
8094 v[281]=F[2][0]*v[24];
8095 v[271]=-(F[2][2]*v[24]);
8096 v[268]=F[1][0]*v[24];
8097 v[258]=-(F[1][2]*v[24]);
8098 v[255]=F[0][0]*v[24];
8099 v[243]=-(F[0][2]*v[24]);
8100 v[233]=-(F[2][1]*v[24]);
8101 v[222]=-(F[1][1]*v[24]);
8102 v[209]=-(F[0][1]*v[24]);
8103 v[179]=v[18]*v[22]-v[15]*v[24];
8104 v[341]=2e0*v[179];
8105 v[339]=2e0*v[179];
8106 v[336]=2e0*v[179];
8107 v[38]=-(v[22]*v[22]);
8108 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
8109 v[343]=v[20]*v[26]-v[344];
8110 v[361]=v[343]*v[57];
8111 v[247]=v[22]*v[24]-v[18]*v[26];
8112 v[342]=2e0*v[247];
8113 v[340]=2e0*v[247];
8114 v[338]=2e0*v[247];
8115 v[100]=v[26]*v[59];
8116 v[98]=v[26]*v[58];
8117 v[94]=v[26]*v[68];
8118 v[92]=v[26]*v[67];
8119 v[90]=v[26]*v[66];
8120 v[151]=v[15]*v[26]+v[38];
8121 v[29]=v[151]*v[20]+2e0*v[22]*v[335]-v[15]*v[344]-v[26]*v[345];
8122 v[346]=1e0/Power(v[29],2);
8123 v[33]=-2e0*v[139]-v[4]+v[5]*std::log(std::sqrt(v[29]));
8124 v[347]=v[346]*(-v[33]/2e0+v[5]/4e0);
8125 v[138]=v[347]*(F[2][1]*v[336]+F[2][0]*v[337]-v[345]*v[89]+v[15]*v[95]);
8126 v[149]=v[138]*v[140];
8127 v[137]=v[347]*(F[2][2]*v[339]+F[2][0]*v[340]+v[38]*v[68]+v[15]*v[94]);
8128 v[161]=v[137]*v[151];
8129 v[136]=v[347]*(v[100]*v[20]+F[2][2]*v[337]+F[2][1]*v[338]-v[344]*v[59]);
8130 v[174]=v[136]*v[343];
8131 v[135]=v[347]*(F[1][1]*v[336]+F[1][0]*v[337]-v[345]*v[88]+v[15]*v[93]);
8132 v[146]=v[135]*v[140];
8133 v[134]=v[347]*(F[1][2]*v[341]+F[1][0]*v[342]+v[38]*v[67]+v[15]*v[92]);
8134 v[157]=v[134]*v[151];
8135 v[133]=v[347]*(F[1][2]*v[337]+F[1][1]*v[338]-v[344]*v[58]+v[20]*v[98]);
8136 v[169]=v[133]*v[343];
8137 v[132]=v[347]*(F[0][0]*v[337]+F[0][1]*v[339]-v[345]*v[87]+v[15]*v[91]);
8138 v[131]=v[347]*(F[0][2]*v[341]+F[0][0]*v[342]+v[38]*v[66]+v[15]*v[90]);
8139 v[129]=v[347]*(F[0][2]*v[337]+F[0][1]*v[340]+v[361]);
8140 v[37]=v[33]/(2e0*v[29]);
8141 v[365]=v[37]*(2e0*v[183]+v[15]*v[87]);
8142 v[363]=v[37]*(2e0*v[243]+v[90]);
8143 v[362]=v[37]*(2e0*v[209]+v[91]);
8144 v[359]=-2e0*(F[1][0]*v[20]+v[228])*v[37];
8145 v[358]=-(v[37]*(2e0*v[196]+v[15]*v[67]));
8146 v[357]=-2e0*(F[2][0]*v[20]+v[239])*v[37];
8147 v[356]=-(v[37]*(2e0*v[205]+v[15]*v[68]));
8148 v[355]=-(v[37]*(2e0*v[262]+v[98]));
8149 v[354]=-(v[37]*(2e0*v[192]+v[15]*v[88]));
8150 v[353]=-((v[100]+2e0*v[275])*v[37]);
8151 v[352]=-(v[37]*(2e0*v[201]+v[15]*v[89]));
8152 v[351]=-(v[37]*(2e0*v[258]+v[92]));
8153 v[350]=-(v[37]*(2e0*v[222]+v[93]));
8154 v[349]=-(v[37]*(2e0*v[271]+v[94]));
8155 v[348]=-(v[37]*(2e0*v[233]+v[95]));
8156 v[283]=v[138]*v[338]+v[37]*(2e0*v[279]+2e0*v[281]-2e0*v[18]*v[89]);
8157 v[278]=-v[159]+v[137]*v[338]+v[353];
8158 v[274]=-v[175]+v[136]*v[338]+v[349];
8159 v[270]=v[135]*v[338]+v[37]*(2e0*v[266]+2e0*v[268]-2e0*v[18]*v[88]);
8160 v[265]=-v[155]+v[134]*v[338]+v[355];
8161 v[261]=-v[170]+v[133]*v[338]+v[351];
8162 v[257]=v[132]*v[338]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[255]-2e0*v[18]*v[87]);
8163 v[252]=-v[150]+v[131]*v[338]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
8164 v[242]=-v[159]+v[138]*v[337]+v[357];
8165 v[238]=v[137]*v[337]+v[37]*(2e0*v[236]+2e0*v[281]-2e0*v[22]*v[68]);
8166 v[235]=-v[177]+v[136]*v[337]+v[348];
8167 v[312]=2e0*F[1][0]*v[174]+F[1][2]*v[235]+F[1][1]*v[274];
8168 v[290]=2e0*F[0][0]*v[174]+F[0][2]*v[235]+F[0][1]*v[274];
8169 v[231]=-v[155]+v[135]*v[337]+v[359];
8170 v[227]=v[134]*v[337]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[22]*v[67]);
8171 v[224]=-v[172]+v[133]*v[337]+v[350];
8172 v[287]=2e0*F[0][0]*v[169]+F[0][2]*v[224]+F[0][1]*v[261];
8173 v[220]=-v[150]+v[132]*v[337]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
8174 v[207]=-v[175]+v[138]*v[336]+v[356];
8175 v[325]=2e0*F[1][2]*v[149]+F[1][1]*v[207]+F[1][0]*v[242];
8176 v[307]=2e0*F[0][2]*v[149]+F[0][1]*v[207]+F[0][0]*v[242];
8177 v[203]=-v[177]+v[137]*v[336]+v[352];
8178 v[319]=2e0*F[1][1]*v[161]+F[1][2]*v[203]+F[1][0]*v[278];
8179 v[299]=2e0*F[0][1]*v[161]+F[0][2]*v[203]+F[0][0]*v[278];
8180 v[199]=v[136]*v[336]+v[37]*(2e0*v[236]+2e0*v[279]-2e0*v[24]*v[59]);
8181 v[198]=-v[170]+v[135]*v[336]+v[358];
8182 v[304]=2e0*F[0][2]*v[146]+F[0][1]*v[198]+F[0][0]*v[231];
8183 v[194]=-v[172]+v[134]*v[336]+v[354];
8184 v[296]=2e0*F[0][1]*v[157]+F[0][2]*v[194]+F[0][0]*v[265];
8185 v[190]=v[133]*v[336]+v[37]*(2e0*v[225]+2e0*v[266]-2e0*v[24]*v[58]);
8186 v[189]=-v[165]+v[132]*v[336]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
8187 v[178]=v[177]+v[138]*v[343]-v[348];
8188 v[314]=2e0*F[1][0]*v[178]+F[1][2]*v[242]+F[1][1]*v[283];
8189 v[292]=2e0*F[0][0]*v[178]+F[0][2]*v[242]+F[0][1]*v[283];
8190 v[176]=v[175]+v[137]*v[343]-v[349];
8191 v[313]=2e0*F[1][0]*v[176]+F[1][2]*v[238]+F[1][1]*v[278];
8192 v[291]=2e0*F[0][0]*v[176]+F[0][2]*v[238]+F[0][1]*v[278];
8193 v[173]=v[172]+v[135]*v[343]-v[350];
8194 v[289]=2e0*F[0][0]*v[173]+F[0][2]*v[231]+F[0][1]*v[270];
8195 v[171]=v[170]+v[134]*v[343]-v[351];
8196 v[288]=2e0*F[0][0]*v[171]+F[0][2]*v[227]+F[0][1]*v[265];
8197 v[162]=v[138]*v[151]+v[177]-v[352];
8198 v[320]=2e0*F[1][1]*v[162]+F[1][2]*v[207]+F[1][0]*v[283];
8199 v[300]=2e0*F[0][1]*v[162]+F[0][2]*v[207]+F[0][0]*v[283];
8200 v[160]=v[136]*v[151]+v[159]-v[353];
8201 v[318]=2e0*F[1][1]*v[160]+F[1][2]*v[199]+F[1][0]*v[274];
8202 v[298]=2e0*F[0][1]*v[160]+F[0][2]*v[199]+F[0][0]*v[274];
8203 v[158]=v[135]*v[151]+v[172]-v[354];
8204 v[297]=2e0*F[0][1]*v[158]+F[0][2]*v[198]+F[0][0]*v[270];
8205 v[295]=F[0][2]*v[190]+F[0][0]*v[261]+2e0*F[0][1]*(v[133]*v[151]+v[155]-v[355]);
8206 v[148]=v[137]*v[140]+v[175]-v[356];
8207 v[324]=2e0*F[1][2]*v[148]+F[1][1]*v[203]+F[1][0]*v[238];
8208 v[306]=2e0*F[0][2]*v[148]+F[0][1]*v[203]+F[0][0]*v[238];
8209 v[147]=v[136]*v[140]+v[159]-v[357];
8210 v[323]=2e0*F[1][2]*v[147]+F[1][1]*v[199]+F[1][0]*v[235];
8211 v[305]=2e0*F[0][2]*v[147]+F[0][1]*v[199]+F[0][0]*v[235];
8212 v[303]=F[0][1]*v[194]+F[0][0]*v[227]+2e0*F[0][2]*(v[134]*v[140]+v[170]-v[358]);
8213 v[302]=F[0][1]*v[190]+F[0][0]*v[224]+(v[133]*v[140]+v[155]-v[359])*v[366];
8214 v[36]=v[140]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[20]))*v[4])/2e0;
8215 v[321]=2e0*v[36];
8216 v[40]=v[151]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[26]))*v[4])/2e0;
8217 v[315]=2e0*v[40];
8218 v[43]=v[343]*v[37]+((1e0+(*C)*(-1e0+v[20]+v[26]))*v[4])/2e0;
8219 v[308]=2e0*v[43];
8220 v[45]=-2e0*v[139]*v[24]+v[336]*v[37];
8221 v[330]=2e0*F[2][1]*v[162]+F[2][2]*v[207]+F[2][0]*v[283]+v[45];
8222 v[317]=2e0*F[1][1]*v[158]+F[1][2]*v[198]+F[1][0]*v[270]+v[45];
8223 v[294]=F[0][2]*v[189]+F[0][0]*v[257]+v[364]*(v[132]*v[151]+v[167]+v[365])+v[45];
8224 v[46]=-2e0*v[139]*v[22]+v[337]*v[37];
8225 v[328]=2e0*F[2][0]*v[178]+F[2][2]*v[242]+F[2][1]*v[283]+v[46];
8226 v[311]=2e0*F[1][0]*v[173]+F[1][2]*v[231]+F[1][1]*v[270]+v[46];
8227 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];
8228 v[47]=-2e0*v[139]*v[18]+v[338]*v[37];
8229 v[327]=2e0*F[2][0]*v[176]+F[2][2]*v[238]+F[2][1]*v[278]+v[47];
8230 v[310]=2e0*F[1][0]*v[171]+F[1][2]*v[227]+F[1][1]*v[265]+v[47];
8231 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]*
8232 (2e0*F[0][2]*v[18]+2e0*v[255]-2e0*v[22]*v[66]));
8233 Pmat[0][0]=F[0][0]*v[308]+F[0][2]*v[46]+F[0][1]*v[47];
8234 Pmat[0][1]=F[0][1]*v[315]+F[0][2]*v[45]+F[0][0]*v[47];
8235 Pmat[0][2]=F[0][2]*v[321]+F[0][1]*v[45]+F[0][0]*v[46];
8236 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[46]+F[1][1]*v[47];
8237 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[45]+F[1][0]*v[47];
8238 Pmat[1][2]=2e0*F[1][2]*v[36]+F[1][1]*v[45]+F[1][0]*v[46];
8239 Pmat[2][0]=F[2][0]*v[308]+F[2][2]*v[46]+F[2][1]*v[47];
8240 Pmat[2][1]=F[2][1]*v[315]+F[2][2]*v[45]+F[2][0]*v[47];
8241 Pmat[2][2]=F[2][2]*v[321]+F[2][1]*v[45]+F[2][0]*v[46];
8242 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]
8243 +v[129]*v[338]-v[363]);
8244 Amat[0][0][0][1]=v[285];
8245 Amat[0][0][0][2]=v[286];
8246 Amat[0][0][1][0]=v[287];
8247 Amat[0][0][1][1]=v[288];
8248 Amat[0][0][1][2]=v[289];
8249 Amat[0][0][2][0]=v[290];
8250 Amat[0][0][2][1]=v[291];
8251 Amat[0][0][2][2]=v[292];
8252 Amat[0][1][0][0]=v[285];
8253 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]);
8254 Amat[0][1][0][2]=v[294];
8255 Amat[0][1][1][0]=v[295];
8256 Amat[0][1][1][1]=v[296];
8257 Amat[0][1][1][2]=v[297];
8258 Amat[0][1][2][0]=v[298];
8259 Amat[0][1][2][1]=v[299];
8260 Amat[0][1][2][2]=v[300];
8261 Amat[0][2][0][0]=v[286];
8262 Amat[0][2][0][1]=v[294];
8263 Amat[0][2][0][2]=F[0][1]*v[189]+F[0][0]*v[220]+v[321]+v[132]*v[140]*v[366];
8264 Amat[0][2][1][0]=v[302];
8265 Amat[0][2][1][1]=v[303];
8266 Amat[0][2][1][2]=v[304];
8267 Amat[0][2][2][0]=v[305];
8268 Amat[0][2][2][1]=v[306];
8269 Amat[0][2][2][2]=v[307];
8270 Amat[1][0][0][0]=v[287];
8271 Amat[1][0][0][1]=v[295];
8272 Amat[1][0][0][2]=v[302];
8273 Amat[1][0][1][0]=2e0*F[1][0]*v[169]+F[1][2]*v[224]+F[1][1]*v[261]+v[308];
8274 Amat[1][0][1][1]=v[310];
8275 Amat[1][0][1][2]=v[311];
8276 Amat[1][0][2][0]=v[312];
8277 Amat[1][0][2][1]=v[313];
8278 Amat[1][0][2][2]=v[314];
8279 Amat[1][1][0][0]=v[288];
8280 Amat[1][1][0][1]=v[296];
8281 Amat[1][1][0][2]=v[303];
8282 Amat[1][1][1][0]=v[310];
8283 Amat[1][1][1][1]=2e0*F[1][1]*v[157]+F[1][2]*v[194]+F[1][0]*v[265]+v[315];
8284 Amat[1][1][1][2]=v[317];
8285 Amat[1][1][2][0]=v[318];
8286 Amat[1][1][2][1]=v[319];
8287 Amat[1][1][2][2]=v[320];
8288 Amat[1][2][0][0]=v[289];
8289 Amat[1][2][0][1]=v[297];
8290 Amat[1][2][0][2]=v[304];
8291 Amat[1][2][1][0]=v[311];
8292 Amat[1][2][1][1]=v[317];
8293 Amat[1][2][1][2]=2e0*F[1][2]*v[146]+F[1][1]*v[198]+F[1][0]*v[231]+v[321];
8294 Amat[1][2][2][0]=v[323];
8295 Amat[1][2][2][1]=v[324];
8296 Amat[1][2][2][2]=v[325];
8297 Amat[2][0][0][0]=v[290];
8298 Amat[2][0][0][1]=v[298];
8299 Amat[2][0][0][2]=v[305];
8300 Amat[2][0][1][0]=v[312];
8301 Amat[2][0][1][1]=v[318];
8302 Amat[2][0][1][2]=v[323];
8303 Amat[2][0][2][0]=2e0*F[2][0]*v[174]+F[2][2]*v[235]+F[2][1]*v[274]+v[308];
8304 Amat[2][0][2][1]=v[327];
8305 Amat[2][0][2][2]=v[328];
8306 Amat[2][1][0][0]=v[291];
8307 Amat[2][1][0][1]=v[299];
8308 Amat[2][1][0][2]=v[306];
8309 Amat[2][1][1][0]=v[313];
8310 Amat[2][1][1][1]=v[319];
8311 Amat[2][1][1][2]=v[324];
8312 Amat[2][1][2][0]=v[327];
8313 Amat[2][1][2][1]=2e0*F[2][1]*v[161]+F[2][2]*v[203]+F[2][0]*v[278]+v[315];
8314 Amat[2][1][2][2]=v[330];
8315 Amat[2][2][0][0]=v[292];
8316 Amat[2][2][0][1]=v[300];
8317 Amat[2][2][0][2]=v[307];
8318 Amat[2][2][1][0]=v[314];
8319 Amat[2][2][1][1]=v[320];
8320 Amat[2][2][1][2]=v[325];
8321 Amat[2][2][2][0]=v[328];
8322 Amat[2][2][2][1]=v[330];
8323 Amat[2][2][2][2]=2e0*F[2][2]*v[149]+F[2][1]*v[207]+F[2][0]*v[242]+v[321];
8324};
8325
8326
8327/*************************************************************
8328 * AceGen 6.921 MacOSX (29 Jan 19) *
8329 * Co. J. Korelc 2013 17 Jul 19 15:09:55 *
8330 **************************************************************
8331 User : Full professional version
8332 Notebook : st_venant_kirchhoff_3d
8333 Evaluation time : 3 s Mode : Optimal
8334 Number of formulae : 91 Method: Automatic
8335 Subroutine : stvk3d size: 2846
8336 Total size of Mathematica code : 2846 subexpressions
8337 Total size of C code : 5830 bytes */
8338
8339/******************* S U B R O U T I N E *********************/
8340template <class SC, class LO, class GO, class NO>
8341void FE<SC,LO,GO,NO>::stvk3d(double* v,double (*lam),double (*mue),double** F
8342 ,double** Pmat,double**** Amat)
8343{
8344 v[169]=Power(F[0][0],2);
8345 v[168]=2e0*(*mue);
8346 v[167]=Power(F[0][2],2);
8347 v[166]=F[2][2]*(*mue);
8348 v[165]=F[2][1]*(*mue);
8349 v[164]=F[2][0]*(*mue);
8350 v[163]=F[1][2]*(*mue);
8351 v[162]=F[1][1]*(*mue);
8352 v[161]=F[1][0]*(*mue);
8353 v[88]=F[0][0]*(*mue);
8354 v[116]=F[0][0]*v[88];
8355 v[70]=F[0][1]*(*lam);
8356 v[93]=F[0][1]*(*mue);
8357 v[117]=F[0][1]*v[93];
8358 v[71]=F[0][2]*(*lam);
8359 v[105]=(*mue)*v[167];
8360 v[72]=F[1][0]*(*lam);
8361 v[85]=2e0*v[161]+v[72];
8362 v[142]=F[1][0]*v[161];
8363 v[121]=F[0][0]*v[161];
8364 v[73]=F[1][1]*(*lam);
8365 v[100]=F[0][1]*v[161]+F[0][0]*v[73];
8366 v[82]=2e0*v[162]+v[73];
8367 v[143]=F[1][1]*v[162];
8368 v[122]=F[0][1]*v[162];
8369 v[108]=F[0][0]*v[162]+F[0][1]*v[72];
8370 v[74]=F[1][2]*(*lam);
8371 v[111]=F[0][2]*v[162]+F[0][1]*v[74];
8372 v[101]=F[0][2]*v[161]+F[0][0]*v[74];
8373 v[79]=2e0*v[163]+v[74];
8374 v[123]=v[121]+v[122]+F[0][2]*v[79];
8375 v[135]=F[1][2]*v[163];
8376 v[120]=F[0][1]*v[163]+F[0][2]*v[73];
8377 v[119]=F[0][0]*v[163]+F[0][2]*v[72];
8378 v[109]=F[0][2]*v[163];
8379 v[110]=v[109]+v[121]+F[0][1]*v[82];
8380 v[99]=v[109]+v[122]+F[0][0]*v[85];
8381 v[75]=F[2][0]*(*lam);
8382 v[86]=2e0*v[164]+v[75];
8383 v[156]=F[2][0]*v[164];
8384 v[147]=F[1][0]*v[164];
8385 v[126]=F[0][0]*v[164];
8386 v[76]=F[2][1]*(*lam);
8387 v[133]=F[1][1]*v[164]+F[1][0]*v[76];
8388 v[103]=F[0][1]*v[164]+F[0][0]*v[76];
8389 v[83]=2e0*v[165]+v[76];
8390 v[157]=F[2][1]*v[165];
8391 v[148]=F[1][1]*v[165];
8392 v[138]=F[1][0]*v[165]+F[1][1]*v[75];
8393 v[127]=F[0][1]*v[165];
8394 v[112]=F[0][0]*v[165]+F[0][1]*v[75];
8395 v[77]=F[2][2]*(*lam);
8396 v[141]=F[1][2]*v[165]+F[1][1]*v[77];
8397 v[134]=F[1][2]*v[164]+F[1][0]*v[77];
8398 v[115]=F[0][2]*v[165]+F[0][1]*v[77];
8399 v[104]=F[0][2]*v[164]+F[0][0]*v[77];
8400 v[80]=2e0*v[166]+v[77];
8401 v[149]=v[147]+v[148]+F[1][2]*v[80];
8402 v[128]=v[126]+v[127]+F[0][2]*v[80];
8403 v[153]=F[2][2]*v[166];
8404 v[146]=F[1][1]*v[166]+F[1][2]*v[76];
8405 v[145]=F[1][0]*v[166]+F[1][2]*v[75];
8406 v[139]=F[1][2]*v[166];
8407 v[140]=v[139]+v[147]+F[1][1]*v[83];
8408 v[132]=v[139]+v[148]+F[1][0]*v[86];
8409 v[125]=F[0][1]*v[166]+F[0][2]*v[76];
8410 v[124]=F[0][0]*v[166]+F[0][2]*v[75];
8411 v[113]=F[0][2]*v[166];
8412 v[114]=v[113]+v[126]+F[0][1]*v[83];
8413 v[102]=v[113]+v[127]+F[0][0]*v[86];
8414 v[24]=(-1e0+Power(F[1][0],2)+Power(F[2][0],2)+v[169])/2e0;
8415 v[28]=(-1e0+Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2))/2e0;
8416 v[32]=(-1e0+Power(F[1][2],2)+Power(F[2][2],2)+v[167])/2e0;
8417 v[36]=(*lam)*(v[24]+v[28]+v[32]);
8418 v[35]=2e0*(*mue)*v[32]+v[36];
8419 v[37]=2e0*(*mue)*v[28]+v[36];
8420 v[38]=2e0*(*mue)*v[24]+v[36];
8421 v[39]=(F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2])*(*mue);
8422 v[152]=F[2][2]*v[164]+v[39]+F[2][0]*v[77];
8423 v[131]=F[1][2]*v[161]+v[39]+F[1][0]*v[74];
8424 v[98]=v[39]+F[0][0]*v[71]+F[0][2]*v[88];
8425 v[40]=(F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2])*(*mue);
8426 v[155]=F[2][2]*v[165]+v[40]+F[2][1]*v[77];
8427 v[137]=F[1][2]*v[162]+v[40]+F[1][1]*v[74];
8428 v[107]=v[40]+F[0][1]*v[71]+F[0][2]*v[93];
8429 v[41]=(F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1])*(*mue);
8430 v[151]=F[2][1]*v[164]+v[41]+F[2][0]*v[76];
8431 v[130]=F[1][1]*v[161]+v[41]+F[1][0]*v[73];
8432 v[97]=v[41]+F[0][0]*v[70]+F[0][1]*v[88];
8433 Pmat[0][0]=F[0][0]*v[38]+F[0][2]*v[39]+F[0][1]*v[41];
8434 Pmat[0][1]=F[0][1]*v[37]+F[0][2]*v[40]+F[0][0]*v[41];
8435 Pmat[0][2]=F[0][2]*v[35]+F[0][0]*v[39]+F[0][1]*v[40];
8436 Pmat[1][0]=F[1][0]*v[38]+F[1][2]*v[39]+F[1][1]*v[41];
8437 Pmat[1][1]=F[1][1]*v[37]+F[1][2]*v[40]+F[1][0]*v[41];
8438 Pmat[1][2]=F[1][2]*v[35]+F[1][0]*v[39]+F[1][1]*v[40];
8439 Pmat[2][0]=F[2][0]*v[38]+F[2][2]*v[39]+F[2][1]*v[41];
8440 Pmat[2][1]=F[2][1]*v[37]+F[2][2]*v[40]+F[2][0]*v[41];
8441 Pmat[2][2]=F[2][2]*v[35]+F[2][0]*v[39]+F[2][1]*v[40];
8442 Amat[0][0][0][0]=v[105]+v[117]+((*lam)+v[168])*v[169]+v[38];
8443 Amat[0][0][0][1]=v[97];
8444 Amat[0][0][0][2]=v[98];
8445 Amat[0][0][1][0]=v[99];
8446 Amat[0][0][1][1]=v[100];
8447 Amat[0][0][1][2]=v[101];
8448 Amat[0][0][2][0]=v[102];
8449 Amat[0][0][2][1]=v[103];
8450 Amat[0][0][2][2]=v[104];
8451 Amat[0][1][0][0]=v[97];
8452 Amat[0][1][0][1]=v[105]+v[116]+v[37]+F[0][1]*(v[70]+2e0*v[93]);
8453 Amat[0][1][0][2]=v[107];
8454 Amat[0][1][1][0]=v[108];
8455 Amat[0][1][1][1]=v[110];
8456 Amat[0][1][1][2]=v[111];
8457 Amat[0][1][2][0]=v[112];
8458 Amat[0][1][2][1]=v[114];
8459 Amat[0][1][2][2]=v[115];
8460 Amat[0][2][0][0]=v[98];
8461 Amat[0][2][0][1]=v[107];
8462 Amat[0][2][0][2]=v[116]+v[117]+v[35]+F[0][2]*(F[0][2]*v[168]+v[71]);
8463 Amat[0][2][1][0]=v[119];
8464 Amat[0][2][1][1]=v[120];
8465 Amat[0][2][1][2]=v[123];
8466 Amat[0][2][2][0]=v[124];
8467 Amat[0][2][2][1]=v[125];
8468 Amat[0][2][2][2]=v[128];
8469 Amat[1][0][0][0]=v[99];
8470 Amat[1][0][0][1]=v[108];
8471 Amat[1][0][0][2]=v[119];
8472 Amat[1][0][1][0]=v[135]+v[143]+v[38]+F[1][0]*v[85];
8473 Amat[1][0][1][1]=v[130];
8474 Amat[1][0][1][2]=v[131];
8475 Amat[1][0][2][0]=v[132];
8476 Amat[1][0][2][1]=v[133];
8477 Amat[1][0][2][2]=v[134];
8478 Amat[1][1][0][0]=v[100];
8479 Amat[1][1][0][1]=v[110];
8480 Amat[1][1][0][2]=v[120];
8481 Amat[1][1][1][0]=v[130];
8482 Amat[1][1][1][1]=v[135]+v[142]+v[37]+F[1][1]*v[82];
8483 Amat[1][1][1][2]=v[137];
8484 Amat[1][1][2][0]=v[138];
8485 Amat[1][1][2][1]=v[140];
8486 Amat[1][1][2][2]=v[141];
8487 Amat[1][2][0][0]=v[101];
8488 Amat[1][2][0][1]=v[111];
8489 Amat[1][2][0][2]=v[123];
8490 Amat[1][2][1][0]=v[131];
8491 Amat[1][2][1][1]=v[137];
8492 Amat[1][2][1][2]=v[142]+v[143]+v[35]+F[1][2]*v[79];
8493 Amat[1][2][2][0]=v[145];
8494 Amat[1][2][2][1]=v[146];
8495 Amat[1][2][2][2]=v[149];
8496 Amat[2][0][0][0]=v[102];
8497 Amat[2][0][0][1]=v[112];
8498 Amat[2][0][0][2]=v[124];
8499 Amat[2][0][1][0]=v[132];
8500 Amat[2][0][1][1]=v[138];
8501 Amat[2][0][1][2]=v[145];
8502 Amat[2][0][2][0]=v[153]+v[157]+v[38]+F[2][0]*v[86];
8503 Amat[2][0][2][1]=v[151];
8504 Amat[2][0][2][2]=v[152];
8505 Amat[2][1][0][0]=v[103];
8506 Amat[2][1][0][1]=v[114];
8507 Amat[2][1][0][2]=v[125];
8508 Amat[2][1][1][0]=v[133];
8509 Amat[2][1][1][1]=v[140];
8510 Amat[2][1][1][2]=v[146];
8511 Amat[2][1][2][0]=v[151];
8512 Amat[2][1][2][1]=v[153]+v[156]+v[37]+F[2][1]*v[83];
8513 Amat[2][1][2][2]=v[155];
8514 Amat[2][2][0][0]=v[104];
8515 Amat[2][2][0][1]=v[115];
8516 Amat[2][2][0][2]=v[128];
8517 Amat[2][2][1][0]=v[134];
8518 Amat[2][2][1][1]=v[141];
8519 Amat[2][2][1][2]=v[149];
8520 Amat[2][2][2][0]=v[152];
8521 Amat[2][2][2][1]=v[155];
8522 Amat[2][2][2][2]=v[156]+v[157]+v[35]+F[2][2]*v[80];
8523};
8524/*************************************************************
8525 * AceGen 6.921 MacOSX (29 Jan 19) *
8526 * Co. J. Korelc 2013 17 Jul 19 16:01:42 *
8527 **************************************************************
8528 User : Full professional version
8529 Notebook : st_venant_kirchhoff_2d
8530 Evaluation time : 1 s Mode : Optimal
8531 Number of formulae : 25 Method: Automatic
8532 Subroutine : stvk2d size: 772
8533 Total size of Mathematica code : 772 subexpressions
8534 Total size of C code : 1672 bytes */
8535
8536
8537/******************* S U B R O U T I N E *********************/
8538template <class SC, class LO, class GO, class NO>
8539void FE<SC,LO,GO,NO>::stvk2d(double* v, double (*lam),double (*mue),double** F
8540 ,double** Pmat,double**** Amat)
8541{
8542 v[43]=F[0][0]*F[1][0];
8543 v[42]=F[0][1]*F[1][1];
8544 v[37]=Power(F[0][0],2);
8545 v[12]=F[0][0]/2e0;
8546 v[36]=Power(F[0][1],2);
8547 v[34]=F[0][0]*F[0][1];
8548 v[11]=F[0][1]/2e0;
8549 v[27]=Power(F[1][0],2);
8550 v[31]=-1e0+v[27]+v[37];
8551 v[14]=F[1][0]/2e0;
8552 v[25]=Power(F[1][1],2);
8553 v[26]=-1e0+v[25]+v[36];
8554 v[23]=F[1][0]*F[1][1];
8555 v[22]=v[23]+v[34];
8556 v[35]=(*lam)*v[34]+(*mue)*(v[22]+v[34]);
8557 v[24]=(*lam)*v[23]+(*mue)*(v[22]+v[23]);
8558 v[21]=(*lam)*v[42]+2e0*(*mue)*(2e0*v[12]*v[14]+v[42]);
8559 v[20]=F[0][0]*F[1][1]*(*lam)+4e0*(*mue)*v[11]*v[14];
8560 v[13]=F[1][1]/2e0;
8561 v[30]=F[0][1]*F[1][0]*(*lam)+4e0*(*mue)*v[12]*v[13];
8562 v[29]=(*lam)*v[43]+2e0*(*mue)*(2e0*v[11]*v[13]+v[43]);
8563 v[44]=2e0*v[22];
8564 v[32]=((*lam)*(v[26]+v[31]))/2e0;
8565 Pmat[0][0]=F[0][0]*v[32]+(*mue)*(F[0][0]*v[31]+v[11]*v[44]);
8566 Pmat[0][1]=F[0][1]*v[32]+(*mue)*(F[0][1]*v[26]+v[12]*v[44]);
8567 Pmat[1][0]=F[1][0]*v[32]+(*mue)*(F[1][0]*v[31]+v[13]*v[44]);
8568 Pmat[1][1]=F[1][1]*v[32]+(*mue)*(F[1][1]*v[26]+v[14]*v[44]);
8569 Amat[0][0][0][0]=v[32]+(*lam)*v[37]+(*mue)*(v[31]+v[36]+2e0*v[37]);
8570 Amat[0][0][0][1]=v[35];
8571 Amat[0][0][1][0]=v[29];
8572 Amat[0][0][1][1]=v[20];
8573 Amat[0][1][0][0]=v[35];
8574 Amat[0][1][0][1]=v[32]+(*lam)*v[36]+(*mue)*(v[26]+2e0*v[36]+v[37]);
8575 Amat[0][1][1][0]=v[30];
8576 Amat[0][1][1][1]=v[21];
8577 Amat[1][0][0][0]=v[29];
8578 Amat[1][0][0][1]=v[30];
8579 Amat[1][0][1][0]=(*lam)*v[27]+(*mue)*(v[25]+2e0*v[27]+v[31])+v[32];
8580 Amat[1][0][1][1]=v[24];
8581 Amat[1][1][0][0]=v[20];
8582 Amat[1][1][0][1]=v[21];
8583 Amat[1][1][1][0]=v[24];
8584 Amat[1][1][1][1]=(*lam)*v[25]+(*mue)*(2e0*v[25]+v[26]+v[27])+v[32];
8585};
8586
8587}
8588#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:7011
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:3881
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:3968
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:4457
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:4192
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:4098
void assemblyPressureMeanValue(int dim, std::string FEType, MatrixPtr_Type a, MatrixPtr_Type aT)
Assembling Pressure Integral to determine pressure mean value.
Definition FE_def.hpp:7475
void assemblyLaplaceXDim(int dim, std::string FEType, MatrixPtr_Type &A, CoeffFuncDbl_Type func, double *parameters, bool callFillComplete=true)
Definition FE_def.hpp:4275
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:3696
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:3790
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:1252
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:5147
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:2735
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:5459
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:1863
void assemblyLinElasXDim(int dim, std::string FEType, MatrixPtr_Type &A, double lambda, double mu, bool callFillComplete=true)
Definition FE_def.hpp:4791
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
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:22
Adaptive Mesh Refinement.
Definition AdaptiveMeshRefinement_decl.hpp:33