Finite Element Domain Decomposition Library
FEDDLib
Loading...
Searching...
No Matches
FE_def.hpp
1#ifndef FE_DEF_hpp
2#define FE_DEF_hpp
3
4#include <string>
5#include "feddlib/core/core_config.h"
6#ifdef FEDD_HAVE_ACEGENINTERFACE
7#include <aceinterface.hpp>
8#endif
9
10#include "FE_decl.hpp"
11
20
21
22int MMAInitialisationCode[]={
23 0,0
24};
25
26
27using Teuchos::reduceAll;
28using Teuchos::REDUCE_SUM;
29using Teuchos::outArg;
30
31namespace FEDD {
32DataElement::DataElement():
33ht_(1,0.),
34hp_(1,0.)
35{
36
37}
38
39DataElement::DataElement(int size):
40ht_(size,0.),
41hp_(size,0.)
42{
43
44}
45
46std::vector<double> DataElement::getHp()
47{
48 return hp_;
49}
50
51std::vector<double> DataElement::getHt()
52{
53 return ht_;
54}
55
56void DataElement::setHp( double* ht )
57{
58 for (int i=0; i<hp_.size(); i++)
59 hp_[i] = ht[i];
60}
61
62
63template <class SC, class LO, class GO, class NO>
64FE<SC,LO,GO,NO>::FE(bool saveAssembly):
65domainVec_(0),
66es_(),
67setZeros_(false),
68myeps_(),
69ed_(0),
70saveAssembly_(saveAssembly)
71{
72}
73
74template <class SC, class LO, class GO, class NO>
75void FE<SC,LO,GO,NO>::addFE(DomainConstPtr_Type domain){
76
77 if (saveAssembly_){
78 DomainPtr_Type domainNC = Teuchos::rcp_const_cast<Domain_Type>( domain );
79 domainNC->initializeFEData();
80 }
81 domainVec_.push_back(domain);
82
83}
84
85template <class SC, class LO, class GO, class NO>
86void FE<SC,LO,GO,NO>::doSetZeros(double eps){
87
88 setZeros_ = true;
89 myeps_ = eps;
90
91}
92
93template <class SC, class LO, class GO, class NO>
94void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
95 vec3D_dbl_Type& dPhiOut,
96 SmallMatrix<SC>& Binv){
97 UN dim = Binv.size();
98 for (UN w=0; w<dPhiIn->size(); w++){
99 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
100 for (UN d1=0; d1<dim; d1++) {
101 for (UN d2=0; d2<dim; d2++) {
102 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
103 }
104 }
105 }
106 }
107}
108
120
121// Check the order of chemistry and solid in system matrix
122/*template <class SC, class LO, class GO, class NO>
123void FE<SC,LO,GO,NO>::globalAssembly(std::string ProblemType,
124 int dim,
125 int degree,
126 MultiVectorPtr_Type sol_rep,
127 BlockMatrixPtr_Type &A,
128 BlockMultiVectorPtr_Type &resVec,
129 ParameterListPtr_Type params,
130 std::string assembleMode,
131 bool callFillComplete,
132 int FELocExternal){
133
134 int problemSize = domainVec_.size(); // Problem size, as in number of subproblems
135
136 // Depending on problem size we extract necessary information
137
138 /// Tupel construction follows follwing pattern:
139 /// std::string: Physical Entity (i.e. Velocity) , std::string: Discretisation (i.e. "P2"), int: Degrees of Freedom per Node, int: Number of Nodes per element)
140 int numChem=3;
141 if(FETypeChem == "P2"){
142 numChem=6;
143 }
144 if(dim==3){
145 numChem=4;
146 if(FETypeChem == "P2")
147 numChem=10;
148 }
149 int numSolid=3;
150 if(FETypeSolid == "P2")
151 numSolid=6;
152
153 if(dim==3){
154 numSolid=4;
155 if(FETypeSolid == "P2")
156 numSolid=10;
157 }
158
159 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 2) );
160
161 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
162 for(int i=0; i< problemSize; i++){
163 int numNodes=0.;
164 if(domainVec.at(i)->getFEType() == "P2"){
165 numNodes=6;
166 }
167 if(dim==3){
168 numNodes=4;
169 if(domainVec.at(i)->getFEType() == "P2")
170 numNodes=10;
171 }
172 tuple_ssii_Type infoTuple (domainVec.at(i)->getPhysic(),domainVec.at(i)->getFEType(),domainVec.at(i)->getDofs(),numChem);
173 problemDisk->push_back(infoTuple);
174
175 MultiVectorPtr_Type resVec;
176 if(domainVec.at(i)->getDofs() == 1)
177 resVec = Teuchos::rcp( new MultiVector_Type( domainVec_.at(i)->getMapRepeated(), 1 ) );
178 else
179 resVec = Teuchos::rcp( new MultiVector_Type( domainVec_.at(i)->getMapVecFieldRepeated(), 1 ) );
180
181 resVecRep->addBlock(resVec,i);
182
183
184 }
185
186
187 if(assemblyFEElements_.size()== 0){
188 initAssembleFEElements(ProblemType,problemDisk,domainVec_.at(0)->getElementsC(), params,domainVec_.at(0)->getPointsRepeated(),domainVec_.at(0)->getElementMap());
189 }
190 else if(assemblyFEElements_.size() != domainVec_.at(0)->getElementsC()->numberElements())
191 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
192
193 vec_dbl_Type solution_tmp;
194 for (UN T=0; T<assemblyFEElements_.size(); T++) {
195 vec_dbl_Type solution(0);
196 vec_FE_Type elements;
197 for(int i=0; i< problemSize; i++){
198 solution_tmp = getSolution(domainVec_.at(i)->getElementsC()->getElement(T).getVectorNodeList(), sol_rep->getBlock(i),domainVec.at(i)->getDofs());
199 solution.insert( solution.end(), solution_tmp.begin(), solution_tmp.end() );
200
201
202 }
203
204 assemblyFEElements_[T]->updateSolution(solution);
205
206 SmallMatrixPtr_Type elementMatrix;
207 vec_dbl_ptr_Type rhsVec;
208
209 if(assembleMode == "Jacobian"){
210 assemblyFEElements_[T]->assembleJacobian();
211
212 elementMatrix = assemblyFEElements_[T]->getJacobian();
213 //elementMatrix->print();
214 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
215
216 addFeBlockMatrix(A, elementMatrix, domainVec_.at(0)->getElementsC()->getElement(T), problemDisk);
217
218 }
219 if(assembleMode == "Rhs"){
220 assemblyFEElements_[T]->assembleRHS();
221 rhsVec = assemblyFEElements_[T]->getRHS();
222 addFeBlockMv(resVecRep, rhsVec, elementsSolid->getElement(T),elementsChem->getElement(T), dofsSolid,dofsChem);
223
224 }
225
226 }
227 if ( assembleMode == "Jacobian"){
228 for(int probRow = 0; probRow < problemSize; probRow++){
229 for(int probCol = 0; probCol < problemSize; probCol++){
230 MapConstPtr_Type rowMap;
231 MapConstPtr_Type domainMap;
232
233 if(domainVec.at(probRow)->getDofs() == 1)
234 rowMap = domainVec_.at(FElocRow)->getMapUnique();
235 else
236 rowMap = domainVec_.at(probRow)->getMapVecFieldUnique();
237
238 if(domainVec.at(probCol)->getDofs() == 1)
239 domainMap = domainVec_.at(probCol)->getMapUnique()
240 else
241 domainMap = domainVec_.at(probCol)->getMapVecFieldUnique()
242
243 A->getBlock(probRow,probCol)->fillComplete(domainMap,rowMap);
244 }
245 }
246 }
247 else if(assembleMode == "Rhs"){
248
249 for(int probRow = 0; probRow < problemSize; probRow++){
250 MapConstPtr_Type rowMap;
251 if(domainVec.at(probRow)->getDofs() == 1)
252 rowMap = domainVec_.at(FElocRow)->getMapUnique();
253 else
254 rowMap = domainVec_.at(probRow)->getMapVecFieldUnique();
255
256 MultiVectorPtr_Type resVecUnique = Teuchos::rcp( new MultiVector_Type( rowMap, 1 ) );
257
258 resVecUnique->putScalar(0.);
259
260 resVecUnique->exportFromVector( resVecRep, true, "Add" );
261
262 resVec->addBlock(resVecUnique,probRow);
263 }
264 }
265
266}*/
267
280/*template <class SC, class LO, class GO, class NO>
281void FE<SC,LO,GO,NO>::addFeBlockMatrix(BlockMatrixPtr_Type &A, SmallMatrixPtr_Type elementMatrix, FiniteElement_vec element, tuple_disk_vec_ptr_Type problemDisk){
282
283 int numDisk = problemDisk->size();
284
285 for(int probRow = 0; probRow < numDisk; probRow++){
286 for(int probCol = 0; probCol < numDisk; probCol++){
287 int dofs1 = std::get<2>(problemDisk->at(probRow));
288 int dofs2 = std::get<2>(problemDisk->at(probCol));
289
290 int numNodes1 = std::get<3>(problemDisk->at(probRow));
291 int numNodes2=std::get<3>(problemDisk->at(probCol));
292
293 int offsetRow= numNodes1*dofs1*probRow;
294 int offsetCol= numNodes1*dofs1*probCol;
295
296 mapRow = domainVec.at(probRow)->getMapRepeated();
297 mapCol = domainVec.at(probCol)->getMapRepeated();
298
299 Teuchos::Array<SC> value2( numNodes2, 0. );
300 Teuchos::Array<GO> columnIndices2( numNodes2, 0 );
301 for (UN i=0; i < numNodes1; i++){
302 for(int di=0; di<dofs1; di++){
303 GO row =GO (dofs1* mapRow->getGlobalElement( element[probRow].getNode(i) )+di);
304 for(int d=0; d<dofs2; d++){
305 for (UN j=0; j < numNodes2 ; j++) {
306 value2[j] = (*elementMatrix)[offsetRow+i*dofs1+di][offsetCol+j*dofs2+d];
307 columnIndices2[j] =GO (dofs2* mapCol->getGlobalElement( element.getNode(j) )+d);
309 A->getBlock(probRow,probCol)->insertGlobalValues( row, columnIndices2(), value2() ); // Automatically adds entries if a value already exists
310 }
311 }
312 }
313
315 }
316}
317
318*/
319
322 \brief Inserting local rhsVec into global residual Mv;
323
324
325@param[in] res BlockMultiVector of residual vec; Repeated distribution; 2 blocks
326@param[in] rhsVec sorted the same way as residual vec
327@param[in] element of block1
328
329*/
330/*
331template <class SC, class LO, class GO, class NO>
332void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec,tuple_disk_vec_ptr_Type problemDisk, FiniteElement_vec element)
333 int numDisk = problemDisk->size();
334
335 for(int probRow = 0; probRow < numDisk; probRow++){
336 Teuchos::ArrayRCP<SC> resArray_block = res->getBlockNonConst(probRow)->getDataNonConst(0);
337 vec_LO_Type nodeList_block = element[probRow].getVectorNodeList();
338 int dofs = std::get<2>(problemDisk->at(probRow));
339 int numNodes = std::get<3>(problemDisk->at(probRow));
340
341 int offset = numNodes*dofs;
342 for(int i=0; i< nodeList_block.size() ; i++){
343 for(int d=0; d<dofs; d++){
344 resArray_block[nodeList_block[i]*dofs+d] += (*rhsVec)[i*dofs+d+offset];
345 }
346 }
347 }
348}
349*/
358@param[in] callFillComplete If Matrix A should be completely filled at end of function
359@param[in] FELocExternal
360
361*/
362
363template <class SC, class LO, class GO, class NO>
365 std::string FEType,
366 int degree,
367 int dofs,
368 MultiVectorPtr_Type d_rep,
369 BlockMatrixPtr_Type &A,
370 BlockMultiVectorPtr_Type &resVec,
371 ParameterListPtr_Type params,
372 bool reAssemble,
373 std::string assembleMode,
374 bool callFillComplete,
375 int FELocExternal){
376
377 ElementsPtr_Type elements = domainVec_.at(0)->getElementsC();
378
379 int dofsElement = elements->getElement(0).getVectorNodeList().size();
381 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(0)->getPointsRepeated();
382
383 MapConstPtr_Type mapVel = domainVec_.at(0)->getMapRepeated();
384
385 vec_dbl_Type solution(0);
386 vec_dbl_Type solution_d;
387
388 vec_dbl_Type rhsVec;
389
392 int numNodes=6;
393 if(dim==3){
394 numNodes=10;
395 }
396 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
397 tuple_ssii_Type displacement ("Displacement",FEType,dofs,numNodes);
398 problemDisk->push_back(displacement);
399
400 if(assemblyFEElements_.size()== 0)
401 initAssembleFEElements("LinearElasticity",problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
402 else if(assemblyFEElements_.size() != elements->numberElements())
403 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
404
405 MultiVectorPtr_Type resVec_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(0)->getMapVecFieldRepeated(), 1 ) );
406
407 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 1) );
408 resVecRep->addBlock(resVec_d,0);
409
410 SmallMatrixPtr_Type elementMatrix;
411 for (UN T=0; T<assemblyFEElements_.size(); T++) {
412 vec_dbl_Type solution(0);
413
414 solution_d = getSolution(elements->getElement(T).getVectorNodeList(), d_rep,dofs);
415
416 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
417
418 assemblyFEElements_[T]->updateSolution(solution);
419
420 assemblyFEElements_[T]->assembleJacobian();
421
422 elementMatrix = assemblyFEElements_[T]->getJacobian();
423
424 assemblyFEElements_[T]->advanceNewtonStep();
425
426
427 addFeBlock(A, elementMatrix, elements->getElement(T), mapVel, 0, 0, problemDisk);
428
429 }
430 if (callFillComplete)
431 A->getBlock(0,0)->fillComplete( domainVec_.at(0)->getMapVecFieldUnique(),domainVec_.at(0)->getMapVecFieldUnique());
432
433
434
435
436}
437
449
450template <class SC, class LO, class GO, class NO>
452 std::string FEType,
453 int degree,
454 int dofs,
455 MultiVectorPtr_Type d_rep,
456 BlockMatrixPtr_Type &A,
457 BlockMultiVectorPtr_Type &resVec,
458 ParameterListPtr_Type params,
459 bool callFillComplete,
460 int FELocExternal){
461
462 ElementsPtr_Type elements = domainVec_.at(0)->getElementsC();
464 int dofsElement = elements->getElement(0).getVectorNodeList().size();
465
466 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(0)->getPointsRepeated();
467
468 MapConstPtr_Type map = domainVec_.at(0)->getMapRepeated();
469
470 vec_dbl_Type solution(0);
471 vec_dbl_Type solution_d;
472
473 vec_dbl_ptr_Type rhsVec;
474
477 int numNodes=6;
478 if(dim==3){
479 numNodes=10;
480 }
481 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
482 tuple_ssii_Type displacement ("Displacement",FEType,dofs,numNodes);
483 problemDisk->push_back(displacement);
484
485 int neoHookeNum = params->sublist("Parameter").get("Neo-Hooke Modell",1);
486
487 std::string nonLinElasModell = "NonLinearElasticity2";
488 if(neoHookeNum == 1)
489 nonLinElasModell = "NonLinearElasticity";
490
491 //std::cout << " ######## Assembly Modell: " << nonLinElasModell << " ############ " << std::endl;
492
493
494 if(assemblyFEElements_.size()== 0)
495 initAssembleFEElements(nonLinElasModell,problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
496 else if(assemblyFEElements_.size() != elements->numberElements())
497 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
498
499
500 SmallMatrixPtr_Type elementMatrix;
501 for (UN T=0; T<assemblyFEElements_.size(); T++) {
502 vec_dbl_Type solution(0);
503
504 solution_d = getSolution(elements->getElement(T).getVectorNodeList(), d_rep,dofs);
505
506 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
507
508 assemblyFEElements_[T]->updateSolution(solution);
509
510 assemblyFEElements_[T]->assembleJacobian();
511 elementMatrix = assemblyFEElements_[T]->getJacobian();
512 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
513
514 assemblyFEElements_[T]->assembleRHS();
515 rhsVec = assemblyFEElements_[T]->getRHS();
516 addFeBlockMv(resVec, rhsVec, elements->getElement(T), dofs);
517
518 assemblyFEElements_[T]->advanceNewtonStep();
519
520
521 }
522 if (callFillComplete)
523 A->getBlock(0,0)->fillComplete( domainVec_.at(0)->getMapVecFieldUnique(),domainVec_.at(0)->getMapVecFieldUnique());
524
525}
526
527/*!
528
529 \brief Assembly of Jacobian for nonlinear Elasticity
530@param[in] dim Dimension
531@param[in] FEType FE Discretization
532@param[in] degree Degree of basis function
533@param[in] A Resulting matrix
534@param[in] callFillComplete If Matrix A should be completely filled at end of function
535@param[in] FELocExternal
536
537*/
538
539template <class SC, class LO, class GO, class NO>
541 std::string FEType,
542 int degree,
543 int dofs,
544 MultiVectorPtr_Type d_rep,
545 BlockMatrixPtr_Type &A,
546 BlockMultiVectorPtr_Type &resVec,
547 ParameterListPtr_Type params,
548 DomainConstPtr_Type domain,
549 MultiVectorPtr_Type eModVec,
550 bool callFillComplete,
551 int FELocExternal){
552
553 ElementsPtr_Type elements = domain->getElementsC();
554
555 int dofsElement = elements->getElement(0).getVectorNodeList().size();
556
557 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
558
559 MapConstPtr_Type map = domain->getMapRepeated();
560
561 vec_dbl_Type solution(0);
562 vec_dbl_Type solution_d;
563
564 vec_dbl_ptr_Type rhsVec;
565
568 int numNodes=6;
569 if(dim==3){
570 numNodes=10;
571 }
572 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
573 tuple_ssii_Type displacement ("Displacement",FEType,dofs,numNodes);
574 problemDisk->push_back(displacement);
575
576 int neoHookeNum = params->sublist("Parameter").get("Neo-Hooke Modell",1);
577
578 std::string nonLinElasModell = "NonLinearElasticity2";
579 if(neoHookeNum == 1)
580 nonLinElasModell = "NonLinearElasticity";
581
582 //std::cout << " ######## Assembly Modell: " << nonLinElasModell << " ############ " << std::endl;
583
584 if(assemblyFEElements_.size()== 0)
585 initAssembleFEElements(nonLinElasModell,problemDisk,elements, params,pointsRep,domain->getElementMap());
586 else if(assemblyFEElements_.size() != elements->numberElements())
587 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
588
589 Teuchos::ArrayRCP<SC> eModVecA = eModVec->getDataNonConst(0);
590
591 SmallMatrixPtr_Type elementMatrix;
592 for (UN T=0; T<assemblyFEElements_.size(); T++) {
593 vec_dbl_Type solution(0);
594
595 solution_d = getSolution(elements->getElement(T).getVectorNodeList(), d_rep,dofs);
597 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
598
599 assemblyFEElements_[T]->updateSolution(solution);
600 assemblyFEElements_[T]->updateParameter("E",eModVecA[T]);
601 assemblyFEElements_[T]->assembleJacobian();
602 elementMatrix = assemblyFEElements_[T]->getJacobian();
603 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
604
605 assemblyFEElements_[T]->assembleRHS();
606 rhsVec = assemblyFEElements_[T]->getRHS();
607 addFeBlockMv(resVec, rhsVec, elements->getElement(T), dofs);
608
609 assemblyFEElements_[T]->advanceNewtonStep();
610
611
612 }
613 if (callFillComplete)
614 A->getBlock(0,0)->fillComplete( domainVec_.at(0)->getMapVecFieldUnique(),domainVec_.at(0)->getMapVecFieldUnique());
616}
617
618
619
630
631template <class SC, class LO, class GO, class NO>
632void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec, FiniteElement elementBlock, int dofs){
633
634 Teuchos::ArrayRCP<SC> resArray_block = res->getBlockNonConst(0)->getDataNonConst(0);
635
636 vec_LO_Type nodeList_block = elementBlock.getVectorNodeList();
637
638 for(int i=0; i< nodeList_block.size() ; i++){
639 for(int d=0; d<dofs; d++)
640 resArray_block[nodeList_block[i]*dofs+d] += (*rhsVec)[i*dofs+d];
641 }
642}
643
644// Check the order of chemistry and solid in system matrix
645template <class SC, class LO, class GO, class NO>
647 std::string FETypeChem,
648 std::string FETypeSolid,
649 int degree,
650 int dofsChem,
651 int dofsSolid,
652 MultiVectorPtr_Type c_rep,
653 MultiVectorPtr_Type d_rep,
654 BlockMatrixPtr_Type &A,
655 BlockMultiVectorPtr_Type &resVec,
656 ParameterListPtr_Type params,
657 std::string assembleMode,
658 bool callFillComplete,
659 int FELocExternal){
660
661 if((FETypeChem != "P2") || (FETypeSolid != "P2") || dim != 3)
662 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No AceGen Implementation available for Discretization and Dimension." );
663
664
665 UN FElocChem = 1; //checkFE(dim,FETypeChem); // Checks for different domains which belongs to a certain fetype
666 UN FElocSolid = 0; //checkFE(dim,FETypeSolid); // Checks for different domains which belongs to a certain fetype
667
668 ElementsPtr_Type elementsChem= domainVec_.at(FElocChem)->getElementsC();
669
670 ElementsPtr_Type elementsSolid = domainVec_.at(FElocSolid)->getElementsC();
671
672 //this->domainVec_.at(FElocChem)->info();
673 //this->domainVec_.at(FElocSolid)->info();
674 //int dofsElement = elements->getElement(0).getVectorNodeList().size();
675
676 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FElocSolid)->getPointsRepeated();
677
678 MapConstPtr_Type mapChem = domainVec_.at(FElocChem)->getMapRepeated();
679
680 MapConstPtr_Type mapSolid = domainVec_.at(FElocSolid)->getMapRepeated();
681
682 vec_dbl_Type solution_c;
683 vec_dbl_Type solution_d;
684
685 vec_dbl_ptr_Type rhsVec;
686
689 int numChem=3;
690 if(FETypeChem == "P2"){
691 numChem=6;
692 }
693 if(dim==3){
694 numChem=4;
695 if(FETypeChem == "P2")
696 numChem=10;
697 }
698 int numSolid=3;
699 if(FETypeSolid == "P2")
700 numSolid=6;
701
702 if(dim==3){
703 numSolid=4;
704 if(FETypeSolid == "P2")
705 numSolid=10;
706 }
707 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
708 tuple_ssii_Type chem ("Chemistry",FETypeChem,dofsChem,numChem);
709 tuple_ssii_Type solid ("Solid",FETypeSolid,dofsSolid,numSolid);
710 problemDisk->push_back(solid);
711 problemDisk->push_back(chem);
712
713 tuple_disk_vec_ptr_Type problemDiskChem = Teuchos::rcp(new tuple_disk_vec_Type(0));
714 problemDiskChem->push_back(chem);
715
716 std::string SCIModel = params->sublist("Parameter").get("Structure Model","SCI_simple");
717
718 if(assemblyFEElements_.size()== 0){
719 initAssembleFEElements(SCIModel,problemDisk,elementsChem, params,pointsRep,domainVec_.at(FElocSolid)->getElementMap());
720 }
721 else if(assemblyFEElements_.size() != elementsChem->numberElements())
722 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
723
724 //SmallMatrixPtr_Type elementMatrix =Teuchos::rcp( new SmallMatrix_Type( dofsElement));
725
726 MultiVectorPtr_Type resVec_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapRepeated(), 1 ) );
727 MultiVectorPtr_Type resVec_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldRepeated(), 1 ) );
728
729 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 2) );
730 resVecRep->addBlock(resVec_d,0);
731 resVecRep->addBlock(resVec_c,1);
732
733 SC detB;
734 SC absDetB;
735 SmallMatrix<SC> B(dim);
736 SmallMatrix<SC> Binv(dim);
737
738
739 for (UN T=0; T<assemblyFEElements_.size(); T++) {
740 vec_dbl_Type solution(0);
741
742 solution_c = getSolution(elementsChem->getElement(T).getVectorNodeList(), c_rep,dofsChem);
743 solution_d = getSolution(elementsSolid->getElement(T).getVectorNodeList(), d_rep,dofsSolid);
744
745 // First Solid, then Chemistry
746 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
747 solution.insert( solution.end(), solution_c.begin(), solution_c.end() );
748
749 assemblyFEElements_[T]->updateSolution(solution);
750
751 SmallMatrixPtr_Type elementMatrix;
752
753 // ------------------------
754 /*buildTransformation(elementsSolid->getElement(T).getVectorNodeList(), pointsRep, B, FETypeSolid);
755 detB = B.computeInverse(Binv);
756 absDetB = std::fabs(detB);
757 std::cout << " Determinante " << detB << std::endl;*/
758 // ------------------------
759
760
761
762
763 if(assembleMode == "Jacobian"){
764 assemblyFEElements_[T]->assembleJacobian();
765
766 elementMatrix = assemblyFEElements_[T]->getJacobian();
767 // elementMatrix->print();
768 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
769
770 addFeBlockMatrix(A, elementMatrix, elementsSolid->getElement(T), elementsSolid->getElement(T), mapSolid, mapChem, problemDisk);
771
772
773
774 }
775 if(assembleMode == "Rhs"){
776 assemblyFEElements_[T]->assembleRHS();
777 rhsVec = assemblyFEElements_[T]->getRHS();
778 addFeBlockMv(resVecRep, rhsVec, elementsSolid->getElement(T),elementsChem->getElement(T), dofsSolid,dofsChem);
779
780 }
781 if(assembleMode=="MassMatrix"){
782 assemblyFEElements_[T]->assembleJacobian();
783
784 AssembleFE_SCI_SMC_Active_Growth_Reorientation_Ptr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFE_SCI_SMC_Active_Growth_Reorientation_Type>(assemblyFEElements_[T] );
785 elTmp->getMassMatrix(elementMatrix);
786 //elementMatrix->print();
787 addFeBlock(A, elementMatrix, elementsChem->getElement(T), mapChem, 0, 0, problemDiskChem);
788
789
790 }
791
792
793
794
795 }
796 if ( assembleMode == "Jacobian"){
797 A->getBlock(0,0)->fillComplete();
798 A->getBlock(1,0)->fillComplete(domainVec_.at(FElocSolid)->getMapVecFieldUnique(),domainVec_.at(FElocChem)->getMapUnique());
799 A->getBlock(0,1)->fillComplete(domainVec_.at(FElocChem)->getMapUnique(),domainVec_.at(FElocSolid)->getMapVecFieldUnique());
800 A->getBlock(1,1)->fillComplete();
801 }
802 else if(assembleMode == "Rhs"){
803
804 MultiVectorPtr_Type resVecUnique_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldUnique(), 1 ) );
805 MultiVectorPtr_Type resVecUnique_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapUnique(), 1 ) );
806
807 resVecUnique_d->putScalar(0.);
808 resVecUnique_c->putScalar(0.);
809
810 resVecUnique_d->exportFromVector( resVec_d, true, "Add" );
811 resVecUnique_c->exportFromVector( resVec_c, true, "Add" );
812
813 resVec->addBlock(resVecUnique_d,0);
814 resVec->addBlock(resVecUnique_c,1);
815 }
816 else if(assembleMode == "MassMatrix"){
817 A->getBlock(0,0)->fillComplete();
818 }
819
820}
821
822// Check the order of chemistry and solid in system matrix
823template <class SC, class LO, class GO, class NO>
825 std::string FETypeChem,
826 std::string FETypeSolid,
827 int degree,
828 int dofsChem,
829 int dofsSolid,
830 MultiVectorPtr_Type c_rep,
831 MultiVectorPtr_Type d_rep,
832 BlockMatrixPtr_Type &A,
833 int blockRow,
834 int blockCol,
835 BlockMultiVectorPtr_Type &resVec,
836 int block,
837 ParameterListPtr_Type params,
838 std::string assembleMode,
839 bool callFillComplete,
840 int FELocExternal){
841
842 if((FETypeChem != "P2") || (FETypeSolid != "P2") || dim != 3)
843 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No AceGen Implementation available for Discretization and Dimension." );
844 if((blockRow != blockCol) && blockRow != 0)
845 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Block assemblyDeformDiffu AceGEN Version only implemented for 0,0 block right now" );
846
847 //UN FElocChem = 1; //checkFE(dim,FETypeChem); // Checks for different domains which belongs to a certain fetype
848 UN FElocSolid = 0; //checkFE(dim,FETypeSolid); // Checks for different domains which belongs to a certain fetype
849
850 ElementsPtr_Type elementsChem= domainVec_.at(FElocSolid)->getElementsC();
851
852 ElementsPtr_Type elementsSolid = domainVec_.at(FElocSolid)->getElementsC();
853
854 //this->domainVec_.at(FElocChem)->info();
855 //this->domainVec_.at(FElocSolid)->info();
856 //int dofsElement = elements->getElement(0).getVectorNodeList().size();
857
858 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FElocSolid)->getPointsRepeated();
859
860 //MapConstPtr_Type mapChem = domainVec_.at(FElocChem)->getMapRepeated();
861
862 MapConstPtr_Type mapSolid = domainVec_.at(FElocSolid)->getMapRepeated();
863
864 vec_dbl_Type solution_c;
865 vec_dbl_Type solution_d;
866
867 vec_dbl_ptr_Type rhsVec;
868
871 int numChem=3;
872 if(FETypeChem == "P2"){
873 numChem=6;
874 }
875 if(dim==3){
876 numChem=4;
877 if(FETypeChem == "P2")
878 numChem=10;
879 }
880 int numSolid=3;
881 if(FETypeSolid == "P2")
882 numSolid=6;
883
884 if(dim==3){
885 numSolid=4;
886 if(FETypeSolid == "P2")
887 numSolid=10;
888 }
889 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
890 tuple_ssii_Type chem ("Chemistry",FETypeChem,dofsChem,numChem);
891 tuple_ssii_Type solid ("Solid",FETypeSolid,dofsSolid,numSolid);
892 problemDisk->push_back(solid);
893 problemDisk->push_back(chem);
894
895 std::string SCIModel = params->sublist("Parameter").get("Structure Model","SCI_simple");
896
897 if(assemblyFEElements_.size()== 0){
898 initAssembleFEElements(SCIModel,problemDisk,elementsChem, params,pointsRep,domainVec_.at(FElocSolid)->getElementMap());
899 }
900 else if(assemblyFEElements_.size() != elementsChem->numberElements())
901 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
902
903 //SmallMatrixPtr_Type elementMatrix =Teuchos::rcp( new SmallMatrix_Type( dofsElement));
904
905 //MultiVectorPtr_Type resVec_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapRepeated(), 1 ) );
906 MultiVectorPtr_Type resVec_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldRepeated(), 1 ) );
907
908 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 1) );
909 resVecRep->addBlock(resVec_d,0);
910 //resVecRep->addBlock(resVec_c,1);
911
912 for (UN T=0; T<assemblyFEElements_.size(); T++) {
913 vec_dbl_Type solution(0);
914
915 solution_c = getSolution(elementsChem->getElement(T).getVectorNodeList(), c_rep,dofsChem);
916 solution_d = getSolution(elementsSolid->getElement(T).getVectorNodeList(), d_rep,dofsSolid);
917
918 // First Solid, then Chemistry
919 solution.insert( solution.end(), solution_d.begin(), solution_d.end() );
920 solution.insert( solution.end(), solution_c.begin(), solution_c.end() );
921
922 assemblyFEElements_[T]->updateSolution(solution);
923
924 SmallMatrixPtr_Type elementMatrix;
925
926 if(assembleMode == "Jacobian"){
927 assemblyFEElements_[T]->assembleJacobian();
928
929 elementMatrix = assemblyFEElements_[T]->getJacobian();
930 // elementMatrix->print();
931 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
932 addFeBlock(A, elementMatrix, elementsSolid->getElement(T), mapSolid, 0, 0, problemDisk);
933 //addFeBlockMatrix(A, elementMatrix, elementsSolid->getElement(T), mapSolid, mapChem, problemDisk);
934 }
935 if(assembleMode == "Rhs"){
936 assemblyFEElements_[T]->assembleRHS();
937 rhsVec = assemblyFEElements_[T]->getRHS();
938 addFeBlockMv(resVecRep, rhsVec, elementsSolid->getElement(T), dofsSolid);
939 }
940 //if(assembleMode=="compute")
941 // assemblyFEElements_[T]->compute();
942
943
944
945
946 }
947 if ( assembleMode != "Rhs"){
948 A->getBlock(0,0)->fillComplete();
949 //A->getBlock(1,0)->fillComplete(domainVec_.at(FElocSolid)->getMapVecFieldUnique(),domainVec_.at(FElocChem)->getMapUnique());
950 //A->getBlock(0,1)->fillComplete(domainVec_.at(FElocChem)->getMapUnique(),domainVec_.at(FElocSolid)->getMapVecFieldUnique());
951 //A->getBlock(1,1)->fillComplete();
952 }
953
954 if(assembleMode == "Rhs"){
955
956 MultiVectorPtr_Type resVecUnique_d = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocSolid)->getMapVecFieldUnique(), 1 ) );
957 //MultiVectorPtr_Type resVecUnique_c = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocChem)->getMapUnique(), 1 ) );
958
959 resVecUnique_d->putScalar(0.);
960 //resVecUnique_c->putScalar(0.);
961
962 resVecUnique_d->exportFromVector( resVec_d, true, "Add" );
963 //resVecUnique_c->exportFromVector( resVec_c, true, "Add" );
964
965 resVec->addBlock(resVecUnique_d,0);
966 //resVec->addBlock(resVecUnique_c,1);
967 }
968
969
970}
971
983template <class SC, class LO, class GO, class NO>
984void 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){
985
986 int numDisk = problemDisk->size();
987
988 int dofs1 = std::get<2>(problemDisk->at(0));
989 int dofs2 = std::get<2>(problemDisk->at(1));
990
991 int numNodes1 = std::get<3>(problemDisk->at(0));
992 int numNodes2=std::get<3>(problemDisk->at(1));
993
994 int dofsBlock1 = dofs1*numNodes1;
995 int dofsBlock2 = dofs2*numNodes2;
996
997 Teuchos::Array<SC> value1( numNodes1, 0. );
998 Teuchos::Array<GO> columnIndices1( numNodes1, 0 );
999
1000 Teuchos::Array<SC> value2( numNodes2, 0. );
1001 Teuchos::Array<GO> columnIndices2( numNodes2, 0 );
1002
1003 for (UN i=0; i < numNodes1 ; i++) {
1004 for(int di=0; di<dofs1; di++){
1005 GO row =GO (dofs1* mapFirstRow->getGlobalElement( element1.getNode(i) )+di);
1006 for(int d=0; d<dofs1; d++){
1007 for (UN j=0; j < columnIndices1.size(); j++){
1008 columnIndices1[j] = GO ( dofs1 * mapFirstRow->getGlobalElement( element1.getNode(j) ) + d );
1009 value1[j] = (*elementMatrix)[dofs1*i+di][dofs1*j+d];
1010 }
1011 A->getBlock(0,0)->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
1012 }
1013 }
1014 }
1015 int offset= numNodes1*dofs1;
1016
1017
1018 Teuchos::Array<SC> value( 1, 0. );
1019 Teuchos::Array<GO> columnIndex( 1, 0 );
1020 for (UN i=0; i < numNodes2 ; i++) {
1021 for(int di=0; di<dofs2; di++){
1022 GO row =GO (dofs2* mapSecondRow->getGlobalElement( element2.getNode(i) )+di);
1023 for(int d=0; d<dofs2; d++){
1024 for (UN j=0; j < columnIndices2.size(); j++){
1025 double tmpValue = (*elementMatrix)[offset+dofs2*i+di][offset+dofs2*j+d];
1026 if(std::fabs(tmpValue) > 1.e-13){
1027 columnIndex[0] = GO ( dofs2 * mapSecondRow->getGlobalElement( element2.getNode(j) ) + d );
1028 value[0] = tmpValue;
1029 A->getBlock(1,1)->insertGlobalValues( row, columnIndex(), value() ); // Automatically adds entries if a value already exists
1030
1031 }
1032 }
1033 }
1034 }
1035 }
1036
1037 for (UN i=0; i < numNodes1; i++){
1038 for(int di=0; di<dofs1; di++){
1039 GO row =GO (dofs1* mapFirstRow->getGlobalElement( element1.getNode(i) )+di);
1040 for(int d=0; d<dofs2; d++){
1041 for (UN j=0; j < numNodes2 ; j++) {
1042 value2[j] = (*elementMatrix)[i*dofs1+di][offset+j*dofs2+d];
1043 columnIndices2[j] =GO (dofs2* mapSecondRow->getGlobalElement( element2.getNode(j) )+d);
1044 }
1045 A->getBlock(0,1)->insertGlobalValues( row, columnIndices2(), value2() ); // Automatically adds entries if a value already exists
1046 }
1047 }
1048 }
1049
1050 for (UN j=0; j < numNodes2; j++){
1051 for(int di=0; di<dofs2; di++){
1052 GO row = GO (dofs2* mapSecondRow->getGlobalElement( element2.getNode(j) ) +di );
1053 for(int d=0; d<dofs1; d++){
1054 for (UN i=0; i < numNodes1 ; i++) {
1055 value1[i] = (*elementMatrix)[offset+j*dofs2+di][dofs1*i+d];
1056 columnIndices1[i] =GO (dofs1* mapFirstRow->getGlobalElement( element1.getNode(i) )+d);
1057 }
1058 A->getBlock(1,0)->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
1059 }
1060 }
1061 }
1062
1063
1064}
1065
1066
1078
1079template <class SC, class LO, class GO, class NO>
1081 std::string FETypeVelocity,
1082 std::string FETypePressure,
1083 int degree,
1084 int dofsVelocity,
1085 int dofsPressure,
1086 MultiVectorPtr_Type u_rep,
1087 MultiVectorPtr_Type p_rep,
1088 BlockMatrixPtr_Type &A,
1089 BlockMultiVectorPtr_Type &resVec,
1090 SmallMatrix_Type coeff,
1091 ParameterListPtr_Type params,
1092 bool reAssemble,
1093 std::string assembleMode,
1094 bool callFillComplete,
1095 int FELocExternal){
1096
1097
1098 UN FElocVel = checkFE(dim,FETypeVelocity); // Checks for different domains which belongs to a certain fetype
1099 UN FElocPres = checkFE(dim,FETypePressure); // Checks for different domains which belongs to a certain fetype
1100
1101 ElementsPtr_Type elements = domainVec_.at(FElocVel)->getElementsC();
1102
1103 ElementsPtr_Type elementsPres = domainVec_.at(FElocPres)->getElementsC();
1104
1105 int dofsElement = elements->getElement(0).getVectorNodeList().size();
1106
1107 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FElocVel)->getPointsRepeated();
1108
1109 MapConstPtr_Type mapVel = domainVec_.at(FElocVel)->getMapRepeated();
1110
1111 MapConstPtr_Type mapPres = domainVec_.at(FElocPres)->getMapRepeated();
1112
1113 vec_dbl_Type solution(0);
1114 vec_dbl_Type solution_u;
1115 vec_dbl_Type solution_p;
1116
1117 vec_dbl_ptr_Type rhsVec;
1118
1121 int numVelo=3;
1122 if(FETypeVelocity == "P2")
1123 numVelo=6;
1124
1125 if(dim==3){
1126 numVelo=4;
1127 if(FETypeVelocity == "P2")
1128 numVelo=10;
1129 }
1130 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
1131 tuple_ssii_Type vel ("Velocity",FETypeVelocity,dofsVelocity,numVelo);
1132 tuple_ssii_Type pres ("Pressure",FETypePressure,dofsPressure,dim+1);
1133 problemDisk->push_back(vel);
1134 problemDisk->push_back(pres);
1135
1136 if(assemblyFEElements_.size()== 0){
1137 if(params->sublist("Material").get("Newtonian",true) == false)
1138 initAssembleFEElements("GeneralizedNewtonian",problemDisk,elements, params,pointsRep,domainVec_.at(FElocVel)->getElementMap()); // In cas of non Newtonian Fluid
1139 else
1140 initAssembleFEElements("NavierStokes",problemDisk,elements, params,pointsRep,domainVec_.at(FElocVel)->getElementMap());
1141 }
1142 else if(assemblyFEElements_.size() != elements->numberElements())
1143 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
1144
1145 //SmallMatrixPtr_Type elementMatrix =Teuchos::rcp( new SmallMatrix_Type( dofsElement));
1146
1147 MultiVectorPtr_Type resVec_u = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getMapVecFieldRepeated(), 1 ) );
1148 MultiVectorPtr_Type resVec_p = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocPres)->getMapRepeated(), 1 ) );
1149
1150 BlockMultiVectorPtr_Type resVecRep = Teuchos::rcp( new BlockMultiVector_Type( 2) );
1151 resVecRep->addBlock(resVec_u,0);
1152 resVecRep->addBlock(resVec_p,1);
1153
1154
1155 for (UN T=0; T<assemblyFEElements_.size(); T++) {
1156 vec_dbl_Type solution(0);
1157
1158 solution_u = getSolution(elements->getElement(T).getVectorNodeList(), u_rep,dofsVelocity);
1159 solution_p = getSolution(elementsPres->getElement(T).getVectorNodeList(), p_rep,dofsPressure);
1160
1161 solution.insert( solution.end(), solution_u.begin(), solution_u.end() );
1162 solution.insert( solution.end(), solution_p.begin(), solution_p.end() );
1163
1164 assemblyFEElements_[T]->updateSolution(solution);
1165
1166 SmallMatrixPtr_Type elementMatrix;
1167
1168 if(assembleMode == "Jacobian"){
1169 assemblyFEElements_[T]->assembleJacobian();
1170
1171 elementMatrix = assemblyFEElements_[T]->getJacobian();
1172
1173 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
1174
1175 if(reAssemble)
1176 addFeBlock(A, elementMatrix, elements->getElement(T), mapVel, 0, 0, problemDisk);
1177 else
1178 addFeBlockMatrix(A, elementMatrix, elements->getElement(T), elementsPres->getElement(T), mapVel, mapPres, problemDisk);
1179 }
1180 if(assembleMode == "FixedPoint"){
1181
1182 //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
1183
1184 if(params->sublist("Material").get("Newtonian",true) == false)
1185 {
1186 AssembleFEGeneralizedNewtonianPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFEGeneralizedNewtonian_Type>( assemblyFEElements_[T] );
1187 elTmp->assembleFixedPoint();
1188 elementMatrix = elTmp->getFixedPointMatrix();
1189 }
1190 else // Newtonian Case
1191 {
1192 AssembleFENavierStokesPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFENavierStokes_Type>( assemblyFEElements_[T] );
1193 elTmp->assembleFixedPoint();
1194 elementMatrix = elTmp->getFixedPointMatrix();
1195 }
1196
1197
1198 assemblyFEElements_[T]->advanceNewtonStep(); // n genereal non linear solver step
1199
1200 if(reAssemble)
1201 addFeBlock(A, elementMatrix, elements->getElement(T), mapVel, 0, 0, problemDisk);
1202 else
1203 addFeBlockMatrix(A, elementMatrix, elements->getElement(T), elementsPres->getElement(T),mapVel, mapPres, problemDisk);
1204
1205 }
1206 if(assembleMode == "Rhs"){
1207 AssembleFENavierStokesPtr_Type elTmp = Teuchos::rcp_dynamic_cast<AssembleFENavierStokes_Type>(assemblyFEElements_[T] );
1208 elTmp->setCoeff(coeff);// Coeffs from time discretization. Right now default [1][1] // [0][0]
1209 assemblyFEElements_[T]->assembleRHS();
1210 rhsVec = assemblyFEElements_[T]->getRHS();
1211 addFeBlockMv(resVecRep, rhsVec, elements->getElement(T),elementsPres->getElement(T), dofsVelocity,dofsPressure);
1212 }
1213
1214
1215 }
1216 if (callFillComplete && reAssemble && assembleMode != "Rhs" )
1217 A->getBlock(0,0)->fillComplete( domainVec_.at(FElocVel)->getMapVecFieldUnique(),domainVec_.at(FElocVel)->getMapVecFieldUnique());
1218 else if(callFillComplete && !reAssemble && assembleMode != "Rhs"){
1219 A->getBlock(0,0)->fillComplete();
1220 A->getBlock(1,0)->fillComplete(domainVec_.at(FElocVel)->getMapVecFieldUnique(),domainVec_.at(FElocPres)->getMapUnique());
1221 A->getBlock(0,1)->fillComplete(domainVec_.at(FElocPres)->getMapUnique(),domainVec_.at(FElocVel)->getMapVecFieldUnique());
1222 }
1223
1224 if(assembleMode == "Rhs"){
1225
1226 MultiVectorPtr_Type resVecUnique_u = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getMapVecFieldUnique(), 1 ) );
1227 MultiVectorPtr_Type resVecUnique_p = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocPres)->getMapUnique(), 1 ) );
1228
1229 resVecUnique_u->putScalar(0.);
1230 resVecUnique_p->putScalar(0.);
1231
1232 resVecUnique_u->exportFromVector( resVec_u, true, "Add" );
1233 resVecUnique_p->exportFromVector( resVec_p, true, "Add" );
1234
1235 resVec->addBlock(resVecUnique_u,0);
1236 resVec->addBlock(resVecUnique_p,1);
1237 }
1238
1239
1240}
1241
1242
1251
1252
1253template <class SC, class LO, class GO, class NO>
1255 std::string FETypeVelocity,
1256 std::string FETypePressure,
1257 int dofsVelocity,
1258 int dofsPressure,
1259 MultiVectorPtr_Type u_rep,
1260 MultiVectorPtr_Type p_rep,
1261 ParameterListPtr_Type params){
1262
1263
1264 UN FElocVel = checkFE(dim,FETypeVelocity); // Checks for different domains which belongs to a certain fetype
1265 UN FElocPres = checkFE(dim,FETypePressure); // Checks for different domains which belongs to a certain fetype
1266
1267 ElementsPtr_Type elements = domainVec_.at(FElocVel)->getElementsC();
1268 ElementsPtr_Type elementsPres = domainVec_.at(FElocPres)->getElementsC();
1269
1270 vec_dbl_Type solution(0);
1271 vec_dbl_Type solution_u;
1272 vec_dbl_Type solution_p;
1273 vec_dbl_Type solution_viscosity;
1274
1275 // We have to compute viscosity solution in each element
1276 MultiVectorPtr_Type Sol_viscosity = Teuchos::rcp( new MultiVector_Type( domainVec_.at(FElocVel)->getElementMap(), 1 ) ); //
1277 BlockMultiVectorPtr_Type visco_output = Teuchos::rcp( new BlockMultiVector_Type(1) );
1278 visco_output->addBlock(Sol_viscosity,0);
1279
1280
1281 for (UN T=0; T<assemblyFEElements_.size(); T++) {
1282
1283 vec_dbl_Type solution(0);
1284 solution_u = getSolution(elements->getElement(T).getVectorNodeList(), u_rep,dofsVelocity); // get the solution inside an element on the nodes
1285 solution_p = getSolution(elementsPres->getElement(T).getVectorNodeList(), p_rep,dofsPressure);
1286
1287 solution.insert( solution.end(), solution_u.begin(), solution_u.end() ); // here we insert the solution
1288 solution.insert( solution.end(), solution_p.begin(), solution_p.end() );
1289
1290 assemblyFEElements_[T]->updateSolution(solution); // here we update the value of the solutions inside an element
1291
1292 assemblyFEElements_[T]->computeLocalconstOutputField(); // we compute the viscosity inside an element
1293 solution_viscosity = assemblyFEElements_[T]->getLocalconstOutputField();
1294
1295 Teuchos::ArrayRCP<SC> resArray_block = visco_output->getBlockNonConst(0)->getDataNonConst(0); // First
1296 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
1297
1298 } // end loop over all elements
1299 // 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
1300 this->const_output_fields= visco_output;
1301
1302
1303}
1304
1305
1306
1317
1318template <class SC, class LO, class GO, class NO>
1319void FE<SC,LO,GO,NO>::addFeBlockMv(BlockMultiVectorPtr_Type &res, vec_dbl_ptr_Type rhsVec, FiniteElement elementBlock1,FiniteElement elementBlock2, int dofs1, int dofs2 ){
1320
1321 Teuchos::ArrayRCP<SC> resArray_block1 = res->getBlockNonConst(0)->getDataNonConst(0);
1322
1323 Teuchos::ArrayRCP<SC> resArray_block2 = res->getBlockNonConst(1)->getDataNonConst(0);
1324
1325 vec_LO_Type nodeList_block1 = elementBlock1.getVectorNodeList();
1326
1327 vec_LO_Type nodeList_block2 = elementBlock2.getVectorNodeList();
1328
1329 for(int i=0; i< nodeList_block1.size() ; i++){
1330 for(int d=0; d<dofs1; d++){
1331 resArray_block1[nodeList_block1[i]*dofs1+d] += (*rhsVec)[i*dofs1+d];
1332 }
1333 }
1334 int offset = nodeList_block1.size()*dofs1;
1335
1336 for(int i=0; i < nodeList_block2.size(); i++){
1337 for(int d=0; d<dofs2; d++)
1338 resArray_block2[nodeList_block2[i]*dofs2+d] += (*rhsVec)[i*dofs2+d+offset];
1339 }
1340
1341}
1342
1343
1356template <class SC, class LO, class GO, class NO>
1357void 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){
1358
1359 int dofs1 = std::get<2>(problemDisk->at(row));
1360
1361 int numNodes1 = std::get<3>(problemDisk->at(row));
1362
1363 int dofsBlock1 = dofs1*numNodes1;
1364
1365 Teuchos::Array<SC> value( numNodes1, 0. );
1366 Teuchos::Array<GO> columnIndices( numNodes1, 0 );
1367
1368 for (UN i=0; i < numNodes1 ; i++) {
1369 for(int di=0; di<dofs1; di++){
1370 GO rowID =GO (dofs1* mapRow->getGlobalElement( element.getNode(i) )+di);
1371 for(int d=0; d<dofs1; d++){
1372 for (UN j=0; j < columnIndices.size(); j++){
1373 columnIndices[j] = GO ( dofs1 * mapRow->getGlobalElement( element.getNode(j) ) + d );
1374 value[j] = (*elementMatrix)[dofs1*i+di][dofs1*j+d];
1375 }
1376 A->getBlock(row,column)->insertGlobalValues( rowID, columnIndices(), value() ); // Automatically adds entries if a value already exists
1377 }
1378 }
1379 }
1380}
1381
1392template <class SC, class LO, class GO, class NO>
1393void 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){
1394
1395 vec2D_dbl_Type nodes;
1396 for (UN T=0; T<elements->numberElements(); T++) {
1397
1398 nodes = getCoordinates(elements->getElement(T).getVectorNodeList(), pointsRep);
1399
1400 AssembleFEFactory<SC,LO,GO,NO> assembleFEFactory;
1401
1402 AssembleFEPtr_Type assemblyFE = assembleFEFactory.build(elementType,elements->getElement(T).getFlag(),nodes, params,problemDisk);
1403 //
1404 assemblyFE->setGlobalElementID(elementMap->getGlobalElement(T));
1405
1406 assemblyFEElements_.push_back(assemblyFE);
1407
1408 }
1409
1410}
1411
1421
1422template <class SC, class LO, class GO, class NO>
1423vec2D_dbl_Type FE<SC,LO,GO,NO>::getCoordinates(vec_LO_Type localIDs, vec2D_dbl_ptr_Type points){
1424
1425 vec2D_dbl_Type coordinates(0,vec_dbl_Type( points->at(0).size()));
1426 for(int i=0; i < localIDs.size() ; i++){
1427 coordinates.push_back(points->at(localIDs[i]));
1428 }
1429
1430 return coordinates;
1431}
1432
1442
1443template <class SC, class LO, class GO, class NO>
1444vec_dbl_Type FE<SC,LO,GO,NO>::getSolution(vec_LO_Type localIDs, MultiVectorPtr_Type u_rep, int dofsVelocity){
1445
1446 Teuchos::ArrayRCP<SC> uArray = u_rep->getDataNonConst(0);
1447
1448 vec_dbl_Type solution(0);
1449 for(int i=0; i < localIDs.size() ; i++){
1450 for(int d=0; d<dofsVelocity; d++)
1451 solution.push_back(uArray[localIDs[i]*dofsVelocity+d]);
1452 }
1453
1454 return solution;
1455}
1456
1457
1458template <class SC, class LO, class GO, class NO>
1459void FE<SC,LO,GO,NO>::applyBTinv( vec3D_dbl_ptr_Type& dPhiIn,
1460 vec3D_dbl_Type& dPhiOut,
1461 const SmallMatrix<SC>& Binv){
1462 UN dim = Binv.size();
1463 for (UN w=0; w<dPhiIn->size(); w++){
1464 for (UN i=0; i < dPhiIn->at(w).size(); i++) {
1465 for (UN d1=0; d1<dim; d1++) {
1466 for (UN d2=0; d2<dim; d2++) {
1467 dPhiOut[w][i][d1] += dPhiIn->at(w).at(i).at(d2) * Binv[d2][d1];
1468 }
1469 }
1470 }
1471 }
1472}
1473
1474template <class SC, class LO, class GO, class NO>
1475void FE<SC,LO,GO,NO>::assemblyEmptyMatrix(MatrixPtr_Type &A){
1476 A->fillComplete();
1477}
1478template <class SC, class LO, class GO, class NO>
1479void FE<SC,LO,GO,NO>::assemblyIdentity(MatrixPtr_Type &A){
1480 Teuchos::Array<SC> value(1, Teuchos::ScalarTraits<SC>::one() );
1481 Teuchos::Array<GO> index(1);
1482 MapConstPtr_Type map = A->getMap();
1483 for (int i=0; i<A->getNodeNumRows(); i++) {
1484 index[0] = map->getGlobalElement( i );
1485 A->insertGlobalValues( index[0], index(), value() );
1486 }
1487 A->fillComplete();
1488}
1489
1490
1491template <class SC, class LO, class GO, class NO>
1492void FE<SC,LO,GO,NO>::assemblySurfaceRobinBC(int dim,
1493 std::string FETypeP,
1494 std::string FETypeV,
1495 MultiVectorPtr_Type u,
1496 MatrixPtr_Type A,
1497 std::vector<SC>& funcParameter,
1498 RhsFunc_Type func,
1499 ParameterListPtr_Type parameters){
1500
1501 ElementsPtr_Type elements = domainVec_.at(1)->getElementsC();
1502 ElementsPtr_Type elementsV = domainVec_.at(0)->getElementsC();
1503
1504 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(1)->getPointsRepeated();
1505
1506 MapConstPtr_Type map = domainVec_.at(1)->getMapRepeated();
1507
1508 vec2D_dbl_ptr_Type phi,phiV;
1509 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1510
1511
1512 UN extraDeg = Helper::determineDegree( dim-1, FETypeV, Helper::Deriv0);
1513 UN deg = Helper::determineDegree( dim-1, FETypeP, Helper::Deriv0)*2 + extraDeg;
1514
1515
1516 Helper::getPhi(phi, weights, dim-1, FETypeP, deg);
1517 Helper::getPhi(phiV, weights, dim-1, FETypeV, deg);
1518
1519 SC detB;
1520 SC absDetB;
1521 SmallMatrix<SC> B(dim);
1522
1523
1524 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
1525 vec_dbl_Type uLocN( weights->size() , -1. );
1526
1527 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1528
1529
1530 SC elScaling;
1531 vec_dbl_Type b(dim);
1532
1533 std::vector<double> valueFunc(dim);
1534 // The second last entry is a placeholder for the surface element flag. It will be set below
1535 SC* paramsFunc = &(funcParameter[0]);
1536 for (UN T=0; T<elements->numberElements(); T++) {
1537 FiniteElement fe = elementsV->getElement( T );
1538 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
1539 for (int surface=0; surface<fe.numSubElements(); surface++) {
1540 FiniteElement feSub = subEl->getElement( surface );
1541 if(subEl->getDimension() == dim-1){
1542 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
1543
1544 vec_int_Type nodeList = feSub.getVectorNodeListNonConst();
1545 vec_int_Type nodeListP = elements->getElement(T).getSubElements()->getElement(surface).getVectorNodeListNonConst();
1546
1547 vec_dbl_Type v_E(dim,1.);
1548 double norm_v_E=1.;
1549 vec_dbl_Type x(dim,0.); //dummy
1550 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
1551
1552 func( &x[0], &valueFunc[0], paramsFunc);
1553 if(valueFunc[0] > 0.){
1554 Helper::computeSurfaceNormal(dim, pointsRep,nodeListP,v_E,norm_v_E);
1555
1556 Helper::buildTransformationSurface( nodeListP, pointsRep, B, b, FETypeP);
1557
1558 elScaling = B.computeScaling( );
1559 for (int w=0; w<phiV->size(); w++){ //quads points
1560 for (int d=0; d<dim; d++) {
1561 uLoc[d][w] = 0.;
1562 for (int i=0; i < phiV->at(0).size(); i++) {
1563 LO index = dim * nodeList[i] + d;
1564 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
1565 }
1566 }
1567 }
1568 for (int w=0; w<phiV->size(); w++){ //quads points
1569 uLocN[w] = 0.;
1570 for (int d=0; d<dim; d++) {
1571 uLocN[w] += uLoc[d][w] *v_E[d] / norm_v_E;
1572 }
1573 }
1574 for (UN i=0; i < phi->at(0).size(); i++) {
1575 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1576 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1577 for (UN j=0; j < value.size(); j++) {
1578 for (UN w=0; w<phi->size(); w++) {
1579 value[j] += weights->at(w) * uLocN[w]* (*phi)[w][j] * (*phi)[w][i] ;
1580 }
1581 value[j] *= elScaling;
1582 indices[j] = GO ( map->getGlobalElement( nodeListP[j] ) );
1583 }
1584
1585 GO row = GO ( map->getGlobalElement( nodeListP[i] ) );
1586 A->insertGlobalValues( row, indices(), value() );
1587 }
1588
1589 }
1590 }
1591 }
1592 }
1593 A->fillComplete();
1594}
1595
1596// Assembling the nonlinear reaction part of Reaction-Diffusion equation
1597// Gerneral function in case of nonlinear reaction function
1598// template <class SC, class LO, class GO, class NO>
1599// void FE<SC,LO,GO,NO>::assemblyReactionTerm(int dim,
1600// std::string FEType,
1601// MatrixPtr_Type &A,
1602// MultiVectorPtr_Type u,
1603// bool callFillComplete,
1604// std::vector<SC>& funcParameter,
1605// RhsFunc_Type reactionFunc){
1606
1607// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1608// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1609
1610// UN FEloc = checkFE(dim,FEType);
1611
1612// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1613
1614// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1615
1616// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1617
1618// vec2D_dbl_ptr_Type phi;
1619// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1620
1621// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1622
1623// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1624// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1625// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1626// extraDeg;
1627
1628// Helper::getPhi(phi, weights, dim, FEType, deg);
1629
1630// // We have a scalar value of concentration in each point
1631// vec_dbl_Type uLoc( weights->size() , -1. );
1632// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1633
1634// std::vector<double> valueFunc(1);
1635
1636// SC* paras = &(funcParameter[0]);
1637
1638// SC detB;
1639// SC absDetB;
1640// SmallMatrix<SC> B(dim);
1641// SmallMatrix<SC> Binv(dim);
1642
1643// for (UN T=0; T<elements->numberElements(); T++) {
1644// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1645// detB = B.computeInverse(Binv);
1646// absDetB = std::fabs(detB);
1647
1648// // Building u
1649// for (int w=0; w<phi->size(); w++){ //quadpoints
1650// uLoc[w] = 0.;
1651// for (int i=0; i < phi->at(0).size(); i++) { // points of element
1652// LO index = elements->getElement(T).getNode(i);
1653// uLoc[w] += uArray[index] * phi->at(w).at(i);
1654// }
1655// }
1656
1657// for (UN i=0; i < phi->at(0).size(); i++) {
1658// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1659// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1660// for (UN j=0; j < value.size(); j++) {
1661// for (UN w=0; w<phi->size(); w++) {
1662// value[j] += weights->at(w) * uLoc[w] * (*phi)[w][i] ;
1663// }
1664// reactionFunc(&value[j], &valueFunc[0] ,paras);
1665
1666// value[j] *= valueFunc[0] * absDetB;
1667// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1668// value[j] = 0.;
1669// }
1670// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1671
1672// }
1673// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1674
1675
1676// A->insertGlobalValues( row, indices(), value() );
1677
1678// }
1679// }
1680
1681// if (callFillComplete)
1682// A->fillComplete();
1683// }
1684
1685
1686// // Assembling the nonlinear reaction part of Reaction-Diffusion equation
1687// template <class SC, class LO, class GO, class NO>
1688// void FE<SC,LO,GO,NO>::assemblyLinearReactionTerm(int dim,
1689// std::string FEType,
1690// MatrixPtr_Type &A,
1691// bool callFillComplete,
1692// std::vector<SC>& funcParameter,
1693// RhsFunc_Type reactionFunc){
1694
1695// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1696// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1697
1698// UN FEloc = checkFE(dim,FEType);
1699
1700// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1701
1702// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1703
1704// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1705
1706// vec2D_dbl_ptr_Type phi;
1707// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1708
1709// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1710// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1711// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1712// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1713// extraDeg;
1714
1715// Helper::getPhi(phi, weights, dim, FEType, deg);
1716
1717// std::vector<double> valueFunc(1);
1718
1719// SC* paras = &(funcParameter[0]);
1720
1721// SC detB;
1722// SC absDetB;
1723// SmallMatrix<SC> B(dim);
1724// SmallMatrix<SC> Binv(dim);
1725
1726// for (UN T=0; T<elements->numberElements(); T++) {
1727// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1728// detB = B.computeInverse(Binv);
1729// absDetB = std::fabs(detB);
1730
1731// for (UN i=0; i < phi->at(0).size(); i++) {
1732// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1733// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1734// for (UN j=0; j < value.size(); j++) {
1735// for (UN w=0; w<phi->size(); w++) {
1736// value[j] += weights->at(w) * (*phi)[w][j] * (*phi)[w][i] ;
1737// }
1738// reactionFunc(&value[j], &valueFunc[0] ,paras);
1739
1740// value[j] *= valueFunc[0] * absDetB;
1741// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1742// value[j] = 0.;
1743// }
1744// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1745
1746// }
1747// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1748
1749// A->insertGlobalValues( row, indices(), value() );
1750
1751// }
1752// }
1753// if (callFillComplete)
1754// A->fillComplete();
1755
1756// A->print();
1757
1758// }
1759
1760// Assembling the nonlinear reaction part of Reaction-Diffusion equation
1761// template <class SC, class LO, class GO, class NO>
1762// void FE<SC,LO,GO,NO>::assemblyDReactionTerm(int dim,
1763// std::string FEType,
1764// MatrixPtr_Type &A,
1765// MultiVectorPtr_Type u,
1766// bool callFillComplete,
1767// std::vector<SC>& funcParameter,
1768// RhsFunc_Type reactionFunc){
1769
1770// //TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
1771// TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1772
1773// UN FEloc = checkFE(dim,FEType);
1774
1775// ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1776
1777// vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1778
1779// MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1780
1781// vec2D_dbl_ptr_Type phi;
1782// vec3D_dbl_ptr_Type dPhi;
1783// vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1784
1785// // TODO: [JK] 2025/04 What is the getting integrated; i.e., what motivates the choice of polynomial degree?
1786// UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
1787// UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) +
1788// Helper::determineDegree( dim, FEType, Helper::Deriv0) +
1789// extraDeg;
1790
1791// Helper::getPhi(phi, weights, dim, FEType, deg);
1792
1793// Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1794
1795// // We have a scalar value of concentration in each point
1796// vec2D_dbl_Type duLoc( weights->size() ,vec_dbl_Type(dim ,-1. ));
1797// Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
1798
1799// std::vector<double> valueFunc(1);
1800
1801// SC* paras = &(funcParameter[0]);
1802
1803// SC detB;
1804// SC absDetB;
1805// SmallMatrix<SC> B(dim);
1806// SmallMatrix<SC> Binv(dim);
1807
1808// for (UN T=0; T<elements->numberElements(); T++) {
1809
1810
1811// Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1812// detB = B.computeInverse(Binv);
1813// absDetB = std::fabs(detB);
1814
1815// vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1816// applyBTinv( dPhi, dPhiTrans, Binv );
1817
1818// for (int w=0; w<dPhiTrans.size(); w++){ //quads points
1819// for (int i=0; i < dPhiTrans[0].size(); i++) {
1820// LO index = elements->getElement(T).getNode(i) ;
1821// for (int d2=0; d2<dim; d2++)
1822// duLoc[w][d2] += uArray[index] * dPhiTrans[w][i][d2];
1823// }
1824
1825// }
1826
1827
1828// for (UN i=0; i < phi->at(0).size(); i++) {
1829// Teuchos::Array<SC> value( phi->at(0).size(), 0. );
1830// Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
1831// for (UN j=0; j < value.size(); j++) {
1832// for (UN d2=0; d2<dim; d2++){
1833// for (UN w=0; w<phi->size(); w++) {
1834// value[j] += weights->at(w) * duLoc[w][d2] * (*phi)[w][i] ;
1835// }
1836// }
1837// reactionFunc(&value[j], &valueFunc[0] ,paras);
1838
1839// value[j] *= valueFunc[0] * absDetB;
1840// if (setZeros_ && std::fabs(value[j]) < myeps_) {
1841// value[j] = 0.;
1842// }
1843// indices[j] = GO( map->getGlobalElement( elements->getElement(T).getNode(j) ));
1844
1845// }
1846// GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
1847// A->insertGlobalValues( row, indices(), value() );
1848// }
1849// }
1850
1851// if (callFillComplete)
1852// A->fillComplete();
1853// }
1854
1864template <class SC, class LO, class GO, class NO>
1866 std::string FEType,
1867 int degree,
1868 int dofs,
1869 BlockMatrixPtr_Type &A,
1870 bool callFillComplete,
1871 int FELocExternal){
1872 ParameterListPtr_Type params = Teuchos::getParametersFromXmlFile("parametersProblemLaplace.xml");
1873
1874 UN FEloc = checkFE(dim,FEType);
1875 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1876 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1877 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1878 vec2D_dbl_Type nodes;
1879 int numNodes=dim+1;
1880 if(FEType == "P2"){
1881 numNodes= 6;
1882 if(dim==3)
1883 numNodes=10;
1884 }
1885 tuple_disk_vec_ptr_Type problemDisk = Teuchos::rcp(new tuple_disk_vec_Type(0));
1886 tuple_ssii_Type vel ("Laplace",FEType,dofs,numNodes);
1887 problemDisk->push_back(vel);
1888 if(assemblyFEElements_.size()== 0)
1889 initAssembleFEElements("Laplace",problemDisk,elements, params,pointsRep,domainVec_.at(0)->getElementMap());
1890 else if(assemblyFEElements_.size() != elements->numberElements())
1891 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Number Elements not the same as number assembleFE elements." );
1892 for (UN T=0; T<elements->numberElements(); T++) {
1893 assemblyFEElements_[T]->assembleJacobian();
1894 SmallMatrixPtr_Type elementMatrix = assemblyFEElements_[T]->getJacobian();
1895 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0, problemDisk);
1896
1897 }
1898 if(callFillComplete)
1899 A->getBlock(0,0)->fillComplete();
1900}
1901
1902
1903template <class SC, class LO, class GO, class NO>
1904void FE<SC,LO,GO,NO>::assemblyLaplaceDiffusion(int dim,
1905 std::string FEType,
1906 int degree,
1907 MatrixPtr_Type &A,
1908 vec2D_dbl_Type diffusionTensor,
1909 bool callFillComplete,
1910 int FELocExternal){
1911 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
1912 UN FEloc;
1913 if (FELocExternal<0)
1914 FEloc = checkFE(dim,FEType);
1915 else
1916 FEloc = FELocExternal;
1917
1918 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
1919
1920 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
1921
1922 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
1923
1924 vec3D_dbl_ptr_Type dPhi;
1925 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
1926
1927 // inner( grad(u) , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
1928 // The diffusion tensor is constant and, thus, does not require a higher-order quadrature rule.
1929 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);//+1;
1930 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
1931
1932 SC detB;
1933 SC absDetB;
1934 SmallMatrix<SC> B(dim);
1935 SmallMatrix<SC> Binv(dim);
1936 GO glob_i, glob_j;
1937 vec_dbl_Type v_i(dim);
1938 vec_dbl_Type v_j(dim);
1939
1940
1941 SmallMatrix<SC> diffusionT(dim);
1942 // Linear Diffusion Tensor
1943 if(diffusionTensor.size()==0 || diffusionTensor.size() < dim ){
1944 vec2D_dbl_Type diffusionTensor(3,vec_dbl_Type(3,0));
1945 for(int i=0; i< dim; i++){
1946 diffusionTensor[i][i]=1.;
1947 }
1948 }
1949
1950 for(int i=0; i< dim; i++){
1951 for(int j=0; j<dim; j++){
1952 diffusionT[i][j]=diffusionTensor[i][j];
1953 }
1954 }
1955 //Teuchos::ArrayRCP< SC > linearDiff = diffusionTensor->getDataNonConst( 0 );
1956 //std::cout << "Assembly Info " << "num Elements " << elements->numberElements() << " num Nodes " << pointsRep->size() << std::endl;
1957 for (UN T=0; T<elements->numberElements(); T++) {
1958
1959 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
1960 detB = B.computeInverse(Binv);
1961 absDetB = std::fabs(detB);
1962
1963 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1964 applyBTinv( dPhi, dPhiTrans, Binv );
1965
1966 vec3D_dbl_Type dPhiTransDiff( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
1967 applyDiff( dPhiTrans, dPhiTransDiff, diffusionT );
1968
1969 for (UN i=0; i < dPhiTrans[0].size(); i++) {
1970 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
1971 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
1972
1973 for (UN j=0; j < value.size(); j++) {
1974 for (UN w=0; w<dPhiTrans.size(); w++) {
1975 for (UN d=0; d<dim; d++){
1976 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTransDiff[w][j][d];
1977 }
1978 }
1979 value[j] *= absDetB;
1980 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
1981 if (setZeros_ && std::fabs(value[j]) < myeps_) {
1982 value[j] = 0.;
1983 }
1984 }
1985 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
1986
1987 A->insertGlobalValues( row, indices(), value() );
1988 }
1989
1990
1991 }
1992 if (callFillComplete)
1993 A->fillComplete();
1994
1995}
1996
1997template <class SC, class LO, class GO, class NO>
1998void FE<SC,LO,GO,NO>::applyDiff( vec3D_dbl_Type& dPhiIn,
1999 vec3D_dbl_Type& dPhiOut,
2000 SmallMatrix<SC>& diffT){
2001 UN dim = diffT.size();
2002 for (UN w=0; w<dPhiIn.size(); w++){
2003 for (UN i=0; i < dPhiIn[w].size(); i++) {
2004 for (UN d1=0; d1<dim; d1++) {
2005 for (UN d2=0; d2<dim; d2++) {
2006 dPhiOut[w][i][d1] += dPhiIn[w][i][d2]* diffT[d2][d1];
2007 }
2008 }
2009 }
2010 }
2011}
2012
2013// template <class SC, class LO, class GO, class NO>
2014// void FE<SC,LO,GO,NO>::assemblyAceGenTPM( MatrixPtr_Type &A00,
2015// MatrixPtr_Type &A01,
2016// MatrixPtr_Type &A10,
2017// MatrixPtr_Type &A11,
2018// MultiVectorPtr_Type &F0,
2019// MultiVectorPtr_Type &F1,
2020// MapPtr_Type &mapRepeated1,
2021// MapPtr_Type &mapRepeated2,
2022// ParameterListPtr_Type parameterList,
2023// MultiVectorPtr_Type u_repeatedNewton,
2024// MultiVectorPtr_Type p_repeatedNewton,
2025// MultiVectorPtr_Type u_repeatedTime,
2026// MultiVectorPtr_Type p_repeatedTime,
2027// bool update,
2028// bool updateHistory)
2029// {
2030
2031
2032// std::string tpmType = parameterList->sublist("Parameter").get("TPM Type","Biot");
2033
2034// int dim = domainVec_[0]->getDimension();
2035// int idata = 1; //= we should init this
2036// int ic = -1; int ng = -1;
2037
2038// //ed.hp:history previous (timestep); previous solution (velocity and acceleration)
2039// //ed.ht:? same length as hp
2040// ElementsPtr_Type elements1 = domainVec_[0]->getElementsC();
2041// ElementsPtr_Type elements2 = domainVec_[1]->getElementsC();
2042
2043// int sizeED = 24; /* 2D case for P2 elements:
2044// 12 velocities, 12 accelerations (2 dof per P2 node)
2045// */
2046// if (dim==3)
2047// sizeED = 60;/* 3D case for P2 elements:
2048// 30 velocities, 30 accelerations (3 dof per P2 node)
2049// */
2050// if (ed_.size()==0){
2051// for (UN T=0; T<elements1->numberElements(); T++)
2052// ed_.push_back( Teuchos::rcp(new DataElement( sizeED )) );
2053// }
2054
2055// std::vector<ElementSpec> es_vec( parameterList->sublist("Parameter").get("Number of materials",1) , ElementSpec());
2056// vec2D_dbl_Type dataVec( parameterList->sublist("Parameter").get("Number of materials",1), vec_dbl_Type(6,0.) );
2057
2058// for (int i=0; i<dataVec.size(); i++) {
2059// if (tpmType == "Biot") {
2060// if (dim==2) {
2061// dataVec[i][0] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2062// dataVec[i][1] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2063// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
2064// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
2065// dataVec[i][4] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
2066// dataVec[i][5] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2067// }
2068// else if (dim==3) {
2069// dataVec[i].resize(12);
2070// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),2.e5);
2071// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2072// dataVec[i][2] = 0.; //body force x
2073// dataVec[i][3] = 0.; //body force y
2074// dataVec[i][4] = parameterList->sublist("Parameter").get("body force z"+std::to_string(i+1),0.);; //body force z
2075// dataVec[i][5] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.67);
2076// dataVec[i][6] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),0.01);
2077// dataVec[i][7] = 2000.; //effective density solid
2078// dataVec[i][8] = 1000.; //effective density fluid?
2079// dataVec[i][9] = 9.81; // gravity
2080// dataVec[i][10] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2081// dataVec[i][11] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2082// }
2083// }
2084
2085
2086// else if (tpmType == "Biot-StVK") {
2087// dataVec[i][0] = parameterList->sublist("Parameter").get("Youngs modulus material"+std::to_string(i+1),60.e6);
2088// dataVec[i][1] = parameterList->sublist("Parameter").get("Poisson ratio material"+std::to_string(i+1),0.3);
2089// dataVec[i][2] = parameterList->sublist("Parameter").get("initial volume fraction solid material"+std::to_string(i+1),0.5); //do we need this?
2090// dataVec[i][3] = parameterList->sublist("Parameter").get("Darcy parameter material"+std::to_string(i+1),1.e-2);
2091// dataVec[i][4] = parameterList->sublist("Timestepping Parameter").get("Newmark gamma",0.5);
2092// dataVec[i][5] = parameterList->sublist("Timestepping Parameter").get("Newmark beta",0.25);
2093// }
2094// }
2095
2096// for (int i=0; i<es_vec.size(); i++){
2097// if(tpmType == "Biot"){
2098// if (dim==2)
2099// this->SMTSetElSpecBiot(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2100// else if(dim==3)
2101// this->SMTSetElSpecBiot3D(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2102// }
2103// else if(tpmType == "Biot-StVK")
2104// this->SMTSetElSpecBiotStVK(&es_vec[i] ,&idata, ic, ng, dataVec[i]);
2105// }
2106// LO elementSizePhase = elements1->nodesPerElement();
2107// LO sizePhase = dim * elementSizePhase;
2108// LO sizePressure = elements2->nodesPerElement();
2109// GO sizePhaseGlobal = A00->getMap()->getMaxAllGlobalIndex()+1;
2110// int workingVectorSize;
2111// if(tpmType == "Biot"){
2112// if (dim==2)
2113// workingVectorSize = 5523;
2114// else if(dim==3)
2115// workingVectorSize = 1817;
2116// }
2117// else if(tpmType == "Biot-StVK")
2118// workingVectorSize = 5223;
2119
2120// double* v = new double [workingVectorSize];
2121
2122// // nd sind Nodalwerte, Anzahl an structs in nd sollte den Knoten entsprechen, bei P2-P1 in 2D also 9
2123// // In X stehen die Koordinaten, X[0] ist x-Koordinate, X[1] ist y-Koordinate, etc.
2124// // nd->X[0]
2125// // at ist die Loesung im letzten Newtonschritt.
2126// // nd[0]->at[0];
2127// // ap ist die Loesung im letzten Zeitschritt.
2128// // nd[0]->ap[0]
2129// // 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.
2130
2131// std::vector<double> rdata(RD_TimeIncrement+1, 0.);
2132
2133// rdata[RD_TimeIncrement] = parameterList->sublist("Timestepping Parameter").get("dt",0.01);
2134
2135// NodeSpec *ns=NULL;//dummy not need in SKR
2136
2137// NodeData** nd = new NodeData*[ elementSizePhase + sizePressure ];
2138
2139// for (int i=0; i<elementSizePhase + sizePressure; i++){
2140// nd[i] = new NodeData();
2141// }
2142
2143// int numNodes = elementSizePhase + sizePressure;
2144
2145// vec2D_dbl_Type xFull( numNodes, vec_dbl_Type(dim,0.) );
2146// vec2D_dbl_Type atFull( numNodes, vec_dbl_Type(dim,0.) );
2147// vec2D_dbl_Type apFull( numNodes, vec_dbl_Type(dim,0.) );
2148
2149// for (int i=0; i<elementSizePhase + sizePressure; i++) {
2150// nd[i]->X = &(xFull[i][0]);
2151// nd[i]->at = &(atFull[i][0]);
2152// nd[i]->ap = &(apFull[i][0]);
2153// }
2154
2155// GO offsetMap1 = dim * mapRepeated1->getMaxAllGlobalIndex()+1;
2156// vec2D_dbl_ptr_Type pointsRepU = domainVec_.at(0)->getPointsRepeated();
2157// vec2D_dbl_ptr_Type pointsRepP = domainVec_.at(1)->getPointsRepeated();
2158
2159// Teuchos::ArrayRCP< const SC > uArrayNewton = u_repeatedNewton->getData(0);
2160// Teuchos::ArrayRCP< const SC > pArrayNewton = p_repeatedNewton->getData(0);
2161// Teuchos::ArrayRCP< const SC > uArrayTime = u_repeatedTime->getData(0);
2162// Teuchos::ArrayRCP< const SC > pArrayTime = p_repeatedTime->getData(0);
2163
2164// double** mat = new double*[sizePhase+sizePressure];
2165// for (int i=0; i<sizePhase+sizePressure; i++){
2166// mat[i] = new double[sizePhase+sizePressure];
2167// }
2168
2169// Teuchos::ArrayRCP<SC> fValues0 = F0->getDataNonConst(0);
2170// Teuchos::ArrayRCP<SC> fValues1 = F1->getDataNonConst(0);
2171
2172// // Element loop
2173
2174// ElementData ed = ElementData();
2175// for (UN T=0; T<elements1->numberElements(); T++) {
2176
2177// std::vector<double> tmpHp = ed_[T]->getHp(); // Dies sind die alten Daten
2178// 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.
2179// ed.hp = &tmpHp[0];
2180// ed.ht = &tmpHt[0];
2181
2182// int materialFlag = elements1->getElement(T).getFlag();
2183// TEUCHOS_TEST_FOR_EXCEPTION( materialFlag>es_vec.size()-1, std::runtime_error, "There are not enought material parameters initialized." ) ;
2184// int counter=0;
2185// //Newtonloesung at und Zeitschrittloesung ap
2186// for (int j=0; j<elementSizePhase; j++) {
2187// for (int d=0; d<dim; d++) {
2188// LO index = dim * elements1->getElement(T).getNode(j)+d;//dim * elements1->at(T).at( j ) + d;
2189// atFull[j][d] = uArrayNewton[index];
2190// apFull[j][d] = uArrayTime[index];
2191// }
2192// }
2193// for (int j=0; j<sizePressure; j++) {
2194// LO index = elements2->getElement(T).getNode(j);//elements2->at(T).at( j );
2195// atFull[elementSizePhase+j][0] = pArrayNewton[index];
2196// apFull[elementSizePhase+j][0] = pArrayTime[index];
2197// }
2198
2199// //Nodes
2200// for (int j=0; j<elementSizePhase; j++ ) {
2201// LO index = elements1->getElement(T).getNode(j);
2202// for (int d=0; d<dim; d++) {
2203// xFull[j][d] = (*pointsRepU)[index][d];
2204// }
2205// }
2206// for (int j=0; j<sizePressure; j++ ) {
2207// LO index = elements2->getElement(T).getNode(j);
2208// for (int d=0; d<dim; d++) {
2209// xFull[elementSizePhase+j][d] = (*pointsRepP)[index][d];
2210// }
2211// }
2212// vec_dbl_Type p( sizePhase+sizePressure , 0. );
2213
2214// for (int i=0; i<sizePhase+sizePressure; i++){
2215// for (int j=0; j<sizePhase+sizePressure; j++)
2216// mat[i][j] = 0.;
2217// }
2218// // element assembly
2219// if(tpmType == "Biot"){
2220// if(dim==2)
2221// this->SKR_Biot( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2222// else if (dim==3)
2223// this->SKR_Biot3D( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2224// }
2225// else if(tpmType == "Biot-StVK")
2226// this->SKR_Biot_StVK( v, &es_vec[materialFlag], &ed, &ns, nd , &rdata[0], &idata, &p[0], mat );
2227
2228// if (updateHistory)
2229// ed_[T]->setHp( ed.ht );
2230
2231// if (update) {
2232
2233// // A00 & A01
2234// for (UN i=0; i < sizePhase; i++) {
2235// Teuchos::Array<SC> value00( sizePhase, 0. );
2236// Teuchos::Array<GO> indices00( sizePhase, 0 );
2237// for (UN j=0; j < value00.size(); j++) {
2238
2239// value00[j] = mat[i][j];
2240
2241// LO tmpJ = j/dim;
2242// LO index = elements1->getElement(T).getNode(tmpJ);
2243// if (j%dim==0)
2244// indices00[j] = dim * mapRepeated1->getGlobalElement( index );
2245// else if (j%dim==1)
2246// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
2247// else if (j%dim==2)
2248// indices00[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
2249// }
2250
2251// Teuchos::Array<SC> value01( sizePressure, 0. );
2252// Teuchos::Array<GO> indices01( sizePressure, 0 );
2253
2254// for (UN j=0; j < value01.size(); j++) {
2255// value01[j] = mat[i][sizePhase+j];
2256// LO index = elements2->getElement(T).getNode(j);
2257// indices01[j] = mapRepeated2->getGlobalElement( index );
2258// }
2259
2260// GO row;
2261// LO tmpI = i/dim;
2262// LO index = elements1->getElement(T).getNode(tmpI);
2263// if (i%dim==0)
2264// row = dim * mapRepeated1->getGlobalElement( index );
2265// else if (i%dim==1)
2266// row = dim * mapRepeated1->getGlobalElement( index ) + 1;
2267// else if (i%dim==2)
2268// row = dim * mapRepeated1->getGlobalElement( index ) + 2;
2269
2270// A00->insertGlobalValues( row, indices00(), value00() );
2271// A01->insertGlobalValues( row, indices01(), value01() );
2272
2273// if (i%dim==0)
2274// fValues0[ dim*index ] += p[ i ];
2275// else if (i%dim==1)
2276// fValues0[ dim*index+1 ] += p[ i ];
2277// else if (i%dim==2)
2278// fValues0[ dim*index+2 ] += p[ i ];
2279// }
2280// // A10 & A11
2281// for (UN i=0; i < sizePressure; i++) {
2282// Teuchos::Array<SC> value10( sizePhase , 0. );
2283// Teuchos::Array<GO> indices10( sizePhase , 0 );
2284// for (UN j=0; j < value10.size(); j++) {
2285// value10[j] = mat[sizePhase+i][j];
2286
2287// LO tmpJ = j/dim;
2288// LO index = elements1->getElement(T).getNode(tmpJ);
2289// if (j%dim==0)
2290// indices10[j] = dim * mapRepeated1->getGlobalElement( index );
2291// else if (j%dim==1)
2292// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 1;
2293// else if (j%dim==2)
2294// indices10[j] = dim * mapRepeated1->getGlobalElement( index ) + 2;
2295// }
2296
2297// Teuchos::Array<SC> value11( sizePressure, 0. );
2298// Teuchos::Array<GO> indices11( sizePressure, 0 );
2299// for (UN j=0; j < value11.size(); j++) {
2300// value11[j] = mat[sizePhase+i][sizePhase+j];
2301
2302// LO index = elements2->getElement(T).getNode(j);
2303// indices11[j] = mapRepeated2->getGlobalElement( index );
2304// }
2305
2306
2307// LO index2 = elements2->getElement(T).getNode(i);
2308// GO row = mapRepeated2->getGlobalElement( index2 );
2309// A10->insertGlobalValues( row, indices10(), value10() );
2310// A11->insertGlobalValues( row, indices11(), value11() );
2311
2312// fValues1[ index2 ] += p[ sizePhase + i ];
2313// }
2314// }
2315// }
2316
2317// for (int i=0; i<sizePhase+sizePressure; i++)
2318// delete [] mat[i];
2319// delete [] mat;
2320
2321// delete [] v;
2322
2323// for (int i=0; i<elementSizePhase+sizePressure; i++)
2324// delete nd[i];
2325
2326// delete [] nd;
2327
2328
2329// A00->fillComplete( A00->getMap("row"), A00->getMap("row") );
2330// A01->fillComplete( A10->getMap("row"), A00->getMap("row") );
2331// A10->fillComplete( A00->getMap("row"), A10->getMap("row") );
2332// A11->fillComplete( A10->getMap("row"), A10->getMap("row") );
2333
2334// }
2335
2336template <class SC, class LO, class GO, class NO>
2337void FE<SC,LO,GO,NO>::assemblyMass(int dim,
2338 std::string FEType,
2339 std::string fieldType,
2340 MatrixPtr_Type &A,
2341 bool callFillComplete){
2342
2343 TEUCHOS_TEST_FOR_EXCEPTION( FEType == "P0", std::logic_error, "Not implemented for P0" );
2344 UN FEloc = checkFE(dim,FEType);
2345 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2346
2347 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2348
2349 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2350
2351 vec2D_dbl_ptr_Type phi;
2352 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2353
2354 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
2355 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2356
2357 Helper::getPhi( phi, weights, dim, FEType, deg );
2358
2359 SC detB;
2360 SC absDetB;
2361 SmallMatrix<SC> B(dim);
2362 GO glob_i, glob_j;
2363 vec_dbl_Type v_i(dim);
2364 vec_dbl_Type v_j(dim);
2365
2366 for (UN T=0; T<elements->numberElements(); T++) {
2367
2368 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2369 detB = B.computeDet( );
2370 absDetB = std::fabs(detB);
2371
2372 for (UN i=0; i < phi->at(0).size(); i++) {
2373 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2374 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2375 for (UN j=0; j < value.size(); j++) {
2376 for (UN w=0; w<phi->size(); w++) {
2377 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2378
2379 }
2380 value[j] *= absDetB;
2381 if (!fieldType.compare("Scalar")) {
2382 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2383 }
2384
2385 }
2386 if (!fieldType.compare("Scalar")) {
2387 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2388 A->insertGlobalValues( row, indices(), value() );
2389 }
2390 else if (!fieldType.compare("Vector")) {
2391 for (UN d=0; d<dim; d++) {
2392 for (int j=0; j<indices.size(); j++) {
2393 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2394 }
2395 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2396 A->insertGlobalValues( row, indices(), value() );
2397 }
2398 }
2399 else
2400 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
2401 }
2402
2403 }
2404
2405 if (callFillComplete)
2406 A->fillComplete();
2407}
2408
2409
2410// Ueberladung der Assemblierung der Massematrix fuer FSI, da
2411// checkFE sonst auch fuer das Strukturproblem FEloc = 1 liefert (= Fluid)
2412// und somit die welche domain und Map in der Assemblierung genutzt wird.
2413template <class SC, class LO, class GO, class NO>
2414void FE<SC,LO,GO,NO>::assemblyMass(int dim,
2415 std::string FEType,
2416 std::string fieldType,
2417 MatrixPtr_Type &A,
2418 int FEloc, // 0 = Fluid, 2 = Struktur
2419 bool callFillComplete){
2420
2421 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2422
2423 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2424
2425 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2426
2427 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2428
2429 vec2D_dbl_ptr_Type phi;
2430 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2431
2432 // inner( phi_i , phi_j ) has twice the polyonimial degree than phi_i and phi_j, respectively.
2433 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
2434
2435 Helper::getPhi( phi, weights, dim, FEType, deg );
2436
2437 SC detB;
2438 SC absDetB;
2439 SmallMatrix<SC> B(dim);
2440 GO glob_i, glob_j;
2441 vec_dbl_Type v_i(dim);
2442 vec_dbl_Type v_j(dim);
2443
2444 for (UN T=0; T<elements->numberElements(); T++) {
2445
2446 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2447 detB = B.computeDet( );
2448 absDetB = std::fabs(detB);
2449
2450 for (UN i=0; i < phi->at(0).size(); i++) {
2451 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
2452 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
2453 for (UN j=0; j < value.size(); j++) {
2454 for (UN w=0; w<phi->size(); w++) {
2455 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
2456 }
2457 value[j] *= absDetB;
2458 if (!fieldType.compare("Scalar")) {
2459 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2460 }
2461
2462 }
2463 if (!fieldType.compare("Scalar")) {
2464 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2465 A->insertGlobalValues( row, indices(), value() );
2466 }
2467 else if (!fieldType.compare("Vector")) {
2468 for (UN d=0; d<dim; d++) {
2469 for (int j=0; j<indices.size(); j++) {
2470 indices[j] = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2471 }
2472 GO row = (GO) ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2473 A->insertGlobalValues( row, indices(), value() );
2474 }
2475 }
2476 else
2477 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Specify valid vieldType for assembly of mass matrix.");
2478 }
2479
2480
2481 }
2482 if (callFillComplete)
2483 A->fillComplete();
2484}
2485
2486
2487template <class SC, class LO, class GO, class NO>
2488void FE<SC,LO,GO,NO>::assemblyLaplace(int dim,
2489 std::string FEType,
2490 int degree,
2491 MatrixPtr_Type &A,
2492 bool callFillComplete,
2493 int FELocExternal){
2494 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2495 UN FEloc;
2496 if (FELocExternal<0)
2497 FEloc = checkFE(dim,FEType);
2498 else
2499 FEloc = FELocExternal;
2500
2501 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2502
2503 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2504
2505 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2506
2507 vec3D_dbl_ptr_Type dPhi;
2508 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2509
2510 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2511 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2512
2513 SC detB;
2514 SC absDetB;
2515 SmallMatrix<SC> B(dim);
2516 SmallMatrix<SC> Binv(dim);
2517 GO glob_i, glob_j;
2518 vec_dbl_Type v_i(dim);
2519 vec_dbl_Type v_j(dim);
2520
2521 for (UN T=0; T<elements->numberElements(); T++) {
2522
2523 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2524 detB = B.computeInverse(Binv);
2525 absDetB = std::fabs(detB);
2526
2527 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2528 applyBTinv( dPhi, dPhiTrans, Binv );
2529 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2530 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2531 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2532 for (UN j=0; j < value.size(); j++) {
2533 for (UN w=0; w<dPhiTrans.size(); w++) {
2534 for (UN d=0; d<dim; d++){
2535 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
2536 }
2537 }
2538 value[j] *= absDetB;
2539 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
2540 }
2541 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
2542
2543 A->insertGlobalValues( row, indices(), value() );
2544 }
2545
2546
2547 }
2548 if (callFillComplete)
2549 A->fillComplete();
2550
2551}
2552
2553template <class SC, class LO, class GO, class NO>
2554void FE<SC,LO,GO,NO>::assemblyLaplaceVecField(int dim,
2555 std::string FEType,
2556 int degree,
2557 MatrixPtr_Type &A,
2558 bool callFillComplete){
2559
2560 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P1-disc" || FEType == "P0",std::logic_error, "Not implemented for P0 or P1-disc");
2561 UN FEloc = checkFE(dim,FEType);
2562
2563 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2564
2565 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2566
2567 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2568
2569 vec3D_dbl_ptr_Type dPhi;
2570 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2571
2572 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2573
2574 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2575
2576 SC detB;
2577 SC absDetB;
2578 SmallMatrix<SC> B(dim);
2579 SmallMatrix<SC> Binv(dim);
2580 GO glob_i, glob_j;
2581 vec_dbl_Type v_i(dim);
2582 vec_dbl_Type v_j(dim);
2583
2584
2585 for (UN T=0; T<elements->numberElements(); T++) {
2586
2587 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
2588 detB = B.computeInverse(Binv);
2589 absDetB = std::fabs(detB);
2590
2591 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
2592 applyBTinv( dPhi, dPhiTrans, Binv );
2593
2594 for (UN i=0; i < dPhiTrans[0].size(); i++) {
2595 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
2596 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
2597 for (UN j=0; j < value.size(); j++) {
2598 for (UN w=0; w<dPhiTrans.size(); w++) {
2599 for (UN d=0; d<dim; d++)
2600 value[j] += weights->at(w) * dPhiTrans[w][i][d] * dPhiTrans[w][j][d];
2601 }
2602 value[j] *= absDetB;
2603 if (setZeros_ && std::fabs(value[j]) < myeps_) {
2604 value[j] = 0.;
2605 }
2606 }
2607 for (UN d=0; d<dim; d++) {
2608 for (UN j=0; j < indices.size(); j++)
2609 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2610
2611 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2612 A->insertGlobalValues( row, indices(), value() );
2613 }
2614 }
2615 }
2616 if (callFillComplete)
2617 A->fillComplete();
2618}
2619//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.
2620template <class SC, class LO, class GO, class NO>
2621void FE<SC,LO,GO,NO>::assemblyLaplaceVecFieldV2(int dim,
2622 std::string FEType,
2623 int degree,
2624 MatrixPtr_Type &A,
2625 bool callFillComplete){
2626
2627 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
2628 UN FEloc = checkFE(dim,FEType);
2629
2630 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2631
2632 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2633
2634 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2635
2636 vec3D_dbl_ptr_Type dPhi;
2637 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2638
2639 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2640
2641 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2642
2643 Teuchos::BLAS<int, SC> teuchosBLAS;
2644
2645 int nmbQuadPoints = dPhi->size();
2646 int nmbScalarDPhi = dPhi->at(0).size();
2647 int nmbAllDPhi = nmbScalarDPhi * dim;
2648 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2649 int sizeLocStiff = dim*dim;
2650 Teuchos::Array<SmallMatrix<double> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<double>(dim) );
2651 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2652
2653
2654 SC detB;
2655 SC absDetB;
2656 SmallMatrix<SC> B(dim);
2657 SmallMatrix<SC> Binv(dim);
2658 GO glob_i, glob_j;
2659 vec_dbl_Type v_i(dim);
2660 vec_dbl_Type v_j(dim);
2661
2662 for (UN T=0; T<elements->numberElements(); T++) {
2663
2664 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2665 detB = B.computeInverse(Binv);
2666 absDetB = std::fabs(detB);
2667
2668 Teuchos::Array<SmallMatrix<double> > allDPhiMatTrans( dPhiMat.size(), SmallMatrix<double>() );
2669
2670 for (int i=0; i<allDPhiMatTrans.size(); i++) {
2671 SmallMatrix<double> res = dPhiMat[i] * Binv;
2672 allDPhiMatTrans[i] = res;
2673 }
2674
2675 SmallMatrix<double> locStiffMat( nmbAllDPhi, 0. );
2676
2677 for (int p=0; p<nmbQuadPoints; p++){
2678
2679 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
2680
2681 int offset = p * nmbAllDPhi;
2682 int offsetInArray = 0;
2683 for (int i=0; i<nmbAllDPhi; i++) {
2684 fillMatrixArray( allDPhiMatTrans[ offset + i ], allDPhiBlas, "rows",offsetInArray );
2685 offsetInArray += sizeLocStiff;
2686 }
2687
2688 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
2689
2690 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);
2691
2692 for (int i=0; i<nmbAllDPhi; i++) {
2693 for (int j=0; j<nmbAllDPhi; j++) {
2694 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
2695 }
2696 }
2697
2698 delete [] allDPhiBlas;
2699 delete [] locStiffMatBlas;
2700
2701 }
2702
2703 for (UN i=0; i < nmbScalarDPhi; i++) {
2704 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
2705 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
2706 for (UN d=0; d<dim; d++) {
2707 for (UN j=0; j < nmbScalarDPhi; j++){
2708 value[ j * dim + d ] = absDetB * locStiffMat[dim * i + d][j];
2709 indices[ j * dim + d ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
2710 }
2711 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
2712 A->insertGlobalValues( row, indices(), value() );
2713 }
2714 }
2715 }
2716 if (callFillComplete)
2717 A->fillComplete();
2718}
2719
2735
2736template <class SC, class LO, class GO, class NO>
2738 int dim, std::string FEType, int degree, MultiVectorPtr_Type u_rep,
2739 BlockMatrixPtr_Type &A, BlockMultiVectorPtr_Type &resVec,
2740 ParameterListPtr_Type params, std::string assembleMode, bool callFillComplete,
2741 int FELocExternal) {
2742
2743 ElementsPtr_Type elements = this->domainVec_.at(0)->getElementsC();
2744
2745 // Only scalar laplace
2746 int dofs = 1;
2747
2748 vec2D_dbl_ptr_Type pointsRep = this->domainVec_.at(0)->getPointsRepeated();
2749 MapConstPtr_Type map = this->domainVec_.at(0)->getMapRepeated();
2750
2751 vec_dbl_Type solution_u;
2752 vec_dbl_ptr_Type rhsVec;
2753
2754 int numNodes = 3;
2755 if (FEType == "P2") {
2756 numNodes = 6;
2757 }
2758 if (dim == 3) {
2759 numNodes = 4;
2760 if (FEType == "P2") {
2761 numNodes = 10;
2762 }
2763 }
2764
2765 // Tupel construction follows follwing pattern:
2766 // std::string: Physical Entity (i.e. Velocity) , std::string: Discretisation (i.e.
2767 // "P2"), int: Degrees of Freedom per Node, int: Number of Nodes per
2768 // element)
2769 tuple_disk_vec_ptr_Type problemDisk =
2770 Teuchos::rcp(new tuple_disk_vec_Type(0));
2771 tuple_ssii_Type temp("Solution", FEType, dofs, numNodes);
2772 problemDisk->push_back(temp);
2773
2774 // Construct an assembler for each element if not already done
2775 if (assemblyFEElements_.size() == 0) {
2776 initAssembleFEElements("NonLinearLaplace", problemDisk, elements, params, pointsRep, domainVec_.at(0)->getElementMap());
2777 } else if (assemblyFEElements_.size() != elements->numberElements()) {
2778 TEUCHOS_TEST_FOR_EXCEPTION(
2779 true, std::logic_error,
2780 "Number Elements not the same as number assembleFE elements.");
2781 }
2782
2783 MultiVectorPtr_Type resVec_u;
2784 BlockMultiVectorPtr_Type resVecRep;
2785
2786 if (assembleMode != "Rhs") {
2787 // add new or overwrite existing block (0,0) of system matrix
2788 // This is done in specific problem class for most other problems
2789 // Placing it here instead as more fitting
2790 auto A_block_zero_zero = Teuchos::rcp(
2791 new Matrix_Type(this->domainVec_.at(0)->getMapUnique(), this->domainVec_.at(0)->getApproxEntriesPerRow()));
2792
2793 A->addBlock(A_block_zero_zero, 0, 0);
2794 } else {
2795 // Or same for the residual vector
2796 resVec_u = Teuchos::rcp(new MultiVector_Type(map, 1));
2797 resVecRep = Teuchos::rcp(new BlockMultiVector_Type(1));
2798 resVecRep->addBlock(resVec_u, 0);
2799 }
2800 // Call assembly routines on each element
2801 for (UN T = 0; T < assemblyFEElements_.size(); T++) {
2802 vec_dbl_Type solution(0);
2803
2804 // Update solution on the element
2805 solution_u = getSolution(elements->getElement(T).getVectorNodeList(),
2806 u_rep, dofs);
2807 solution.insert(solution.end(), solution_u.begin(), solution_u.end());
2808 assemblyFEElements_[T]->updateSolution(solution);
2809
2810 if (assembleMode == "Jacobian") {
2811 SmallMatrixPtr_Type elementMatrix;
2812 assemblyFEElements_[T]->assembleJacobian();
2813 elementMatrix = assemblyFEElements_[T]->getJacobian();
2814 // Insert (additive) the local element Jacobian into the global
2815 // matrix
2816 assemblyFEElements_[T]
2817 ->advanceNewtonStep(); // n genereal non linear solver step
2818 addFeBlock(A, elementMatrix, elements->getElement(T), map, 0, 0,
2819 problemDisk);
2820 }
2821
2822 if (assembleMode == "Rhs") {
2823 assemblyFEElements_[T]->assembleRHS();
2824 rhsVec = assemblyFEElements_[T]->getRHS();
2825 // Name RHS comes from solving linear systems
2826 // For nonlinear systems RHS synonymous to residual
2827 // Insert (additive) the updated residual into the global residual
2828 // vector
2829 addFeBlockMv(resVecRep, rhsVec, elements->getElement(T), dofs);
2830 }
2831 }
2832 if (callFillComplete && assembleMode != "Rhs") {
2833 // Signal that editing A has finished. This causes the entries of A to
2834 // be redistributed across the MPI ranks
2835 A->getBlock(0, 0)->fillComplete(domainVec_.at(0)->getMapUnique(),
2836 domainVec_.at(0)->getMapUnique());
2837 }
2838 if (assembleMode == "Rhs") {
2839 // Export from overlapping residual to unique residual
2840 MultiVectorPtr_Type resVecUnique = Teuchos::rcp(
2841 new MultiVector_Type(domainVec_.at(0)->getMapUnique(), 1));
2842 resVecUnique->putScalar(0.);
2843 resVecUnique->exportFromVector(resVec_u, true, "Add");
2844 resVec->addBlock(resVecUnique, 0);
2845 }
2846}
2847
2848
2849template <class SC, class LO, class GO, class NO>
2850void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAndStressAceFEM(int dim,
2851 std::string FEType,
2852 MatrixPtr_Type &A,
2853 MultiVectorPtr_Type &f,
2854 MultiVectorPtr_Type u,
2855 ParameterListPtr_Type pList,
2856 double C,
2857 bool callFillComplete){
2858 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::runtime_error, "Not implemented for P0");
2859 UN FEloc = checkFE(dim,FEType);
2860
2861
2862 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
2863 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
2864
2865 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
2866 vec3D_dbl_ptr_Type dPhi;
2867 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
2868
2869 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
2870
2871 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
2872
2873 SC detB;
2874 SC absDetB;
2875 SmallMatrix<SC> B(dim);
2876 SmallMatrix<SC> Binv(dim);
2877
2878 Teuchos::BLAS<int,SC> teuchosBLAS;
2879
2880 int nmbQuadPoints = dPhi->size();
2881 int nmbScalarDPhi = dPhi->at(0).size();
2882 int nmbAllDPhi = nmbScalarDPhi * dim;
2883 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
2884 int sizeLocStiff = dim*dim;
2885 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
2886
2887 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
2888
2889 std::string material_model = pList->sublist("Parameter").get("Material model","Neo-Hooke");
2890
2891 double poissonRatio = pList->sublist("Parameter").get("Poisson Ratio",0.4);
2892 double mue = pList->sublist("Parameter").get("Mu",2.0e+6);
2893 double mue1 = pList->sublist("Parameter").get("Mu1",2.0e+6);
2894 double mue2 = pList->sublist("Parameter").get("Mu2",2.0e+6);
2895 // Berechne daraus nun E (Youngsches Modul) und die erste Lamé-Konstante \lambda
2896 double E = pList->sublist("Parameter").get("E",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2897 double E1 = pList->sublist("Parameter").get("E1",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2898 double E2 = pList->sublist("Parameter").get("E2",3.0e+6); // For StVK mue_*2.*(1. + poissonRatio_);
2899
2900 if (material_model=="Saint Venant-Kirchhoff") {
2901 E = mue*2.*(1. + poissonRatio);
2902 E1 = mue1*2.*(1. + poissonRatio);
2903 E2 = mue2*2.*(1. + poissonRatio);
2904 }
2905
2906 // For StVK (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2907 double lambda = (poissonRatio*E)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2908 double lambda1 = (poissonRatio*E1)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2909 double lambda2 = (poissonRatio*E2)/((1 + poissonRatio)*(1 - 2*poissonRatio));
2910
2911 if (dim == 2){
2912 double* v;
2913 if(!material_model.compare("Saint Venant-Kirchhoff"))
2914 v = new double[154];
2915 else
2916 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Saint Venant-Kirchhoff in 2D.");
2917
2918 double** Pmat = new double*[2];
2919 for (int i=0; i<2; i++)
2920 Pmat[i] = new double[2];
2921
2922 double** F = new double*[2];
2923 for (int i=0; i<2; i++)
2924 F[i] = new double[2];
2925
2926 double**** Amat = new double***[2];
2927 for (int i=0; i<2; i++){
2928 Amat[i] = new double**[2];
2929 for (int j=0; j<2; j++) {
2930 Amat[i][j] = new double*[2];
2931 for (int k=0; k<2; k++)
2932 Amat[i][j][k] = new double[2];
2933 }
2934 }
2935
2936 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
2937
2938 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
2939
2940 Teuchos::Array<int> indices(2);
2941 for (int T=0; T<elements->numberElements(); T++) {
2942
2943 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
2944 detB = B.computeInverse(Binv);
2945 absDetB = std::fabs(detB);
2946
2947 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
2948
2949 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
2950 SmallMatrix<SC> res = dPhiMat[i] * Binv;
2951 all_dPhiMat_Binv[i] = res;
2952 }
2953
2954 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
2955 std::vector<SC> locStresses( nmbAllDPhi, 0. );
2956 int elementFlag = 0;
2957 for (int p=0; p<nmbQuadPoints; p++){
2958
2959 SmallMatrix<SC> Fmat( dim, 0. );
2960 SmallMatrix<SC> tmpForScaling( dim, 0. );
2961 Fmat[0][0] = 1.; Fmat[1][1] = 1.;
2962
2963 for (int i=0; i<nmbScalarDPhi; i++) {
2964 indices.at(0) = dim * elements->getElement(T).getNode(i);
2965 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
2966
2967 for (int j=0; j<dim; j++) {
2968 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
2969 SC v = uArray[indices.at(j)];
2970 tmpForScaling.scale( v );
2971 Fmat += tmpForScaling;
2972 }
2973 }
2974
2975 for (int i=0; i<Fmat.size(); i++) {
2976 for (int j=0; j<Fmat.size(); j++) {
2977 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
2978 }
2979 }
2980
2981 elementFlag = elements->getElement(T).getFlag();
2982 if (elementFlag == 1){
2983 lambda = lambda1;
2984 mue = mue1;
2985 E = E1;
2986 }
2987 else if (elementFlag == 2){
2988 lambda = lambda2;
2989 mue = mue2;
2990 E = E2;
2991 }
2992
2993 if ( !material_model.compare("Saint Venant-Kirchhoff") )
2994 stvk2d(v, &lambda, &mue, F, Pmat, Amat);
2995
2996 SmallMatrix<SC> Aloc(dim*dim);
2997 for (int i=0; i<2; i++) {
2998 for (int j=0; j<2; j++) {
2999 for (int k=0; k<2; k++) {
3000 for (int l=0; l<2; l++) {
3001 Aloc[ 2 * i + j ][ 2 * k + l ] = Amat[i][j][k][l];
3002 }
3003 }
3004 }
3005 }
3006
3007 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3008 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3009
3010 //jacobian
3011 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3012 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3013 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3014
3015 int offset = p * nmbAllDPhi;
3016 int offsetInArray = 0;
3017 for (int i=0; i<nmbAllDPhi; i++) {
3018 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3019 offsetInArray += sizeLocStiff;
3020 }
3021
3022 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3023
3024
3025 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3026
3027 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);
3028
3029 for (int i=0; i<nmbAllDPhi; i++) {
3030 for (int j=0; j<nmbAllDPhi; j++)
3031 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3032 }
3033
3034 delete [] resTmp;
3035 delete [] locStiffMatBlas;
3036
3037
3038 //stress
3039 double* fArray = new double[ sizeLocStiff ];
3040 for (int i=0; i<dim; i++) {
3041 for (int j=0; j<dim; j++) {
3042 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3043 }
3044 }
3045
3046 double* res = new double[ nmbAllDPhi ];
3047 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3048 for (int i=0; i<locStresses.size(); i++) {
3049 locStresses[i] += weights->at(p) * res[i];
3050 }
3051
3052 delete [] res;
3053 delete [] aceFEMFunc;
3054 delete [] allDPhiBlas;
3055 delete [] fArray;
3056 }
3057
3058 for (int i=0; i<nmbScalarDPhi; i++) {
3059 for (int d1=0; d1<dim; d1++) {
3060
3061 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
3062 SC v = absDetB * locStresses[ dim * i + d1 ];
3063 fValues[rowLO] += v;
3064
3065 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3066 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3067 LO counter = 0;
3068 for (UN j=0; j < nmbScalarDPhi; j++){
3069 for (UN d2=0; d2<dim; d2++) {
3070 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3071 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3072 counter++;
3073 }
3074 }
3075 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3076 A->insertGlobalValues( row, indices(), value() );
3077 }
3078 }
3079 }
3080
3081 delete [] v;
3082 for (int i=0; i<2; i++)
3083 delete [] Pmat[i];
3084 delete [] Pmat;
3085 for (int i=0; i<2; i++)
3086 delete [] F[i];
3087 delete [] F;
3088
3089 for (int i=0; i<2; i++){
3090 for (int j=0; j<2; j++) {
3091 for (int k=0; k<2; k++)
3092 delete [] Amat[i][j][k];
3093 delete [] Amat[i][j];
3094 }
3095 delete [] Amat[i];
3096 }
3097 delete [] Amat;
3098
3099
3100 }
3101 else if (dim == 3) {
3102 double* v;
3103 if (!material_model.compare("Neo-Hooke"))
3104 v = new double[466];
3105 else if(!material_model.compare("Mooney-Rivlin"))
3106 v = new double[476];
3107 else if(!material_model.compare("Saint Venant-Kirchhoff"))
3108 v = new double[279];
3109 else{
3110 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke, Mooney-Rivlin and Saint Venant-Kirchhoff.");
3111 }
3112
3113 double** Pmat = new double*[3];
3114 for (int i=0; i<3; i++)
3115 Pmat[i] = new double[3];
3116
3117 double** F = new double*[3];
3118 for (int i=0; i<3; i++)
3119 F[i] = new double[3];
3120
3121 double**** Amat = new double***[3];
3122 for (int i=0; i<3; i++){
3123 Amat[i] = new double**[3];
3124 for (int j=0; j<3; j++) {
3125 Amat[i][j] = new double*[3];
3126 for (int k=0; k<3; k++)
3127 Amat[i][j][k] = new double[3];
3128 }
3129 }
3130
3131 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3132
3133 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
3134
3135 Teuchos::Array<int> indices(3);
3136 for (int T=0; T<elements->numberElements(); T++) {
3137
3138 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
3139 detB = B.computeInverse(Binv);
3140 absDetB = std::fabs(detB);
3141
3142 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3143
3144 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3145 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3146 all_dPhiMat_Binv[i] = res;
3147 }
3148
3149 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
3150 std::vector<SC> locStresses( nmbAllDPhi, 0. );
3151 int elementFlag = 0;
3152 for (int p=0; p<nmbQuadPoints; p++){
3153
3154 SmallMatrix<SC> Fmat( dim, 0. );
3155 SmallMatrix<SC> tmpForScaling( dim, 0. );
3156 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3157
3158 for (int i=0; i<nmbScalarDPhi; i++) {
3159 indices.at(0) = dim * elements->getElement(T).getNode(i);
3160 indices.at(1) = dim * elements->getElement(T).getNode(i) + 1;
3161 indices.at(2) = dim * elements->getElement(T).getNode(i) + 2;
3162
3163 for (int j=0; j<dim; j++) {
3164 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3165 SC v = uArray[indices.at(j)];
3166 tmpForScaling.scale( v );
3167 Fmat += tmpForScaling;
3168 }
3169 }
3170
3171 for (int i=0; i<Fmat.size(); i++) {
3172 for (int j=0; j<Fmat.size(); j++) {
3173 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3174 }
3175 }
3176
3177 elementFlag = elements->getElement(T).getFlag();
3178 if (elementFlag == 1){
3179 lambda = lambda1;
3180 mue = mue1;
3181 E = E1;
3182 }
3183 else if (elementFlag == 2){
3184 lambda = lambda2;
3185 mue = mue2;
3186 E = E2;
3187 }
3188
3189 if ( !material_model.compare("Neo-Hooke") )
3190 nh3d(v, &E, &poissonRatio, F, Pmat, Amat);
3191 else if ( !material_model.compare("Mooney-Rivlin") )
3192 mr3d(v, &E, &poissonRatio, &C, F, Pmat, Amat);
3193 else if ( !material_model.compare("Saint Venant-Kirchhoff") )
3194 stvk3d(v, &lambda, &mue, F, Pmat, Amat);
3195
3196 SmallMatrix<SC> Aloc(dim*dim);
3197 for (int i=0; i<3; i++) {
3198 for (int j=0; j<3; j++) {
3199 for (int k=0; k<3; k++) {
3200 for (int l=0; l<3; l++) {
3201 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
3202 }
3203 }
3204 }
3205 }
3206
3207 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3208 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3209
3210 //jacobian
3211 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3212 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3213 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3214
3215 int offset = p * nmbAllDPhi;
3216 int offsetInArray = 0;
3217 for (int i=0; i<nmbAllDPhi; i++) {
3218 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3219 offsetInArray += sizeLocStiff;
3220 }
3221
3222 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3223
3224
3225 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3226
3227 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);
3228
3229 for (int i=0; i<nmbAllDPhi; i++) {
3230 for (int j=0; j<nmbAllDPhi; j++)
3231 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3232 }
3233
3234 delete [] resTmp;
3235 delete [] locStiffMatBlas;
3236
3237
3238 //stress
3239 double* fArray = new double[ sizeLocStiff ];
3240 for (int i=0; i<dim; i++) {
3241 for (int j=0; j<dim; j++) {
3242 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3243 }
3244 }
3245
3246 double* res = new double[ nmbAllDPhi ];
3247 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3248 for (int i=0; i<locStresses.size(); i++) {
3249 locStresses[i] += weights->at(p) * res[i];
3250 }
3251
3252 delete [] res;
3253 delete [] aceFEMFunc;
3254 delete [] allDPhiBlas;
3255 delete [] fArray;
3256 }
3257
3258 for (int i=0; i<nmbScalarDPhi; i++) {
3259 for (int d1=0; d1<dim; d1++) {
3260
3261 LO rowLO = dim * elements->getElement(T).getNode(i) + d1;
3262 SC v = absDetB * locStresses[ dim * i + d1 ];
3263 fValues[rowLO] += v;
3264
3265 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3266 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3267 LO counter = 0;
3268 for (UN j=0; j < nmbScalarDPhi; j++){
3269 for (UN d2=0; d2<dim; d2++) {
3270 indices[counter] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3271 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3272
3273 counter++;
3274 }
3275 }
3276 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3277 A->insertGlobalValues( row, indices(), value() );
3278 }
3279 }
3280 }
3281
3282 delete [] v;
3283 for (int i=0; i<3; i++)
3284 delete [] Pmat[i];
3285 delete [] Pmat;
3286 for (int i=0; i<3; i++)
3287 delete [] F[i];
3288 delete [] F;
3289
3290 for (int i=0; i<3; i++){
3291 for (int j=0; j<3; j++) {
3292 for (int k=0; k<3; k++)
3293 delete [] Amat[i][j][k];
3294 delete [] Amat[i][j];
3295 }
3296 delete [] Amat[i];
3297 }
3298 delete [] Amat;
3299
3300 }
3301 if (callFillComplete)
3302 A->fillComplete();
3303
3304}
3305
3306
3307template <class SC, class LO, class GO, class NO>
3308void FE<SC,LO,GO,NO>::assemblyElasticityJacobianAceFEM(int dim,
3309 std::string FEType,
3310 MatrixPtr_Type &A,
3311 MultiVectorPtr_Type u,
3312 std::string material_model,
3313 double E,
3314 double nu,
3315 double C,
3316 bool callFillComplete){
3317 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3318 UN FEloc = checkFE(dim,FEType);
3319
3320 vec2D_int_ptr_Type elements = domainVec_.at(FEloc)->getElements();
3321
3322 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3323
3324 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3325 vec3D_dbl_ptr_Type dPhi;
3326 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3327
3328 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
3329
3330 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3331
3332 SC detB;
3333 SC absDetB;
3334 SmallMatrix<SC> B(dim);
3335 SmallMatrix<SC> Binv(dim);
3336
3337 Teuchos::BLAS<int, SC> teuchosBLAS;
3338
3339 int nmbQuadPoints = dPhi->size();
3340 int nmbScalarDPhi = dPhi->at(0).size();
3341 int nmbAllDPhi = nmbScalarDPhi * dim;
3342 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
3343 int sizeLocStiff = dim*dim;
3344 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
3345
3346 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
3347
3348 if (dim == 2){
3349 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
3350 }
3351 else if (dim == 3) {
3352
3353 double* v;
3354 if (!material_model.compare("Neo-Hooke"))
3355 v = new double[466];
3356 else if(!material_model.compare("Mooney-Rivlin"))
3357 v = new double[476];
3358 else{
3359 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
3360 }
3361
3362
3363 double** Pmat = new double*[3];
3364 for (int i=0; i<3; i++)
3365 Pmat[i] = new double[3];
3366
3367 double** F = new double*[3];
3368 for (int i=0; i<3; i++)
3369 F[i] = new double[3];
3370
3371 double**** Amat = new double***[3];
3372 for (int i=0; i<3; i++){
3373 Amat[i] = new double**[3];
3374 for (int j=0; j<3; j++) {
3375 Amat[i][j] = new double*[3];
3376 for (int k=0; k<3; k++)
3377 Amat[i][j][k] = new double[3];
3378 }
3379 }
3380
3381 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3382
3383 Teuchos::Array<int> indices(3);
3384 for (int T=0; T<elements->size(); T++) {
3385
3386 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
3387 detB = B.computeInverse(Binv);
3388 absDetB = std::fabs(detB);
3389
3390 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3391
3392 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3393 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3394 all_dPhiMat_Binv[i] = res;
3395 }
3396
3397 SmallMatrix<SC> locStiffMat( nmbAllDPhi, 0. );
3398
3399 for (int p=0; p<nmbQuadPoints; p++){
3400
3401 SmallMatrix<SC> Fmat( dim, 0. );
3402 SmallMatrix<SC> tmpForScaling( dim, 0. );
3403 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3404
3405 for (int i=0; i<nmbScalarDPhi; i++) {
3406 indices.at(0) = dim * elements->at(T).at(i);
3407 indices.at(1) = dim * elements->at(T).at(i) + 1;
3408 indices.at(2) = dim * elements->at(T).at(i) + 2;
3409
3410 for (int j=0; j<dim; j++) {
3411 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3412 SC v = uArray[indices.at(j)];
3413 tmpForScaling.scale( v );
3414 Fmat += tmpForScaling;
3415 }
3416 }
3417
3418 for (int i=0; i<Fmat.size(); i++) {
3419 for (int j=0; j<Fmat.size(); j++) {
3420 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3421 }
3422 }
3423 if ( !material_model.compare("Neo-Hooke") )
3424 nh3d(v, &E, &nu, F, Pmat, Amat);
3425 else if ( !material_model.compare("Mooney-Rivlin") )
3426 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
3427
3428 SmallMatrix<SC> Aloc(dim*dim);
3429 for (int i=0; i<3; i++) {
3430 for (int j=0; j<3; j++) {
3431 for (int k=0; k<3; k++) {
3432 for (int l=0; l<3; l++) {
3433 Aloc[ 3 * i + j ][ 3 * k + l ] = Amat[i][j][k][l];
3434 }
3435 }
3436 }
3437 }
3438
3439 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3440 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3441 double* resTmp = new double[ nmbAllDPhi * sizeLocStiff ];
3442 // all_dPhiMat_Binv: quadpoints -> basisfunction vector field
3443 fillMatrixArray(Aloc, aceFEMFunc, "cols"); //blas uses column-major
3444
3445 int offset = p * nmbAllDPhi;
3446 int offsetInArray = 0;
3447 for (int i=0; i<nmbAllDPhi; i++) {
3448 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3449 offsetInArray += sizeLocStiff;
3450 }
3451
3452 teuchosBLAS.GEMM (Teuchos::NO_TRANS, Teuchos::NO_TRANS, sizeLocStiff, nmbAllDPhi, sizeLocStiff, 1., aceFEMFunc, sizeLocStiff, allDPhiBlas, sizeLocStiff, 0., resTmp, sizeLocStiff);
3453
3454 double* locStiffMatBlas = new double[ nmbAllDPhi * nmbAllDPhi ];
3455
3456 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);
3457
3458 for (int i=0; i<nmbAllDPhi; i++) {
3459 for (int j=0; j<nmbAllDPhi; j++)
3460 locStiffMat[i][j] += weights->at(p) * locStiffMatBlas[ j * nmbAllDPhi + i ];
3461 }
3462
3463 delete [] aceFEMFunc;
3464 delete [] allDPhiBlas;
3465 delete [] resTmp;
3466 delete [] locStiffMatBlas;
3467
3468 }
3469 for (int i=0; i<nmbScalarDPhi; i++) {
3470 for (int d1=0; d1<dim; d1++) {
3471 Teuchos::Array<SC> value( nmbAllDPhi, 0. );
3472 Teuchos::Array<GO> indices( nmbAllDPhi, 0 );
3473 LO counter = 0;
3474 for (UN j=0; j < nmbScalarDPhi; j++){
3475 for (UN d2=0; d2<dim; d2++) {
3476 indices[counter] = GO ( dim * map->getGlobalElement( elements->at(T).at(j) ) + d2 );
3477 value[counter] = absDetB * locStiffMat[dim*i+d1][dim*j+d2];
3478 counter++;
3479 }
3480 }
3481 GO row = GO ( dim * map->getGlobalElement( elements->at(T).at(i) ) + d1 );
3482 A->insertGlobalValues( row, indices(), value() );
3483 }
3484 }
3485 }
3486
3487 delete [] v;
3488 for (int i=0; i<3; i++)
3489 delete [] Pmat[i];
3490 delete [] Pmat;
3491 for (int i=0; i<3; i++)
3492 delete [] F[i];
3493 delete [] F;
3494
3495 for (int i=0; i<3; i++){
3496 for (int j=0; j<3; j++) {
3497 for (int k=0; k<3; k++)
3498 delete [] Amat[i][j][k];
3499 delete [] Amat[i][j];
3500 }
3501 delete [] Amat[i];
3502 }
3503 delete [] Amat;
3504
3505 }
3506 if (callFillComplete)
3507 A->fillComplete();
3508
3509}
3510
3511template <class SC, class LO, class GO, class NO>
3512void FE<SC,LO,GO,NO>::assemblyElasticityStressesAceFEM(int dim,
3513 std::string FEType,
3514 MultiVectorPtr_Type &f,
3515 MultiVectorPtr_Type u,
3516 std::string material_model,
3517 double E,
3518 double nu,
3519 double C,
3520 bool callFillComplete){
3521 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3522 UN FEloc = checkFE(dim,FEType);
3523
3524 vec2D_int_ptr_Type elements = domainVec_.at(FEloc)->getElements();
3525
3526 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3527
3528 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3529
3530 vec3D_dbl_ptr_Type dPhi;
3531 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3532
3533 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv1);
3534
3535 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3536
3537 SC detB;
3538 SC absDetB;
3539 SmallMatrix<SC> B(dim);
3540 SmallMatrix<SC> Binv(dim);
3541
3542 Teuchos::BLAS<int, SC> teuchosBLAS;
3543
3544 int nmbQuadPoints = dPhi->size();
3545 int nmbScalarDPhi = dPhi->at(0).size();
3546 int nmbAllDPhi = nmbScalarDPhi * dim;
3547 int nmbAllDPhiAllQaud = nmbQuadPoints * nmbAllDPhi;
3548 int sizeLocStiff = dim*dim;
3549 Teuchos::Array<SmallMatrix<SC> > dPhiMat( nmbAllDPhiAllQaud, SmallMatrix<SC>(dim) );
3550
3551 this->buildFullDPhi( dPhi, dPhiMat ); //builds matrix from gradient of scalar phi
3552
3553 if (dim == 2){
3554 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only for 3D.");
3555 }
3556 else if (dim == 3) {
3557
3558 double* v;
3559 if (!material_model.compare("Neo-Hooke"))
3560 v = new double[466];
3561 else if(!material_model.compare("Mooney-Rivlin"))
3562 v = new double[476];
3563 else{
3564 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Only Neo-Hooke and Mooney-Rivlin.");
3565 }
3566
3567
3568 double** Pmat = new double*[3];
3569 for (int i=0; i<3; i++)
3570 Pmat[i] = new double[3];
3571
3572 double** F = new double*[3];
3573 for (int i=0; i<3; i++)
3574 F[i] = new double[3];
3575
3576 double**** Amat = new double***[3];
3577 for (int i=0; i<3; i++){
3578 Amat[i] = new double**[3];
3579 for (int j=0; j<3; j++) {
3580 Amat[i][j] = new double*[3];
3581 for (int k=0; k<3; k++)
3582 Amat[i][j][k] = new double[3];
3583 }
3584 }
3585
3586 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3587
3588 Teuchos::ArrayRCP<SC> fValues = f->getDataNonConst(0);
3589
3590 Teuchos::Array<int> indices(3);
3591 for (int T=0; T<elements->size(); T++) {
3592
3593 Helper::buildTransformation(elements->at(T), pointsRep, B,FEType);
3594 detB = B.computeInverse(Binv);
3595 absDetB = std::fabs(detB);
3596
3597 Teuchos::Array<SmallMatrix<SC> > all_dPhiMat_Binv( dPhiMat.size(), SmallMatrix<SC>() );
3598
3599 for (int i=0; i<all_dPhiMat_Binv.size(); i++) {
3600 SmallMatrix<SC> res = dPhiMat[i] * Binv;
3601 all_dPhiMat_Binv[i] = res;
3602 }
3603 std::vector<double> locStresses( nmbAllDPhi, 0. );
3604
3605 for (int p=0; p<nmbQuadPoints; p++){
3606
3607 SmallMatrix<SC> Fmat( dim, 0. );
3608 SmallMatrix<SC> tmpForScaling( dim, 0. );
3609 Fmat[0][0] = 1.; Fmat[1][1] = 1.; Fmat[2][2] = 1.;
3610
3611 for (int i=0; i<nmbScalarDPhi; i++) {
3612 indices.at(0) = dim * elements->at(T).at(i);
3613 indices.at(1) = dim * elements->at(T).at(i) + 1;
3614 indices.at(2) = dim * elements->at(T).at(i) + 2;
3615
3616 for (int j=0; j<dim; j++) {
3617 tmpForScaling = all_dPhiMat_Binv[ p * nmbAllDPhi + dim * i + j ]; //we should not copy here
3618 SC v = uArray[indices.at(j)];
3619 tmpForScaling.scale( v );
3620 Fmat += tmpForScaling;
3621 }
3622 }
3623
3624 for (int i=0; i<Fmat.size(); i++) {
3625 for (int j=0; j<Fmat.size(); j++) {
3626 F[i][j] = Fmat[i][j]; //fix so we dont need to copy.
3627 }
3628 }
3629 if ( !material_model.compare("Neo-Hooke") )
3630 nh3d(v, &E, &nu, F, Pmat, Amat);
3631 else if ( !material_model.compare("Mooney-Rivlin") )
3632 mr3d(v, &E, &nu, &C, F, Pmat, Amat);
3633
3634 double* aceFEMFunc = new double[ sizeLocStiff * sizeLocStiff ];
3635 double* allDPhiBlas = new double[ nmbAllDPhi * sizeLocStiff ];
3636
3637 int offset = p * nmbAllDPhi;
3638 int offsetInArray = 0;
3639 for (int i=0; i<nmbAllDPhi; i++) {
3640 fillMatrixArray( all_dPhiMat_Binv[ offset + i ], allDPhiBlas, "rows",offsetInArray );
3641 offsetInArray += sizeLocStiff;
3642 }
3643
3644
3645 double* fArray = new double[ sizeLocStiff ];
3646 for (int i=0; i<dim; i++) {
3647 for (int j=0; j<dim; j++) {
3648 fArray[i * dim + j] = Pmat[i][j]; //is this correct?
3649 }
3650 }
3651
3652 double* res = new double[ nmbAllDPhi ];
3653 teuchosBLAS.GEMV(Teuchos::TRANS, sizeLocStiff, nmbAllDPhi, 1., allDPhiBlas, sizeLocStiff, fArray, 1, 0., res, 1);
3654 for (int i=0; i<locStresses.size(); i++) {
3655 locStresses[i] += weights->at(p) * res[i];
3656 }
3657
3658 delete [] aceFEMFunc;
3659 delete [] allDPhiBlas;
3660 delete [] fArray;
3661 }
3662
3663
3664
3665 for (int i=0; i<nmbScalarDPhi; i++) {
3666 for (int d1=0; d1<dim; d1++) {
3667 LO row = dim * elements->at(T).at(i) + d1;
3668 SC v = absDetB * locStresses[ dim * i + d1 ];
3669 fValues[row] = v;
3670 }
3671 }
3672 }
3673
3674
3675 delete [] v;
3676 for (int i=0; i<3; i++)
3677 delete [] Pmat[i];
3678 delete [] Pmat;
3679 for (int i=0; i<3; i++)
3680 delete [] F[i];
3681 delete [] F;
3682
3683 for (int i=0; i<3; i++){
3684 for (int j=0; j<3; j++) {
3685 for (int k=0; k<3; k++)
3686 delete [] Amat[i][j][k];
3687 delete [] Amat[i][j];
3688 }
3689 delete [] Amat[i];
3690 }
3691 delete [] Amat;
3692
3693 }
3694}
3695
3697template <class SC, class LO, class GO, class NO>
3699 std::string FEType,
3700 MatrixPtr_Type &A,
3701 MultiVectorPtr_Type u,
3702 bool callFillComplete){
3703
3704 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3705 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3706
3707 UN FEloc = checkFE(dim,FEType);
3708
3709 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
3710
3711 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3712
3713 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3714
3715 vec3D_dbl_ptr_Type dPhi;
3716 vec2D_dbl_ptr_Type phi;
3717 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3718
3719 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of grad u
3720
3721 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1 ) +
3722 Helper::determineDegree( dim, FEType, Helper::Deriv0) +
3723 extraDeg;
3724
3725 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3726 Helper::getPhi(phi, weights, dim, FEType, deg);
3727 SC detB;
3728 SC absDetB;
3729 SmallMatrix<SC> B(dim);
3730 SmallMatrix<SC> Binv(dim);
3731 GO glob_i, glob_j;
3732 vec_dbl_Type v_i(dim);
3733 vec_dbl_Type v_j(dim);
3734
3735 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
3736 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3737
3738 for (UN T=0; T<elements->numberElements(); T++) {
3739
3740 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3741 detB = B.computeInverse(Binv);
3742 absDetB = std::fabs(detB);
3743
3744 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3745 applyBTinv( dPhi, dPhiTrans, Binv );
3746
3747 for (int w=0; w<phi->size(); w++){ //quads points
3748 for (int d=0; d<dim; d++) {
3749 uLoc[d][w] = 0.;
3750 for (int i=0; i < phi->at(0).size(); i++) {
3751 LO index = dim * elements->getElement(T).getNode(i) + d;
3752 uLoc[d][w] += uArray[index] * phi->at(w).at(i);
3753 }
3754 }
3755 }
3756
3757 for (UN i=0; i < phi->at(0).size(); i++) {
3758 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
3759 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
3760 for (UN j=0; j < value.size(); j++) {
3761 for (UN w=0; w<dPhiTrans.size(); w++) {
3762 for (UN d=0; d<dim; d++){
3763 value[j] += weights->at(w) * uLoc[d][w] * (*phi)[w][i] * dPhiTrans[w][j][d];
3764 }
3765
3766 }
3767 value[j] *= absDetB;
3768 if (setZeros_ && std::fabs(value[j]) < myeps_) {
3769 value[j] = 0.;
3770 }
3771
3772 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) );
3773 GO glob_j = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) );
3774 }
3775 for (UN d=0; d<dim; d++) {
3776 for (UN j=0; j < indices.size(); j++)
3777 indices[j] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d );
3778
3779 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d );
3780 A->insertGlobalValues( row, indices(), value() );
3781 }
3782 }
3783 }
3784
3785
3786 if (callFillComplete)
3787 A->fillComplete();
3788}
3789
3791template <class SC, class LO, class GO, class NO>
3793 std::string FEType,
3794 MatrixPtr_Type &A,
3795 MultiVectorPtr_Type u,
3796 bool callFillComplete){
3797
3798 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3799 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3800 UN FEloc = checkFE(dim,FEType);
3801
3802 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
3803
3804 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
3805
3806 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
3807
3808 vec3D_dbl_ptr_Type dPhi;
3809 vec2D_dbl_ptr_Type phi;
3810 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3811
3812 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); //Elementwise assembly of u
3813
3814 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
3815
3816 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
3817 Helper::getPhi(phi, weights, dim, FEType, deg);
3818
3819 SC detB;
3820 SC absDetB;
3821 SmallMatrix<SC> B(dim);
3822 SmallMatrix<SC> Binv(dim);
3823 GO glob_i, glob_j;
3824 vec_dbl_Type v_i(dim);
3825 vec_dbl_Type v_j(dim);
3826
3827 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3828
3829 for (UN T=0; T<elements->numberElements(); T++) {
3830
3831 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3832 detB = B.computeInverse(Binv);
3833 absDetB = std::fabs(detB);
3834
3835 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3836 applyBTinv( dPhi, dPhiTrans, Binv );
3837
3838 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)
3839
3840 for (int w=0; w<dPhiTrans.size(); w++){ //quads points
3841 for (int d1=0; d1<dim; d1++) {
3842 for (int i=0; i < dPhiTrans[0].size(); i++) {
3843 LO index = dim * elements->getElement(T).getNode(i) + d1;
3844 for (int d2=0; d2<dim; d2++)
3845 duLoc[w][d2][d1] += uArray[index] * dPhiTrans[w][i][d2];
3846 }
3847 }
3848 }
3849
3850 for (UN i=0; i < phi->at(0).size(); i++) {
3851 for (UN d1=0; d1<dim; d1++) {
3852 Teuchos::Array<SC> value( dim*phi->at(0).size(), 0. ); //These are value (W_ix,W_iy,W_iz)
3853 Teuchos::Array<GO> indices( dim*phi->at(0).size(), 0 );
3854 for (UN j=0; j < phi->at(0).size(); j++) {
3855 for (UN d2=0; d2<dim; d2++){
3856 for (UN w=0; w<phi->size(); w++) {
3857 value[ dim * j + d2 ] += weights->at(w) * duLoc[w][d2][d1] * (*phi)[w][i] * (*phi)[w][j];
3858 }
3859 value[ dim * j + d2 ] *= absDetB;
3860
3861 if (setZeros_ && std::fabs(value[ dim * j + d2 ]) < myeps_) {
3862 value[ dim * j + d2 ] = 0.;
3863 }
3864 }
3865 }
3866 for (UN j=0; j < phi->at(0).size(); j++){
3867 for (UN d2=0; d2<dim; d2++){
3868 indices[ dim * j + d2 ] = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(j) ) + d2 );
3869 }
3870 }
3871
3872 GO row = GO ( dim * map->getGlobalElement( elements->getElement(T).getNode(i) ) + d1 );
3873 A->insertGlobalValues( row, indices(), value() );
3874 }
3875 }
3876 }
3877 if (callFillComplete)
3878 A->fillComplete();
3879}
3880
3882template <class SC, class LO, class GO, class NO>
3884 std::string FEType,
3885 std::string FETypeV,
3886 MatrixPtr_Type &A,
3887 MultiVectorPtr_Type u,
3888 bool callFillComplete){
3889
3890 TEUCHOS_TEST_FOR_EXCEPTION( u->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
3891 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
3892
3893 UN FEloc = checkFE(dim,FEType);
3894
3895 ElementsPtr_Type elements = domainVec_.at(1)->getElementsC();
3896 ElementsPtr_Type elementsVel = domainVec_.at(0)->getElementsC();
3897
3898 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(1)->getPointsRepeated();
3899
3900 MapConstPtr_Type map = domainVec_.at(1)->getMapRepeated();
3901
3902 vec3D_dbl_ptr_Type dPhi;
3903 vec2D_dbl_ptr_Type phi,phiV;
3904 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
3905
3906 UN degV = Helper::determineDegree( dim, FETypeV, Helper::Deriv0); //Elementwise assembly of u
3907 UN degP = Helper::determineDegree( dim, FEType, Helper::Deriv0); //Elementwise assembly of p
3908 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv1) + degV + degP;
3909
3910 Helper::getDPhi(dPhi, weights, dim, FEType, deg); // Dphi for \nabla p
3911 Helper::getPhi(phi, weights, dim, FEType, deg); // phi for u
3912 Helper::getPhi(phiV, weights, dim, FETypeV, deg); // phi for p
3913
3914 SC detB;
3915 SC absDetB;
3916 SmallMatrix<SC> B(dim);
3917 SmallMatrix<SC> Binv(dim);
3918 GO glob_i, glob_j;
3919 vec_dbl_Type v_i(dim);
3920 vec_dbl_Type v_j(dim);
3921
3922 vec2D_dbl_Type uLoc( dim, vec_dbl_Type( weights->size() , -1. ) );
3923 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
3924
3925 for (UN T=0; T<elements->numberElements(); T++) {
3926
3927 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
3928 detB = B.computeInverse(Binv);
3929 absDetB = std::fabs(detB);
3930
3931 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
3932 applyBTinv( dPhi, dPhiTrans, Binv );
3933
3934 for (int w=0; w<phiV->size(); w++){ //quads points
3935 for (int d=0; d<dim; d++) {
3936 uLoc[d][w] = 0.;
3937 for (int i=0; i < phiV->at(0).size(); i++) {
3938 LO index = dim * elementsVel->getElement(T).getNode(i) + d;
3939 uLoc[d][w] += uArray[index] * phiV->at(w).at(i);
3940 }
3941 }
3942 }
3943
3944 for (UN i=0; i < phi->at(0).size(); i++) {
3945 Teuchos::Array<SC> value( dPhiTrans[0].size(), 0. );
3946 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
3947 for (UN j=0; j < value.size(); j++) {
3948 for (UN w=0; w<dPhiTrans.size(); w++) {
3949 for (UN d=0; d<dim; d++){
3950 value[j] += weights->at(w) * uLoc[d][w]* dPhiTrans[w][j][d] * (*phi)[w][i] ;
3951 }
3952 }
3953 value[j] *= absDetB;
3954 indices[j] = GO ( map->getGlobalElement( elements->getElement(T).getNode(j) ) );
3955 }
3956
3957 GO row = GO ( map->getGlobalElement( elements->getElement(T).getNode(i) ) );
3958 A->insertGlobalValues( row, indices(), value() );
3959
3960 }
3961 }
3962
3963
3964 if (callFillComplete)
3965 A->fillComplete();
3966}
3967
3969template <class SC, class LO, class GO, class NO>
3971 std::string FEType1,
3972 std::string FEType2,
3973 int degree,
3974 MatrixPtr_Type &Bmat,
3975 MatrixPtr_Type &BTmat,
3976 MapConstPtr_Type map1,
3977 MapConstPtr_Type map2,
3978 bool callFillComplete) {
3979
3980
3981 UN FEloc1 = checkFE(dim,FEType1);
3982 UN FEloc2 = checkFE(dim,FEType2);
3983
3984 ElementsPtr_Type elements1 = domainVec_.at(FEloc1)->getElementsC();
3985 ElementsPtr_Type elements2 = domainVec_.at(FEloc2)->getElementsC();
3986
3987 vec2D_dbl_ptr_Type pointsRep1 = domainVec_.at(FEloc1)->getPointsRepeated();
3988
3989 MapConstPtr_Type mapping1 = domainVec_.at(FEloc1)->getMapRepeated();
3990 MapConstPtr_Type mapping2;
3991
3992 if (FEType2 == "P0")
3993 mapping2 = domainVec_.at(FEloc2)->getElementMap();
3994 else
3995 mapping2 = domainVec_.at(FEloc2)->getMapRepeated();
3996
3997 vec3D_dbl_ptr_Type dPhi;
3998 vec2D_dbl_ptr_Type phi;
3999 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4000
4001 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
4003
4004 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
4005
4006 // if (FEType2=="P1-disc-global")
4007 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
4008 if (FEType2=="P1-disc" && FEType1=="Q2" )
4009 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
4010 else
4011 Helper::getPhi(phi, weights, dim, FEType2, deg);
4012
4013 SC detB;
4014 SC absDetB;
4015 SmallMatrix<SC> B(dim);
4016 SmallMatrix<SC> Binv(dim);
4017 GO glob_i, glob_j;
4018 vec_dbl_Type v_i(dim);
4019 vec_dbl_Type v_j(dim);
4020
4021 for (UN T=0; T<elements1->numberElements(); T++) {
4022
4023 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
4024 detB = B.computeInverse(Binv);
4025 absDetB = std::fabs(detB);
4026
4027 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4028 applyBTinv( dPhi, dPhiTrans, Binv );
4029
4030 for (UN i=0; i < phi->at(0).size(); i++) {
4031 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( dPhiTrans[0].size(), 0. ) );
4032 Teuchos::Array<GO> indices( dPhiTrans[0].size(), 0 );
4033
4034 for (UN j=0; j < valueVec[0].size(); j++) {
4035 for (UN w=0; w<dPhiTrans.size(); w++) {
4036 for (UN d=0; d<dim; d++)
4037 valueVec[d][j] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
4038 }
4039 for (UN d=0; d<dim; d++){
4040 valueVec[d][j] *= absDetB;
4041 if (setZeros_ && std::fabs(valueVec[d][j]) < myeps_) {
4042 valueVec[d][j] = 0.;
4043 }
4044 }
4045 }
4046 for (UN d=0; d<dim; d++) {
4047 for (UN j=0; j < indices.size(); j++)
4048 indices[j] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
4049
4050 GO row;
4051 if (FEType2=="P0")
4052 row = GO ( mapping2->getGlobalElement( T ) );
4053 else
4054 row = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
4055 Bmat->insertGlobalValues( row, indices(), valueVec[d]() );
4056 }
4057 }
4058
4059 // We compute value twice, maybe we should change this
4060 for (UN i=0; i < dPhiTrans[0].size(); i++) {
4061
4062 Teuchos::Array<Teuchos::Array<SC> >valueVec( dim, Teuchos::Array<SC>( phi->at(0).size(), 0. ) );
4063 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
4064 for (UN j=0; j < valueVec[0].size(); j++) {
4065 for (UN w=0; w<dPhiTrans.size(); w++) {
4066 for (UN d=0; d<dim; d++)
4067 valueVec[d][j] += weights->at(w) * phi->at(w)[j] * dPhiTrans[w][i][d];
4068 }
4069 for (UN d=0; d<dim; d++){
4070 valueVec[d][j] *= absDetB;
4071 if (setZeros_ && std::fabs(valueVec[d][j]) < myeps_) {
4072 valueVec[d][j] = 0.;
4073 }
4074 }
4075 }
4076
4077 for (UN j=0; j < indices.size(); j++){
4078 if (FEType2=="P0")
4079 indices[j] = GO ( mapping2->getGlobalElement( T ) );
4080 else
4081 indices[j] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(j) ) );
4082 }
4083 for (UN d=0; d<dim; d++) {
4084 GO row = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(i) ) + d );
4085 BTmat->insertGlobalValues( row, indices(), valueVec[d]() );
4086 }
4087
4088 }
4089
4090 }
4091 if (callFillComplete) {
4092 Bmat->fillComplete( map1, map2 );
4093 BTmat->fillComplete( map2, map1 );
4094 }
4095
4096}
4097
4099template <class SC, class LO, class GO, class NO>
4101 std::string FEType1,
4102 std::string FEType2,
4103 int degree,
4104 MatrixPtr_Type &Bmat,
4105 MatrixPtr_Type &BTmat,
4106 MapConstPtr_Type map1,
4107 MapConstPtr_Type map2,
4108 bool callFillComplete) {
4109
4110
4111 UN FEloc1 = checkFE(dim,FEType1);
4112 UN FEloc2 = checkFE(dim,FEType2);
4113
4114 ElementsPtr_Type elements1 = domainVec_.at(FEloc1)->getElementsC();
4115 ElementsPtr_Type elements2 = domainVec_.at(FEloc2)->getElementsC();
4116
4117 vec2D_dbl_ptr_Type pointsRep1 = domainVec_.at(FEloc1)->getPointsRepeated();
4118
4119 MapConstPtr_Type mapping1 = domainVec_.at(FEloc1)->getMapRepeated();
4120 MapConstPtr_Type mapping2;
4121
4122 if (FEType2 == "P0")
4123 mapping2 = domainVec_.at(FEloc2)->getElementMap();
4124 else
4125 mapping2 = domainVec_.at(FEloc2)->getMapRepeated();
4126
4127 vec3D_dbl_ptr_Type dPhi;
4128 vec2D_dbl_ptr_Type phi;
4129 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4130
4131 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv1) +
4133
4134 Helper::getDPhi(dPhi, weights, dim, FEType1, deg);
4135
4136 // if (FEType2=="P1-disc-global")
4137 // Helper::getPhiGlobal(phi, weights, dim, FEType2, deg);
4138 if (FEType2=="P1-disc" && FEType1=="Q2" )
4139 Helper::getPhi(phi, weights, dim, FEType2, deg, FEType1);
4140 else
4141 Helper::getPhi(phi, weights, dim, FEType2, deg);
4142
4143 SC detB;
4144 SC absDetB;
4145 SmallMatrix<SC> B(dim);
4146 SmallMatrix<SC> Binv(dim);
4147 GO glob_i, glob_j;
4148 vec_dbl_Type v_i(dim);
4149 vec_dbl_Type v_j(dim);
4150
4151 Teuchos::Array<GO> colIndex( 1, 0 );
4152 Teuchos::Array<GO> rowIndex( 1, 0 );
4153 Teuchos::Array<SC> value(1, 0.);
4154
4155 for (UN T=0; T<elements1->numberElements(); T++) {
4156
4157 Helper::buildTransformation(elements1->getElement(T).getVectorNodeList(), pointsRep1, B, FEType1);
4158 detB = B.computeInverse(Binv);
4159 absDetB = std::fabs(detB);
4160
4161 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4162 applyBTinv( dPhi, dPhiTrans, Binv );
4163
4164 for (UN i=0; i < phi->at(0).size(); i++) {
4165 if (FEType2=="P0")
4166 rowIndex[0] = GO ( mapping2->getGlobalElement( T ) );
4167 else
4168 rowIndex[0] = GO ( mapping2->getGlobalElement( elements2->getElement(T).getNode(i) ) );
4169
4170 for (UN j=0; j < dPhiTrans[0].size(); j++) {
4171 for (UN d=0; d<dim; d++){
4172 value[0] = 0.;
4173 for (UN w=0; w<dPhiTrans.size(); w++)
4174 value[0] += weights->at(w) * phi->at(w)[i] * dPhiTrans[w][j][d];
4175 value[0] *= absDetB;
4176 colIndex[0] = GO ( dim * mapping1->getGlobalElement( elements1->getElement(T).getNode(j) ) + d );
4177 Bmat->insertGlobalValues( rowIndex[0], colIndex(), value() );
4178 BTmat->insertGlobalValues( colIndex[0], rowIndex(), value() );
4179
4180 }
4181 }
4182 }
4183
4184 }
4185 if (callFillComplete) {
4186 Bmat->fillComplete( map1, map2 );
4187 BTmat->fillComplete( map2, map1 );
4188 }
4189
4190}
4191
4193template <class SC, class LO, class GO, class NO>
4195 std::string FEType,
4196 MatrixPtr_Type &A,
4197 bool callFillComplete){
4198
4199 TEUCHOS_TEST_FOR_EXCEPTION(FEType != "P1" && FEType != "Q1",std::logic_error, "Only implemented for P1, Q1.");
4200 UN FEloc = checkFE(dim,FEType);
4201
4202 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4203
4204 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4205
4206 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4207
4208 vec2D_dbl_ptr_Type phi;
4209
4210 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
4211
4212 UN deg = 2*Helper::determineDegree(dim,FEType,Helper::Deriv0);
4213
4214 Helper::getPhi( phi, weights, dim, FEType, deg );
4215
4216 SC detB;
4217 SC absDetB;
4218 SmallMatrix<SC> B(dim);
4219 GO glob_i, glob_j;
4220 vec_dbl_Type v_i(dim);
4221 vec_dbl_Type v_j(dim);
4222
4223 SC refElementSize;
4224 SC refElementScale;
4225 if(FEType=="P1"){
4226 if (dim==2) {
4227 refElementSize = 0.5;
4228 refElementScale = 1./9.;
4229 }
4230 else if(dim==3){
4231 refElementSize = 1./6.;
4232 refElementScale = 1./16.;
4233 }
4234 }
4235 else if(FEType=="Q1"){
4236 if(dim==3){
4237 refElementScale=1./64;
4238 refElementSize=8.;
4239 }
4240 else{
4241 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Q1 Only implemented for 3D.");
4242 }
4243 }
4244
4245 for (UN T=0; T<elements->numberElements(); T++) {
4246
4247 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4248 detB = B.computeDet( );
4249 absDetB = std::fabs(detB);
4250
4251 for (UN i=0; i < phi->at(0).size(); i++) {
4252 Teuchos::Array<SC> value( phi->at(0).size(), 0. );
4253 Teuchos::Array<GO> indices( phi->at(0).size(), 0 );
4254 for (UN j=0; j < value.size(); j++) {
4255 for (UN w=0; w<phi->size(); w++) {
4256 value[j] += weights->at(w) * (*phi)[w][i] * (*phi)[w][j];
4257 }
4258 value[j] *= absDetB;
4259 value[j] -= refElementSize * absDetB * refElementScale;
4260
4261 indices[j] = map->getGlobalElement( elements->getElement(T).getNode(j) );
4262 }
4263
4264 GO row = map->getGlobalElement( elements->getElement(T).getNode(i) );
4265 A->insertGlobalValues( row, indices(), value() );
4266 }
4267
4268 }
4269
4270 if (callFillComplete)
4271 A->fillComplete();
4272}
4273
4274
4275
4276template <class SC, class LO, class GO, class NO>
4278 std::string FEType,
4279 MatrixPtr_Type &A,
4280 CoeffFuncDbl_Type func,
4281 double* parameters,
4282 bool callFillComplete)
4283{
4284 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4285 int FEloc = this->checkFE(dim,FEType);
4286
4287 DomainConstPtr_Type domain = domainVec_.at(FEloc);
4288 ElementsPtr_Type elements = domain->getElementsC();
4289 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
4290 MapConstPtr_Type map = domain->getMapRepeated();
4291
4292 vec3D_dbl_ptr_Type dPhi;
4293 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4294 vec2D_dbl_ptr_Type quadPts;
4295
4296 // double val, value1_j, value2_j , value1_i, value2_i;
4297
4298 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4299
4300 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4301 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi, FEType);
4302
4303 // SC = double, GO = long, UN = int
4304 SC detB;
4305 SC absDetB;
4306 SmallMatrix<SC> B(dim);
4307 SmallMatrix<SC> Binv(dim);
4308 GO glob_i, glob_j;
4309
4310
4311 vec_dbl_ptr_Type dist = domain->getDistancesToInterface();
4312 if (dim == 2)
4313 {
4314 double val, value1_j, value2_j , value1_i, value2_i;
4315 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
4316
4317 double distance1, distance2, distance3;
4318 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
4319 for (int T = 0; T < elements->numberElements(); T++)
4320 {
4321 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4322 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4323 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4324
4325 distance1 = dist->at(elements->getElement(T).getNode(0));
4326 distance2 = dist->at(elements->getElement(T).getNode(1));
4327 distance3 = dist->at(elements->getElement(T).getNode(2));
4328
4329 distance_mean.at(0) = (distance1 + distance2 + distance3)/3.0; // Mittelwert
4330 double funcvalue = func(&distance_mean.at(0),parameters);
4331
4332 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4333 detB = B.computeInverse(Binv);
4334 absDetB = std::fabs(detB);
4335
4336 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4337 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4338 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4339
4340 for (int i = 0; i < dPhi->at(0).size(); i++)
4341 {
4342 Teuchos::Array<SC> value( 1, 0. );
4343 Teuchos::Array<GO> indices( 1, 0 );
4344
4345 for (int j = 0; j < dPhi->at(0).size(); j++)
4346 {
4347 val = 0.0;
4348 for (int k = 0; k < dPhi->size(); k++)
4349 {
4350
4351 value1_j = dPhiTrans.at(k).at(j).at(0);
4352 value2_j = dPhiTrans.at(k).at(j).at(1);
4353
4354 value1_i = dPhiTrans.at(k).at(i).at(0);
4355 value2_i = dPhiTrans.at(k).at(i).at(1);
4356
4357 val = val + funcvalue * weightsDPhi->at(k) * ( value1_j*value1_i + value2_j*value2_i );
4358 }
4359 val = absDetB * val;
4360 value[0] = val;
4361
4362 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4363 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4364 indices[0] = glob_j;
4365
4366
4367 A->insertGlobalValues(glob_i, indices(), value());
4368 glob_j++;
4369 indices[0] = glob_j;
4370 A->insertGlobalValues(glob_i+1, indices(), value());
4371 }
4372 }
4373 }
4374 if (callFillComplete)
4375 {
4376 A->fillComplete();
4377 }
4378 }
4379 else if(dim == 3)
4380 {
4381 double val, value1_j, value2_j ,value3_j, value1_i, value2_i ,value3_i;
4382
4383 long long glob_i, glob_j;
4384 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4385
4386 double distance1, distance2, distance3, distance4;
4387 vec_dbl_Type distance_mean(1); // Durchschnittliche Distanz des elements T
4388 for (int T = 0; T < elements->numberElements(); T++)
4389 {
4390 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4391 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4392 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4393 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4394
4395 distance1 = dist->at(elements->getElement(T).getNode(0));
4396 distance2 = dist->at(elements->getElement(T).getNode(1));
4397 distance3 = dist->at(elements->getElement(T).getNode(2));
4398 distance4 = dist->at(elements->getElement(T).getNode(3));
4399
4400 distance_mean.at(0) = (distance1 + distance2 + distance3 + distance4)/4.0; //Mittelwert
4401 double funcvalue = func(&distance_mean.at(0),parameters);
4402
4403 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4404 detB = B.computeInverse(Binv);
4405 absDetB = std::fabs(detB);
4406
4407 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4408 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4409 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4410
4411 for (int i = 0; i < dPhi->at(0).size(); i++)
4412 {
4413 Teuchos::Array<SC> value( 1, 0. );
4414 Teuchos::Array<GO> indices( 1, 0 );
4415
4416 for (int j = 0; j < dPhi->at(0).size(); j++)
4417 {
4418 val = 0.0;
4419 for (int k = 0; k < dPhi->size(); k++)
4420 {
4421 value1_j = dPhiTrans.at(k).at(j).at(0);
4422 value2_j = dPhiTrans.at(k).at(j).at(1);
4423 value3_j = dPhiTrans.at(k).at(j).at(2);
4424
4425 value1_i = dPhiTrans.at(k).at(i).at(0);
4426 value2_i = dPhiTrans.at(k).at(i).at(1);
4427 value3_i = dPhiTrans.at(k).at(i).at(2);
4428
4429 val = val + funcvalue * weightsDPhi->at(k) * (value1_j*value1_i + value2_j*value2_i + value3_j*value3_i);
4430 }
4431 val = absDetB * val;
4432 value[0] = val;
4433
4434 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4435 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4436 indices[0] = glob_j;
4437 A->insertGlobalValues(glob_i, indices(), value());
4438 glob_j++;
4439 indices[0] = glob_j;
4440 A->insertGlobalValues(glob_i+1, indices(), value());
4441 glob_j++;
4442 indices[0] = glob_j;
4443 A->insertGlobalValues(glob_i+2, indices(), value());
4444
4445 }
4446 }
4447 }
4448 if (callFillComplete)
4449 {
4450 A->fillComplete();
4451 }
4452 }
4453
4454}
4455
4456
4457
4458template <class SC, class LO, class GO, class NO>
4460 std::string FEType,
4461 MatrixPtr_Type &A,
4462 CoeffFunc_Type func,
4463 int* parameters,
4464 bool callFillComplete)
4465{
4466 // 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.
4467 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4468 int FEloc = this->checkFE(dim,FEType);
4469
4470 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4471 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4472 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4473
4474 vec3D_dbl_ptr_Type dPhi;
4475 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4476 vec2D_dbl_ptr_Type quadPts;
4477
4478 // double value, value1_j, value2_j , value1_i, value2_i;
4479
4480 // inner( grad(u) + grad(u)^T , grad(v) ) has twice the polyonimial degree than grad(u) or grad(v).
4481 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4482 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4483 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4484
4485 // SC = double, GO = long, UN = int
4486 SC detB;
4487 SC absDetB;
4488 SmallMatrix<SC> B(dim);
4489 SmallMatrix<SC> Binv(dim);
4490 GO glob_i, glob_j;
4491
4492 if (dim == 2)
4493 {
4494 double v11, v12, v21, v22, value1_j, value2_j , value1_i, value2_i;
4495 double e_11_j_1,e_12_j_1,e_21_j_1,e_22_j_1;
4496 double e_11_j_2,e_12_j_2,e_21_j_2,e_22_j_2;
4497 double e_11_i_1,e_12_i_1,e_21_i_1,e_22_i_1;
4498 double e_11_i_2,e_12_i_2,e_21_i_2,e_22_i_2;
4499
4500 SmallMatrix<double> tmpRes1(dim);
4501 SmallMatrix<double> tmpRes2(dim);
4502 SmallMatrix<double> e1i(dim);
4503 SmallMatrix<double> e2i(dim);
4504 SmallMatrix<double> e1j(dim);
4505 SmallMatrix<double> e2j(dim);
4506
4507 long long glob_i, glob_j;
4508 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
4509
4510 vec_dbl_Type xy(2);
4511 for (int T = 0; T < elements->numberElements(); T++)
4512 {
4513 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4514 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4515 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4516
4517 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
4518 detB = B.computeInverse(Binv);
4519 absDetB = std::fabs(detB);
4520
4521 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1)
4522 // Also \hat{grad_phi}.
4523 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4524 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4525
4526 for (int i = 0; i < dPhi->at(0).size(); i++)
4527 {
4528 Teuchos::Array<SC> value11( 1, 0. );
4529 Teuchos::Array<SC> value12( 1, 0. );
4530 Teuchos::Array<SC> value21( 1, 0. );
4531 Teuchos::Array<SC> value22( 1, 0. );
4532 Teuchos::Array<GO> indices( 1, 0 );
4533
4534 for (int j=0; j < dPhi->at(0).size(); j++)
4535 {
4536 v11 = 0.0;v12 = 0.0;v21 = 0.0;v22 = 0.0;
4537 for (int k = 0; k < dPhi->size(); k++)
4538 {
4539 // Mappen der Gausspunkte (definiert auf T_ref) auf T (bzw. \Omega)
4540 // xy = F(quadPts) = B*quadPts + b, mit b = p1 (affin lineare Transformation)
4541 xy[0]=0.; xy[1]=0.;
4542 for (int r=0; r<2; r++) {
4543 xy[0] += B[0][r]*quadPts->at(k).at(r);
4544 xy[1] += B[1][r]*quadPts->at(k).at(r);
4545 }
4546 xy[0] += p1[0];
4547 xy[1] += p1[1];
4548
4549 value1_j = dPhiTrans.at(k).at(j).at(0);
4550 value2_j = dPhiTrans.at(k).at(j).at(1);
4551
4552 value1_i = dPhiTrans.at(k).at(i).at(0);
4553 value2_i = dPhiTrans.at(k).at(i).at(1);
4554
4555 tmpRes1[0][0] = value1_j;
4556 tmpRes1[0][1] = value2_j;
4557 tmpRes1[1][0] = 0.;
4558 tmpRes1[1][1] = 0.;
4559
4560 tmpRes2[0][0] = value1_j;
4561 tmpRes2[0][1] = 0.;
4562 tmpRes2[1][0] = value2_j;
4563 tmpRes2[1][1] = 0.;
4564
4565 tmpRes1.add(tmpRes2,e1j/*result*/);
4566
4567 e1i[0][0] = value1_i;
4568 e1i[0][1] = value2_i;
4569
4570
4571 tmpRes1[0][0] = 0.;
4572 tmpRes1[0][1] = 0.;
4573 tmpRes1[1][0] = value1_j;
4574 tmpRes1[1][1] = value2_j;
4575
4576 tmpRes2[0][0] = 0.;
4577 tmpRes2[0][1] = value1_j;
4578 tmpRes2[1][0] = 0.;
4579 tmpRes2[1][1] = value2_j;
4580
4581 tmpRes1.add(tmpRes2,e2j/*result*/);
4582
4583 e2i[1][0] = value1_i;
4584 e2i[1][1] = value2_i;
4585
4586 double funcvalue = func(&xy.at(0),parameters);
4587 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
4588 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
4589 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
4590 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
4591
4592 }
4593
4594 v11 = absDetB * v11;
4595 v12 = absDetB * v12;
4596 v21 = absDetB * v21;
4597 v22 = absDetB * v22;
4598
4599 value11[0] = v11;
4600 value12[0] = v12;
4601 value21[0] = v21;
4602 value22[0] = v22;
4603
4604 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4605 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4606 indices[0] = glob_j;
4607
4608 A->insertGlobalValues(glob_i, indices(), value11());
4609 A->insertGlobalValues(glob_i+1, indices(), value21());
4610 glob_j++;
4611 indices[0] = glob_j;
4612 A->insertGlobalValues(glob_i, indices(), value12());
4613 A->insertGlobalValues(glob_i+1, indices(), value22());
4614 }
4615 }
4616 }
4617 if (callFillComplete)
4618 {
4619 A->fillComplete();
4620 }
4621 }
4622 else if(dim == 3)
4623 {
4624 double v11, v12, v13, v21, v22, v23, v31, v32, v33, value1_j, value2_j, value3_j , value1_i, value2_i, value3_i;
4625
4626 SmallMatrix<double> e1i(dim);
4627 SmallMatrix<double> e2i(dim);
4628 SmallMatrix<double> e3i(dim);
4629 SmallMatrix<double> e1j(dim);
4630 SmallMatrix<double> e2j(dim);
4631 SmallMatrix<double> e3j(dim);
4632
4633 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4634 vec_dbl_Type xyz(3);
4635
4636 for (int T = 0; T < elements->numberElements(); T++)
4637 {
4638 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4639 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4640 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4641 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4642
4643 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4644 detB = B.computeInverse(Binv);
4645 absDetB = std::fabs(detB);
4646
4647 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4648 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4649 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4650
4651 for (int i = 0; i < dPhi->at(0).size(); i++)
4652 {
4653 Teuchos::Array<SC> value11( 1, 0. );
4654 Teuchos::Array<SC> value12( 1, 0. );
4655 Teuchos::Array<SC> value13( 1, 0. );
4656 Teuchos::Array<SC> value21( 1, 0. );
4657 Teuchos::Array<SC> value22( 1, 0. );
4658 Teuchos::Array<SC> value23( 1, 0. );
4659 Teuchos::Array<SC> value31( 1, 0. );
4660 Teuchos::Array<SC> value32( 1, 0. );
4661 Teuchos::Array<SC> value33( 1, 0. );
4662 Teuchos::Array<GO> indices( 1, 0 );
4663
4664 for (int j = 0; j < dPhi->at(0).size(); j++)
4665 {
4666 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;
4667 for (int k = 0; k < dPhi->size(); k++)
4668 {
4669
4670 xyz[0]=0.; xyz[1]=0.; xyz[2]=0.;
4671 for (int r = 0; r < 3; r++)
4672 {
4673 xyz[0] += B[0][r]*quadPts->at(k).at(r);
4674 xyz[1] += B[1][r]*quadPts->at(k).at(r);
4675 xyz[2] += B[2][r]*quadPts->at(k).at(r);
4676 }
4677 xyz[0] += p1[0];
4678 xyz[1] += p1[1];
4679 xyz[2] += p1[2];
4680
4681
4682
4683 value1_j = dPhiTrans.at(k).at(j).at(0);
4684 value2_j = dPhiTrans.at(k).at(j).at(1);
4685 value3_j = dPhiTrans.at(k).at(j).at(2);
4686
4687
4688 value1_i = dPhiTrans.at(k).at(i).at(0);
4689 value2_i = dPhiTrans.at(k).at(i).at(1);
4690 value3_i = dPhiTrans.at(k).at(i).at(2);
4691
4692
4693 e1j[0][0] = 2.*value1_j;
4694 e1j[0][1] = value2_j;
4695 e1j[0][2] = value3_j;
4696 e1j[1][0] = value2_j;
4697 e1j[2][0] = value3_j;
4698
4699 e1i[0][0] = value1_i;
4700 e1i[0][1] = value2_i;
4701 e1i[0][2] = value3_i;
4702
4703
4704 e2j[1][0] = value1_j;
4705 e2j[1][1] = 2.*value2_j;
4706 e2j[1][2] = value3_j;
4707 e2j[0][1] = value1_j;
4708 e2j[2][1] = value3_j;
4709
4710 e2i[1][0] = value1_i;
4711 e2i[1][1] = value2_i;
4712 e2i[1][2] = value3_i;
4713
4714
4715 e3j[2][0] = value1_j;
4716 e3j[2][1] = value2_j;
4717 e3j[2][2] = 2.*value3_j;
4718 e3j[0][2] = value1_j;
4719 e3j[1][2] = value2_j;
4720
4721 e3i[2][0] = value1_i;
4722 e3i[2][1] = value2_i;
4723 e3i[2][2] = value3_i;
4724
4725 double funcvalue = func(&xyz.at(0),parameters);
4726
4727 v11 = v11 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e1j);
4728 v12 = v12 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e2j);
4729 v13 = v13 + funcvalue * weightsDPhi->at(k) * e1i.innerProduct(e3j);
4730
4731 v21 = v21 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e1j);
4732 v22 = v22 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e2j);
4733 v23 = v23 + funcvalue * weightsDPhi->at(k) * e2i.innerProduct(e3j);
4734
4735 v31 = v31 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e1j);
4736 v32 = v32 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e2j);
4737 v33 = v33 + funcvalue * weightsDPhi->at(k) * e3i.innerProduct(e3j);
4738
4739
4740 }
4741 v11 = absDetB * v11;
4742 v12 = absDetB * v12;
4743 v13 = absDetB * v13;
4744 v21 = absDetB * v21;
4745 v22 = absDetB * v22;
4746 v23 = absDetB * v23;
4747 v31 = absDetB * v31;
4748 v32 = absDetB * v32;
4749 v33 = absDetB * v33;
4750
4751 value11[0] = v11;
4752 value12[0] = v12;
4753 value13[0] = v13;
4754 value21[0] = v21;
4755 value22[0] = v22;
4756 value23[0] = v23;
4757 value31[0] = v31;
4758 value32[0] = v32;
4759 value33[0] = v33;
4760
4761 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4762 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4763 indices[0] = glob_j;
4764 A->insertGlobalValues(glob_i, indices(), value11());
4765 A->insertGlobalValues(glob_i+1, indices(), value21());
4766 A->insertGlobalValues(glob_i+2, indices(), value31());
4767
4768 glob_j++;
4769 indices[0] = glob_j;
4770 A->insertGlobalValues(glob_i, indices(), value12());
4771 A->insertGlobalValues(glob_i+1, indices(), value22());
4772 A->insertGlobalValues(glob_i+2, indices(), value32());
4773
4774 glob_j++;
4775 indices[0] = glob_j;
4776 A->insertGlobalValues(glob_i, indices(), value13());
4777 A->insertGlobalValues(glob_i+1, indices(), value23());
4778 A->insertGlobalValues(glob_i+2, indices(), value33());
4779 }
4780 }
4781 }
4782 if (callFillComplete)
4783 {
4784 A->fillComplete();
4785 }
4786 }
4787
4788}
4789
4790
4791
4792template <class SC, class LO, class GO, class NO>
4794 std::string FEType,
4795 MatrixPtr_Type &A,
4796 double lambda,
4797 double mu,
4798 bool callFillComplete)
4799{
4800 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
4801 int FEloc = this->checkFE(dim,FEType);
4802
4803 // Hole Elemente und Knotenliste
4804 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
4805 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
4806 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
4807
4808 vec3D_dbl_ptr_Type dPhi;
4809 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
4810 vec2D_dbl_ptr_Type quadPts;
4811
4812 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
4813
4814 // Hole die grad_phi, hier DPhi
4815 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
4816 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
4817
4818 // Definiere die Basisfunktion \phi_i bzw. \phi_j
4819 // vec_dbl_Type basisValues_i(dim,0.), basisValues_j(dim,0.);
4820
4821 // SC = double, GO = long, UN = int
4822 SC detB;
4823 SC absDetB;
4824 SmallMatrix<SC> B(dim);
4825 SmallMatrix<SC> Binv(dim);
4826 GO glob_i, glob_j;
4827
4828 // Fuer Zwischenergebniss
4829 SC res;
4830
4831 // Fuer die Berechnung der Spur
4832 double res_trace_i, res_trace_j;
4833
4834 if (dim == 2)
4835 {
4836
4837 double v11, v12, v21, v22;
4838 // Setzte Vektoren der Groesse 2 und initialisiere mit 0.0 (double)
4839 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
4840
4841 // Matrizen der Groesse (2x2) in denen die einzelnen Epsilon-Tensoren berechnet werden.
4842 // Siehe unten fuer mehr.
4843 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
4844 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
4845
4846 for (int T = 0; T < elements->numberElements(); T++)
4847 {
4848 // Hole die Eckknoten des Dreiecks
4849 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4850 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4851 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4852
4853 // Berechne die Transormationsmatrix B fuer das jeweilige Element (2D)
4854 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4855 detB = B.computeInverse(Binv);
4856 absDetB = std::fabs(detB);
4857
4858 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1).
4859 // Also \hat{grad_phi}.
4860 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4861 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4862
4863 for (int i = 0; i < dPhi->at(0).size(); i++)
4864 {
4865 Teuchos::Array<SC> value11( 1, 0. );
4866 Teuchos::Array<SC> value12( 1, 0. );
4867 Teuchos::Array<SC> value21( 1, 0. );
4868 Teuchos::Array<SC> value22( 1, 0. );
4869 Teuchos::Array<GO> indices( 1, 0 );
4870
4871 for (int j = 0; j < dPhi->at(0).size(); j++)
4872 {
4873 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
4874 for (int k = 0; k < dPhi->size(); k++)
4875 {
4876 // In epsilonValuesMat1_i (2x2 Matrix) steht fuer die Ansatzfunktion i bzw. \phi_i
4877 // der epsilonTensor fuer eine skalare Ansatzfunktion fuer die Richtung 1 (vgl. Mat1).
4878 // Also in Mat1_i wird dann also phi_i = (phi_scalar_i, 0) gesetzt und davon \eps berechnet.
4879
4880 // Stelle \hat{grad_phi_i} = basisValues_i auf, also B^(-T)*grad_phi_i
4881 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
4882
4883 // \eps(v) = \eps(phi_i)
4884 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
4885 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
4886
4887 // Siehe oben, nur fuer j
4888 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4889
4890 // \eps(u) = \eps(phi_j)
4891 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
4892 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
4893
4894 // Nun berechnen wir \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
4895 // Das Ergebniss steht in res.
4896 // Berechne zudem noch die Spur der Epsilon-Tensoren tr(\eps(u)) (j) und tr(\eps(v)) (i)
4897 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
4898 epsilonValuesMat1_i.trace(res_trace_i);
4899 epsilonValuesMat1_j.trace(res_trace_j);
4900 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4901
4902 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
4903 epsilonValuesMat1_i.trace(res_trace_i);
4904 epsilonValuesMat2_j.trace(res_trace_j);
4905 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4906
4907 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
4908 epsilonValuesMat2_i.trace(res_trace_i);
4909 epsilonValuesMat1_j.trace(res_trace_j);
4910 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4911
4912 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
4913 epsilonValuesMat2_i.trace(res_trace_i);
4914 epsilonValuesMat2_j.trace(res_trace_j);
4915 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
4916
4917
4918 }
4919 // Noch mit der abs(det(B)) skalieren
4920 v11 = absDetB * v11;
4921 v12 = absDetB * v12;
4922 v21 = absDetB * v21;
4923 v22 = absDetB * v22;
4924
4925 value11[0] = v11;
4926 value12[0] = v12;
4927 value21[0] = v21;
4928 value22[0] = v22;
4929
4930 // Hole die globale Zeile und Spalte in der die Eintraege hingeschrieben werden sollen
4931 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
4932 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
4933 indices[0] = glob_j;
4934 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
4935 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
4936 glob_j++;
4937 indices[0] = glob_j;
4938 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
4939 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
4940 }
4941 }
4942 }
4943 if (callFillComplete)
4944 {
4945 A->fillComplete();
4946 }
4947 }
4948 else if(dim == 3)
4949 {
4950
4951 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
4952
4953 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
4954 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
4955 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
4956
4957 for (int T = 0; T < elements->numberElements(); T++)
4958 {
4959 p1 = pointsRep->at(elements->getElement(T).getNode(0));
4960 p2 = pointsRep->at(elements->getElement(T).getNode(1));
4961 p3 = pointsRep->at(elements->getElement(T).getNode(2));
4962 p4 = pointsRep->at(elements->getElement(T).getNode(3));
4963
4964 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
4965 detB = B.computeInverse(Binv);
4966 absDetB = std::fabs(detB);
4967
4968 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
4969 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
4970 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
4971
4972 for (int i = 0; i < dPhi->at(0).size(); i++)
4973 {
4974 Teuchos::Array<SC> value11( 1, 0. );
4975 Teuchos::Array<SC> value12( 1, 0. );
4976 Teuchos::Array<SC> value13( 1, 0. );
4977 Teuchos::Array<SC> value21( 1, 0. );
4978 Teuchos::Array<SC> value22( 1, 0. );
4979 Teuchos::Array<SC> value23( 1, 0. );
4980 Teuchos::Array<SC> value31( 1, 0. );
4981 Teuchos::Array<SC> value32( 1, 0. );
4982 Teuchos::Array<SC> value33( 1, 0. );
4983 Teuchos::Array<GO> indices( 1, 0 );
4984
4985 for (int j = 0; j < dPhi->at(0).size(); j++)
4986 {
4987 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;
4988 for (int k = 0; k < dPhi->size(); k++)
4989 {
4990
4991 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
4992
4993 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
4994 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
4995 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
4996
4997
4998 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
4999
5000 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
5001 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
5002 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
5003
5004 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
5005 epsilonValuesMat1_i.trace(res_trace_i);
5006 epsilonValuesMat1_j.trace(res_trace_j);
5007 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5008
5009 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
5010 epsilonValuesMat1_i.trace(res_trace_i);
5011 epsilonValuesMat2_j.trace(res_trace_j);
5012 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5013
5014 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
5015 epsilonValuesMat1_i.trace(res_trace_i);
5016 epsilonValuesMat3_j.trace(res_trace_j);
5017 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5018
5019 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
5020 epsilonValuesMat2_i.trace(res_trace_i);
5021 epsilonValuesMat1_j.trace(res_trace_j);
5022 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5023
5024 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5025 epsilonValuesMat2_i.trace(res_trace_i);
5026 epsilonValuesMat2_j.trace(res_trace_j);
5027 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5028
5029 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
5030 epsilonValuesMat2_i.trace(res_trace_i);
5031 epsilonValuesMat3_j.trace(res_trace_j);
5032 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5033
5034 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
5035 epsilonValuesMat3_i.trace(res_trace_i);
5036 epsilonValuesMat1_j.trace(res_trace_j);
5037 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5038
5039 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
5040 epsilonValuesMat3_i.trace(res_trace_i);
5041 epsilonValuesMat2_j.trace(res_trace_j);
5042 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5043
5044 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
5045 epsilonValuesMat3_i.trace(res_trace_i);
5046 epsilonValuesMat3_j.trace(res_trace_j);
5047 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5048
5049 }
5050 v11 = absDetB * v11;
5051 v12 = absDetB * v12;
5052 v13 = absDetB * v13;
5053 v21 = absDetB * v21;
5054 v22 = absDetB * v22;
5055 v23 = absDetB * v23;
5056 v31 = absDetB * v31;
5057 v32 = absDetB * v32;
5058 v33 = absDetB * v33;
5059
5060 value11[0] = v11;
5061 value12[0] = v12;
5062 value13[0] = v13;
5063 value21[0] = v21;
5064 value22[0] = v22;
5065 value23[0] = v23;
5066 value31[0] = v31;
5067 value32[0] = v32;
5068 value33[0] = v33;
5069
5070 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5071 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5072 indices[0] = glob_j;
5073 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5074 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5075 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
5076 glob_j++;
5077 indices[0] = glob_j;
5078 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5079 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5080 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
5081 glob_j++;
5082 indices[0] = glob_j;
5083 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
5084 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
5085 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
5086 }
5087 }
5088 }
5089 if (callFillComplete)
5090 {
5091 A->fillComplete();
5092 }
5093 }
5094}
5095
5096// Determine the change of emodule depending on concentration
5097template <class SC, class LO, class GO, class NO>
5098void FE<SC,LO,GO,NO>::determineEMod(std::string FEType, MultiVectorPtr_Type solution,MultiVectorPtr_Type &eModVec, DomainConstPtr_Type domain, ParameterListPtr_Type params){
5099
5100
5101 ElementsPtr_Type elements = domain->getElementsC();
5102
5103 int dim = domain->getDimension();
5104 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5105
5106 //MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
5107
5108 Teuchos::ArrayRCP< const SC > uArray = solution->getData(0);
5109 Teuchos::ArrayRCP< SC > eModVecA = eModVec->getDataNonConst(0);
5110
5111 double E0 = params->sublist("Parameter Solid").get("E",3.0e+6);
5112 double E1 = params->sublist("Parameter Solid").get("E1",3.0e+5);
5113 double c1 = params->sublist("Parameter Solid").get("c1",1.0);
5114 double eModMax =E1;
5115 double eModMin = E0;
5116
5117 int nodesElement = elements->getElement(0).getVectorNodeList().size();
5118 for (UN T=0; T<elements->numberElements(); T++) {
5119
5120 /*buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
5121 detB = B.computeInverse(Binv);
5122 absDetB = std::fabs(detB);*/
5123
5124 double uLoc = 0.;
5125
5126 for(int i=0; i< nodesElement;i++){
5127 LO index = elements->getElement(T).getNode(i) ;
5128 uLoc += 1./nodesElement*uArray[index];
5129 }
5130
5131 eModVecA[T] = E0-(E0-E1)*(uLoc/(uLoc+c1));
5132 if(eModVecA[T] > eModMax )
5133 eModMax = eModVecA[T];
5134 if(eModVecA[T] < eModMin)
5135 eModMin = eModVecA[T];
5136 }
5137 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MIN, eModMin, Teuchos::outArg (eModMin));
5138 Teuchos::reduceAll<int, double> (*(domain->getComm()), Teuchos::REDUCE_MAX, eModMax, Teuchos::outArg (eModMax));
5139
5140 if(domain->getComm()->getRank()==0)
5141 std::cout << " ################# eMOD Min: " << eModMin << " \t eModMax: " << eModMax<< " ############# " << std::endl;
5142
5143
5144}
5145
5146
5148template <class SC, class LO, class GO, class NO>
5150 std::string FEType,
5151 MatrixPtr_Type &A,
5152 MultiVectorPtr_Type eModVec,
5153 double nu,
5154 bool callFillComplete)
5155{
5156 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
5157 int FEloc = this->checkFE(dim,FEType);
5158 // Hole Elemente und Knotenliste
5159 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
5160 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
5161 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
5162
5163 vec3D_dbl_ptr_Type dPhi;
5164 vec_dbl_ptr_Type weightsDPhi = Teuchos::rcp(new vec_dbl_Type(0));
5165 vec2D_dbl_ptr_Type quadPts;
5166
5167 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv1);
5168
5169 // Hole die grad_phi, hier DPhi
5170 Helper::getDPhi(dPhi, weightsDPhi, dim, FEType, deg);
5171 Helper::getQuadratureValues(dim, deg, quadPts, weightsDPhi,FEType);
5172
5173 SC detB;
5174 SC absDetB;
5175 SmallMatrix<SC> B(dim);
5176 SmallMatrix<SC> Binv(dim);
5177 GO glob_i, glob_j;
5178
5179 // Fuer Zwischenergebniss
5180 SC res;
5181
5182 // Fuer die Berechnung der Spur
5183 double res_trace_i, res_trace_j;
5184
5185 Teuchos::ArrayRCP< const SC > E = eModVec->getData(0);
5186 double lambda;
5187 double mu ;
5188
5189 if (dim == 2)
5190 {
5191
5192 double v11, v12, v21, v22;
5193 // Setzte Vektoren der Groesse 2 und initialisiere mit 0.0 (double)
5194 vec_dbl_Type p1(2,0.0), p2(2,0.0), p3(2,0.0);
5195
5196 // Matrizen der Groesse (2x2) in denen die einzelnen Epsilon-Tensoren berechnet werden.
5197 // Siehe unten fuer mehr.
5198 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim),
5199 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim);
5200
5201 for (int T = 0; T < elements->numberElements(); T++)
5202 {
5204 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
5205 mu = E[T] / (2.*(1.+nu));
5206
5207 // Hole die Eckknoten des Dreiecks
5208 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5209 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5210 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5211
5212 // Berechne die Transormationsmatrix B fuer das jeweilige Element (2D)
5213 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5214 detB = B.computeInverse(Binv);
5215 absDetB = std::fabs(detB);
5216
5217 // dPhiTrans sind die transformierten Basifunktionen, also B^(-T) * \grad_phi bzw. \grad_phi^T * B^(-1).
5218 // Also \hat{grad_phi}.
5219 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5220 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5221
5222 for (int i = 0; i < dPhi->at(0).size(); i++)
5223 {
5224 Teuchos::Array<SC> value11( 1, 0. );
5225 Teuchos::Array<SC> value12( 1, 0. );
5226 Teuchos::Array<SC> value21( 1, 0. );
5227 Teuchos::Array<SC> value22( 1, 0. );
5228 Teuchos::Array<GO> indices( 1, 0 );
5229
5230 for (int j = 0; j < dPhi->at(0).size(); j++)
5231 {
5232 v11 = 0.0; v12 = 0.0; v21 = 0.0; v22 = 0.0;
5233 for (int k = 0; k < dPhi->size(); k++)
5234 {
5235 // In epsilonValuesMat1_i (2x2 Matrix) steht fuer die Ansatzfunktion i bzw. \phi_i
5236 // der epsilonTensor fuer eine skalare Ansatzfunktion fuer die Richtung 1 (vgl. Mat1).
5237 // Also in Mat1_i wird dann also phi_i = (phi_scalar_i, 0) gesetzt und davon \eps berechnet.
5238
5239 // Stelle \hat{grad_phi_i} = basisValues_i auf, also B^(-T)*grad_phi_i
5240 // GradPhiOnRef( dPhi->at(k).at(i), b_T_inv, basisValues_i );
5241
5242 // \eps(v) = \eps(phi_i)
5243 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
5244 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
5245
5246 // Siehe oben, nur fuer j
5247 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
5248
5249 // \eps(u) = \eps(phi_j)
5250 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
5251 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
5252
5253 // Nun berechnen wir \eps(u):\eps(v) = \eps(phi_j):\eps(phi_i).
5254 // Das Ergebniss steht in res.
5255 // Berechne zudem noch die Spur der Epsilon-Tensoren tr(\eps(u)) (j) und tr(\eps(v)) (i)
5256 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
5257 epsilonValuesMat1_i.trace(res_trace_i);
5258 epsilonValuesMat1_j.trace(res_trace_j);
5259 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5260
5261 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
5262 epsilonValuesMat1_i.trace(res_trace_i);
5263 epsilonValuesMat2_j.trace(res_trace_j);
5264 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5265
5266 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
5267 epsilonValuesMat2_i.trace(res_trace_i);
5268 epsilonValuesMat1_j.trace(res_trace_j);
5269 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5270
5271 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5272 epsilonValuesMat2_i.trace(res_trace_i);
5273 epsilonValuesMat2_j.trace(res_trace_j);
5274 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5275
5276
5277 }
5278 // Noch mit der abs(det(B)) skalieren
5279 v11 = absDetB * v11;
5280 v12 = absDetB * v12;
5281 v21 = absDetB * v21;
5282 v22 = absDetB * v22;
5283
5284 value11[0] = v11;
5285 value12[0] = v12;
5286 value21[0] = v21;
5287 value22[0] = v22;
5288
5289 // Hole die globale Zeile und Spalte in der die Eintraege hingeschrieben werden sollen
5290 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5291 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5292 indices[0] = glob_j;
5293 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5294 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5295 glob_j++;
5296 indices[0] = glob_j;
5297 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5298 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5299 }
5300 }
5301 }
5302 if (callFillComplete)
5303 {
5304 A->fillComplete();
5305 }
5306 }
5307 else if(dim == 3)
5308 {
5309
5310 double v11, v12, v13, v21, v22, v23, v31, v32, v33;
5311
5312 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
5313 SmallMatrix<double> epsilonValuesMat1_i(dim), epsilonValuesMat2_i(dim), epsilonValuesMat3_i(dim),
5314 epsilonValuesMat1_j(dim), epsilonValuesMat2_j(dim), epsilonValuesMat3_j(dim);
5315
5316 for (int T = 0; T < elements->numberElements(); T++)
5317 {
5318 lambda = E[T]* nu / ((1.+nu)*(1.-2.*nu));
5319 mu = E[T] / (2.*(1.+nu));
5320
5321 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5322 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5323 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5324 p4 = pointsRep->at(elements->getElement(T).getNode(3));
5325
5326 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5327 detB = B.computeInverse(Binv);
5328 absDetB = std::fabs(detB);
5329
5330 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5331 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5332 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5333
5334 for (int i = 0; i < dPhi->at(0).size(); i++)
5335 {
5336
5337 Teuchos::Array<SC> value11( 1, 0. );
5338 Teuchos::Array<SC> value12( 1, 0. );
5339 Teuchos::Array<SC> value13( 1, 0. );
5340 Teuchos::Array<SC> value21( 1, 0. );
5341 Teuchos::Array<SC> value22( 1, 0. );
5342 Teuchos::Array<SC> value23( 1, 0. );
5343 Teuchos::Array<SC> value31( 1, 0. );
5344 Teuchos::Array<SC> value32( 1, 0. );
5345 Teuchos::Array<SC> value33( 1, 0. );
5346 Teuchos::Array<GO> indices( 1, 0 );
5347
5348 for (int j = 0; j < dPhi->at(0).size(); j++)
5349 {
5350 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;
5351 for (int k = 0; k < dPhi->size(); k++)
5352 {
5353
5354 // GradPhiOnRef( DPhi->at(k).at(i), b_T_inv, basisValues_i );
5355
5356 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat1_i, 0); // x-Richtung
5357 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat2_i, 1); // y-Richtung
5358 epsilonTensor( dPhiTrans.at(k).at(i), epsilonValuesMat3_i, 2); // z-Richtung
5359
5360
5361 // GradPhiOnRef( DPhi->at(k).at(j), b_T_inv, basisValues_j );
5362
5363 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat1_j, 0); // x-Richtung
5364 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat2_j, 1); // y-Richtung
5365 epsilonTensor( dPhiTrans.at(k).at(j), epsilonValuesMat3_j, 2); // z-Richtung
5366
5367 epsilonValuesMat1_i.innerProduct(epsilonValuesMat1_j, res); // x-x
5368 epsilonValuesMat1_i.trace(res_trace_i);
5369 epsilonValuesMat1_j.trace(res_trace_j);
5370 v11 = v11 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5371
5372 epsilonValuesMat1_i.innerProduct(epsilonValuesMat2_j, res); // x-y
5373 epsilonValuesMat1_i.trace(res_trace_i);
5374 epsilonValuesMat2_j.trace(res_trace_j);
5375 v12 = v12 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5376
5377 epsilonValuesMat1_i.innerProduct(epsilonValuesMat3_j, res); // x-z
5378 epsilonValuesMat1_i.trace(res_trace_i);
5379 epsilonValuesMat3_j.trace(res_trace_j);
5380 v13 = v13 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5381
5382 epsilonValuesMat2_i.innerProduct(epsilonValuesMat1_j, res); // y-x
5383 epsilonValuesMat2_i.trace(res_trace_i);
5384 epsilonValuesMat1_j.trace(res_trace_j);
5385 v21 = v21 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5386
5387 epsilonValuesMat2_i.innerProduct(epsilonValuesMat2_j, res); // y-y
5388 epsilonValuesMat2_i.trace(res_trace_i);
5389 epsilonValuesMat2_j.trace(res_trace_j);
5390 v22 = v22 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5391
5392 epsilonValuesMat2_i.innerProduct(epsilonValuesMat3_j, res); // y-z
5393 epsilonValuesMat2_i.trace(res_trace_i);
5394 epsilonValuesMat3_j.trace(res_trace_j);
5395 v23 = v23 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5396
5397 epsilonValuesMat3_i.innerProduct(epsilonValuesMat1_j, res); // z-x
5398 epsilonValuesMat3_i.trace(res_trace_i);
5399 epsilonValuesMat1_j.trace(res_trace_j);
5400 v31 = v31 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5401
5402 epsilonValuesMat3_i.innerProduct(epsilonValuesMat2_j, res); // z-y
5403 epsilonValuesMat3_i.trace(res_trace_i);
5404 epsilonValuesMat2_j.trace(res_trace_j);
5405 v32 = v32 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5406
5407 epsilonValuesMat3_i.innerProduct(epsilonValuesMat3_j, res); // z-z
5408 epsilonValuesMat3_i.trace(res_trace_i);
5409 epsilonValuesMat3_j.trace(res_trace_j);
5410 v33 = v33 + weightsDPhi->at(k)*(2*mu*res + lambda*res_trace_j*res_trace_i);
5411
5412 }
5413 v11 = absDetB * v11;
5414 v12 = absDetB * v12;
5415 v13 = absDetB * v13;
5416 v21 = absDetB * v21;
5417 v22 = absDetB * v22;
5418 v23 = absDetB * v23;
5419 v31 = absDetB * v31;
5420 v32 = absDetB * v32;
5421 v33 = absDetB * v33;
5422
5423 value11[0] = v11;
5424 value12[0] = v12;
5425 value13[0] = v13;
5426 value21[0] = v21;
5427 value22[0] = v22;
5428 value23[0] = v23;
5429 value31[0] = v31;
5430 value32[0] = v32;
5431 value33[0] = v33;
5432
5433 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5434 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5435 indices[0] = glob_j;
5436 A->insertGlobalValues(glob_i, indices(), value11()); // x-x
5437 A->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
5438 A->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
5439 glob_j++;
5440 indices[0] = glob_j;
5441 A->insertGlobalValues(glob_i, indices(), value12()); // x-y
5442 A->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
5443 A->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
5444 glob_j++;
5445 indices[0] = glob_j;
5446 A->insertGlobalValues(glob_i, indices(), value13()); // x-z
5447 A->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
5448 A->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
5449 }
5450 }
5451 }
5452 if (callFillComplete)
5453 {
5454 A->fillComplete();
5455 }
5456 }
5457}
5458
5460template <class SC, class LO, class GO, class NO>
5462 std::string FEType,
5463 MatrixPtr_Type &A,
5464 MultiVectorPtr_Type w,
5465 bool callFillComplete)
5466{
5467
5468 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
5469 int FEloc = this->checkFE(dim,FEType);
5470
5471 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5472 ElementsPtr_Type elements = domain->getElementsC();
5473 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5474 MapConstPtr_Type map = domain->getMapRepeated();
5475
5476 vec3D_dbl_ptr_Type dPhi;
5477 vec2D_dbl_ptr_Type phi;
5478 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5479 vec2D_dbl_ptr_Type quadPts;
5480
5481 UN extraDeg = Helper::determineDegree( dim, FEType, Helper::Deriv1); // Fuer diskretes (\grad \cdot w) in den Gausspuntken
5482 UN deg = 2*Helper::determineDegree( dim, FEType, Helper::Deriv0) + extraDeg;
5483
5484 Helper::getDPhi(dPhi, weights, dim, FEType, deg);
5485 Helper::getPhi(phi, weights, dim, FEType, deg);
5486 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType);
5487
5488 // SC = double, GO = long, UN = int
5489 SC detB;
5490 SC absDetB;
5491 SmallMatrix<SC> B(dim);
5492 SmallMatrix<SC> Binv(dim);
5493 GO glob_i, glob_j;
5494
5495 // Der nichtlineare Teil als Array
5496 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
5497
5498 if (dim == 2)
5499 {
5500 double val;
5501 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
5502
5503 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
5504 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5505 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
5506
5507 for (int T = 0; T < elements->numberElements(); T++)
5508 {
5509 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5510 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5511 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5512
5513 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5514 detB = B.computeInverse(Binv);
5515 absDetB = std::fabs(detB);
5516
5517 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5518 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5519 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5520
5521 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 berechnen,
5522 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
5523 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5524 {
5525 w11[0][k] = 0.0;
5526 w22[0][k] = 0.0;
5527 for(int i = 0; i < dPhiTrans[0].size(); i++)
5528 {
5529 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5530 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5531 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
5532 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
5533
5534 // TEST
5535 // LO indexTest1 = dim * i + 0;
5536 // LO indexTest2 = dim * i + 1;
5537 // w11[0][k] += wTest[indexTest1] * dPhiTrans[k][i][0];
5538 // w22[0][k] += wTest[indexTest2] * dPhiTrans[k][i][1];
5539 }
5540 }
5541
5542 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5543 {
5544 divergenz[0][k] = w11[0][k] + w22[0][k];
5545 // if(T == 0)
5546 // {
5547 // std::cout << "k: " << k << " Divergenz: " << divergenz[0][k] << '\n';
5548 // }
5549 }
5550
5551
5552 for (int i = 0; i < dPhi->at(0).size(); i++)
5553 {
5554 Teuchos::Array<SC> value( 1, 0. );
5555 Teuchos::Array<GO> indices( 1, 0 );
5556
5557 for (int j = 0; j < dPhi->at(0).size(); j++)
5558 {
5559 val = 0.0;
5560 for (int k = 0; k < dPhi->size(); k++)
5561 {
5562 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
5563 }
5564 val = absDetB * val;
5565 value[0] = val;
5566
5567 // if(T == 0)
5568 // {
5569 // std::cout << "i: " << i << " j: " << j << " val: " << val << '\n';
5570 // }
5571
5572 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5573 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5574 indices[0] = glob_j;
5575
5576 A->insertGlobalValues(glob_i, indices(), value());
5577 glob_j++;
5578 indices[0] = glob_j;
5579 A->insertGlobalValues(glob_i+1, indices(), value());
5580 }
5581 }
5582 }
5583 if (callFillComplete)
5584 {
5585 A->fillComplete();
5586 }
5587 }
5588 else if(dim == 3)
5589 {
5590 double val;
5591
5592 // long long glob_i, glob_j;
5593 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
5594
5595 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.)); // diskretes w_11. Siehe unten.
5596 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5597 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
5598 vec2D_dbl_Type divergenz(1, vec_dbl_Type(weights->size(), -1.));
5599
5600 for (int T = 0; T < elements->numberElements(); T++)
5601 {
5602 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5603 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5604 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5605 p4 = pointsRep->at(elements->getElement(T).getNode(3));
5606
5607 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType);
5608 detB = B.computeInverse(Binv);
5609 absDetB = std::fabs(detB);
5610
5611 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5612 vec3D_dbl_Type dPhiTrans( dPhi->size(), vec2D_dbl_Type( dPhi->at(0).size(), vec_dbl_Type(dim,0.) ) );
5613 applyBTinv( dPhi, dPhiTrans, Binv ); //dPhiTrans berechnen
5614
5615 // Diskretes \div(w) = (\grad \cdot w) = w_11 + w_22 + w33 berechnen,
5616 // wobei w_ij = \frac{\partial w_i}{\partial x_j} ist.
5617 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5618 {
5619 w11[0][k] = 0.0;
5620 w22[0][k] = 0.0;
5621 w33[0][k] = 0.0;
5622 for(int i = 0; i < dPhiTrans[0].size(); i++)
5623 {
5624 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5625 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5626 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
5627 w11[0][k] += wArray[index1] * dPhiTrans[k][i][0];
5628 w22[0][k] += wArray[index2] * dPhiTrans[k][i][1];
5629 w33[0][k] += wArray[index3] * dPhiTrans[k][i][2];
5630 }
5631 }
5632
5633 for(int k = 0; k < dPhiTrans.size(); k++) // Quadraturpunkte
5634 {
5635 divergenz[0][k] = w11[0][k] + w22[0][k] + w33[0][k];
5636 }
5637
5638 for (int i = 0; i < dPhi->at(0).size(); i++)
5639 {
5640 Teuchos::Array<SC> value( 1, 0. );
5641 Teuchos::Array<GO> indices( 1, 0 );
5642
5643 for (int j = 0; j < dPhi->at(0).size(); j++)
5644 {
5645 val = 0.0;
5646 for (int k = 0; k < dPhi->size(); k++)
5647 {
5648 val = val + divergenz[0][k] * weights->at(k) * (*phi)[k][i] * (*phi)[k][j];
5649 }
5650 val = absDetB * val;
5651 value[0] = val;
5652
5653 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
5654 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
5655 indices[0] = glob_j;
5656 A->insertGlobalValues(glob_i, indices(), value());
5657 glob_j++;
5658 indices[0] = glob_j;
5659 A->insertGlobalValues(glob_i+1, indices(), value());
5660 glob_j++;
5661 indices[0] = glob_j;
5662 A->insertGlobalValues(glob_i+2, indices(), value());
5663
5664 }
5665 }
5666 }
5667 if (callFillComplete)
5668 {
5669 A->fillComplete();
5670 }
5671 }
5672}
5673
5674template <class SC, class LO, class GO, class NO>
5675void FE<SC,LO,GO,NO>::assemblyDummyCoupling(int dim,
5676 std::string FEType,
5677 MatrixPtr_Type &C,
5678 int FEloc, // 0 = Fluid, 2 = Struktur
5679 bool callFillComplete)
5680{
5681 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5682
5683 MapConstPtr_Type mapInterfaceVecField = domain->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
5684 MapConstPtr_Type mapGlobalInterfaceVecField = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
5685
5686 MapConstPtr_Type mapFieldPartial = domain->getGlobalInterfaceMapVecFieldPartial();
5687
5688 Teuchos::Array<SC> value( 1, 0. );
5689 value[0] = 1.0; // da Einheitsmatrix
5690 Teuchos::Array<GO> indices( 1, 0 );
5691
5692 GO dofGlobal, dofLocal;
5693
5694 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
5695 {
5696 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5697 if ( mapFieldPartial->getLocalElement( dofGlobal ) == Teuchos::OrdinalTraits<LO>::invalid() ) {
5698 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
5699 dofGlobal = mapInterfaceVecField->getGlobalElement( k );
5700 indices[0] = dofGlobal;
5701 C->insertGlobalValues(dofGlobal, indices(), value());
5702 }
5703 }
5704
5705 if (callFillComplete)
5706 C->fillComplete(mapInterfaceVecField, mapInterfaceVecField);
5707
5708}
5709
5710template <class SC, class LO, class GO, class NO>
5711void FE<SC,LO,GO,NO>::assemblyFSICoupling(int dim,
5712 std::string FEType,
5713 MatrixPtr_Type &C,
5714 MatrixPtr_Type &C_T,
5715 int FEloc1, // 0 = Fluid, 2 = Struktur
5716 int FEloc2, // 0 = Fluid, 2 = Struktur
5717 MapConstPtr_Type map1, // DomainMap: InterfaceMapVecFieldUnique = Spalten von C_T
5718 MapConstPtr_Type map2, // RangeMap: this->getDomain(0)->getMapVecFieldUnique() = Zeilen von C_T
5719 bool callFillComplete)
5720{
5721 // int FEloc = this->checkFE(dim,FEType);
5722
5723 DomainConstPtr_Type domain1 = domainVec_.at(FEloc1);
5724
5725 MapConstPtr_Type mapInterfaceVecField = domain1->getInterfaceMapVecFieldUnique(); // Interface-Map in der Interface-Nummerierung
5726
5727 MapConstPtr_Type mapGlobalInterfaceVecField;
5728 MapConstPtr_Type mapFieldPartial;
5729 if (FEloc1!=FEloc2){
5730 mapFieldPartial = domain1->getOtherGlobalInterfaceMapVecFieldPartial();
5731 mapGlobalInterfaceVecField = domain1->getOtherGlobalInterfaceMapVecFieldUnique();
5732 }
5733 else{
5734 mapFieldPartial = domain1->getGlobalInterfaceMapVecFieldPartial();
5735 mapGlobalInterfaceVecField = domain1->getGlobalInterfaceMapVecFieldUnique();
5736 }
5737
5738 Teuchos::Array<SC> value( 1, 0. );
5739 value[0] = 1.0; // da Einheitsmatrix
5740 Teuchos::Array<GO> indices( 1, 0 );
5741
5742 GO dofGlobal, dofLocal;
5743 if (mapFieldPartial.is_null()) {
5744 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++)
5745 {
5746 // Globale ID des Interface-Knotens bzgl. der Globalen oder Interface-Nummerierung
5747 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5748 dofLocal = mapInterfaceVecField->getGlobalElement(k);
5749
5750 indices[0] = dofLocal;
5751 C_T->insertGlobalValues(dofGlobal, indices(), value());
5752 indices[0] = dofGlobal;
5753 C->insertGlobalValues(dofLocal, indices(), value());
5754
5755 }
5756 }
5757 else{
5758 for(int k = 0; k < mapGlobalInterfaceVecField->getNodeNumElements(); k++) {
5759 dofGlobal = mapGlobalInterfaceVecField->getGlobalElement(k);
5760 if ( mapFieldPartial->getLocalElement( dofGlobal ) != Teuchos::OrdinalTraits<LO>::invalid() ) {
5761
5762 dofLocal = mapInterfaceVecField->getGlobalElement(k);
5763
5764 indices[0] = dofLocal;
5765 C_T->insertGlobalValues(dofGlobal, indices(), value());
5766 indices[0] = dofGlobal;
5767 C->insertGlobalValues(dofLocal, indices(), value());
5768 }
5769 }
5770 }
5771
5772 if (callFillComplete)
5773 {
5774 // Erstes Argument: Domain (=Spalten von C_T)
5775 // Zweites Arguement: Range (=Zeilen von C_T)
5776 C_T->fillComplete(map1, map2);
5777 C->fillComplete(map2, map1);
5778 }
5779}
5780
5781
5782template <class SC, class LO, class GO, class NO>
5783void FE<SC,LO,GO,NO>::assemblyGeometryCoupling(int dim,
5784 std::string FEType,
5785 MatrixPtr_Type &C,
5786 int FEloc, // 0 = Fluid, 2 = Struktur, 4 = 0 = Geometrie
5787 MapConstPtr_Type map1, // Fluid-Interface-Map
5788 MapConstPtr_Type map2, // DomainMap: this->getDomain(2)->getMapVecFieldUnique() = Spalten von C
5789 MapConstPtr_Type map3, // RangeMap: this->getDomain(4)->getMapVecFieldUnique() = Zeilen von C
5790 bool callFillComplete)
5791{
5792
5793 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5794
5795 MapConstPtr_Type mapInt = domain->getGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung
5796 MapConstPtr_Type mapOtherInt = domain->getOtherGlobalInterfaceMapVecFieldUnique(); // Interface-Map in der globalen Nummerierung von other. For FELoc=0 or =4, otherInterface has solid dofs
5797 MapConstPtr_Type mapPartInt = domain->getGlobalInterfaceMapVecFieldPartial();
5798 MapConstPtr_Type mapOtherPartInt = domain->getOtherGlobalInterfaceMapVecFieldPartial();
5799 Teuchos::Array<SC> value( 1, 0. );
5800 value[0] = 1.0; // da Einheitsmatrix
5801 Teuchos::Array<GO> indices( 1, 0 );
5802
5803 GO dofRow;
5804 if (mapPartInt.is_null()) {
5805 for(int k = 0; k < mapInt->getNodeNumElements(); k++){
5806 dofRow = mapInt->getGlobalElement(k);
5807 indices[0] = mapOtherInt->getGlobalElement(k);
5808 C->insertGlobalValues(dofRow, indices(), value());
5809 }
5810 }
5811 else{
5812 for(int k = 0; k < mapPartInt->getNodeNumElements(); k++){
5813 dofRow = mapPartInt->getGlobalElement(k);
5814 indices[0] = mapOtherPartInt->getGlobalElement(k);
5815 C->insertGlobalValues(dofRow, indices(), value());
5816 }
5817 }
5818 if (callFillComplete)
5819 {
5820 // (Domain, Range)
5821 C->fillComplete(map2, map3);
5822 }
5823}
5824
5825
5826template <class SC, class LO, class GO, class NO>
5827void FE<SC,LO,GO,NO>::assemblyShapeDerivativeVelocity(int dim,
5828 std::string FEType1, // P2
5829 std::string FEType2, // P1
5830 MatrixPtr_Type &D,
5831 int FEloc, // 0 = Fluid (Velocity)
5832 MultiVectorPtr_Type u, // Geschwindigkeit
5833 MultiVectorPtr_Type w, // Beschleunigung Gitter
5834 MultiVectorPtr_Type p, // Druck
5835 double dt, // Zeitschrittweite
5836 double rho, // Dichte vom Fluid
5837 double nu, // Viskositaet vom Fluid
5838 bool callFillComplete)
5839{
5840 // int FEloc = this->checkFE(dim,FEType1);
5841
5842 DomainConstPtr_Type domain = domainVec_.at(FEloc);
5843 ElementsPtr_Type elements = domain->getElementsC();
5844 vec2D_dbl_ptr_Type pointsRep = domain->getPointsRepeated();
5845 MapConstPtr_Type map = domain->getMapRepeated();
5846
5847 vec3D_dbl_ptr_Type dPhiU;
5848 vec2D_dbl_ptr_Type phiU;
5849 vec2D_dbl_ptr_Type phiP;
5850 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
5851 vec2D_dbl_ptr_Type quadPts;
5852
5853 // Hoechste Quadraturordnung angeben (= Zusaetzlicher Term wg. non-conservativ); bei P2/P1 hier Ordnung 6
5854 UN extraDeg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv1);
5855 UN deg = 2*Helper::determineDegree( dim, FEType1, Helper::Deriv0) + extraDeg;
5856
5857 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
5858 Helper::getPhi(phiU, weights, dim, FEType1, deg);
5859 Helper::getPhi(phiP, weights, dim, FEType2, deg);
5860 Helper::getQuadratureValues(dim, deg, quadPts, weights,FEType1);
5861
5862 // SC = double, GO = long, UN = int
5863 SC detB;
5864 SC absDetB;
5865 SmallMatrix<SC> B(dim);
5866 SmallMatrix<SC> Binv(dim);
5867 GO glob_i, glob_j;
5868
5869 // Der nichtlineare Teil als Array
5870 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
5871 Teuchos::ArrayRCP< const SC > wArray = w->getData(0);
5872 Teuchos::ArrayRCP< const SC > pArray = p->getData(0);
5873
5874 if (dim == 2)
5875 {
5876 double val11, val12, val21, val22;
5877 double valDK1_11, valDK1_12, valDK1_21, valDK1_22;
5878 double valDK2_11, valDK2_12, valDK2_21, valDK2_22;
5879 double valDN_11, valDN_12, valDN_21, valDN_22;
5880 double valDW_11, valDW_12, valDW_21, valDW_22;
5881 double valDP_11, valDP_12, valDP_21, valDP_22;
5882 double valDM_11, valDM_12, valDM_21, valDM_22;
5883 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
5884
5885 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
5886 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
5887 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
5888 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
5889 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
5890 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
5891 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
5892 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
5893 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
5894 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
5895 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
5896 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
5897 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
5898 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
5899 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
5900 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
5901 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
5902 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
5903 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
5904 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
5905
5906 for (int T = 0; T < elements->numberElements(); T++)
5907 {
5908 p1 = pointsRep->at(elements->getElement(T).getNode(0));
5909 p2 = pointsRep->at(elements->getElement(T).getNode(1));
5910 p3 = pointsRep->at(elements->getElement(T).getNode(2));
5911
5912 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
5913 detB = B.computeInverse(Binv);
5914 absDetB = std::fabs(detB);
5915
5916 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
5917 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
5918 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
5919
5920 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
5921 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
5922 {
5923 u1Loc[0][k] = 0.0;
5924 u2Loc[0][k] = 0.0;
5925 w1Loc[0][k] = 0.0;
5926 w2Loc[0][k] = 0.0;
5927 for(int i = 0; i < phiU->at(0).size(); i++)
5928 {
5929 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5930 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5931 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
5932 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
5933 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
5934 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
5935
5936 }
5937 }
5938
5939 // Diskreten Vektor p berechnen
5940 // Beachte: phiP->size() = phiU->size()
5941 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
5942 {
5943 pLoc[0][k] = 0.0;
5944 for(int i = 0; i < phiP->at(0).size(); i++)
5945 {
5946 // Die ersten Eintraege in der Elementliste sind P1
5947 // Alternativ elements2 holen
5948 LO index = elements->getElement(T).getNode(i) + 0;
5949 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
5950
5951 }
5952 }
5953
5954 // Diskrete Grad-Vektoren berechnen,
5955 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
5956 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5957 {
5958 u11[0][k] = 0.0;
5959 u12[0][k] = 0.0;
5960 u21[0][k] = 0.0;
5961 u22[0][k] = 0.0;
5962 w11[0][k] = 0.0;
5963 w12[0][k] = 0.0;
5964 w21[0][k] = 0.0;
5965 w22[0][k] = 0.0;
5966 for(int i = 0; i < dPhiTransU[0].size(); i++)
5967 {
5968 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
5969 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
5970 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
5971 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
5972 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
5973 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
5974 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
5975 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
5976 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
5977 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
5978
5979 }
5980 }
5981
5982 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
5983 // Beachte: phiP->size() = phiU->size()
5984 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
5985 {
5986 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
5987 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
5988 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
5989 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
5990 }
5991
5992
5993 for (int i = 0; i < dPhiU->at(0).size(); i++)
5994 {
5995 Teuchos::Array<SC> value11( 1, 0. ); // x-x
5996 Teuchos::Array<SC> value12( 1, 0. ); // x-y
5997 Teuchos::Array<SC> value21( 1, 0. ); // y-x
5998 Teuchos::Array<SC> value22( 1, 0. ); // y-y
5999 Teuchos::Array<GO> indices( 1, 0 );
6000
6001 for (int j = 0; j < dPhiU->at(0).size(); j++)
6002 {
6003 // DK1
6004 valDK1_11 = 0.0;
6005 valDK1_12 = 0.0;
6006 valDK1_21 = 0.0;
6007 valDK1_22 = 0.0;
6008
6009 // DK2
6010 valDK2_11 = 0.0;
6011 valDK2_12 = 0.0;
6012 valDK2_21 = 0.0;
6013 valDK2_22 = 0.0;
6014
6015 // DN
6016 valDN_11 = 0.0;
6017 valDN_12 = 0.0;
6018 valDN_21 = 0.0;
6019 valDN_22 = 0.0;
6020
6021 // DW
6022 valDW_11 = 0.0;
6023 valDW_12 = 0.0;
6024 valDW_21 = 0.0;
6025 valDW_22 = 0.0;
6026
6027 // DP
6028 valDP_11 = 0.0;
6029 valDP_12 = 0.0;
6030 valDP_21 = 0.0;
6031 valDP_22 = 0.0;
6032
6033 // DM
6034 valDM_11 = 0.0;
6035 valDM_12 = 0.0;
6036 valDM_21 = 0.0;
6037 valDM_22 = 0.0;
6038
6039 for (int k = 0; k < dPhiU->size(); k++)
6040 {
6041 // DK1
6042 valDK1_11 = valDK1_11 + weights->at(k) *
6043 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6044 u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6045 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6046 valDK1_12 = valDK1_12 + weights->at(k) *
6047 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6048 u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6049 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6050 valDK1_21 = valDK1_21 + weights->at(k) *
6051 ( u11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6052 u21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6053 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
6054 valDK1_22 = valDK1_22 + weights->at(k) *
6055 ( u12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6056 u22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6057 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] );
6058
6059 // DK2
6060 valDK2_11 = valDK2_11 + weights->at(k) *
6061 ( -sigma12[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6062 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6063 valDK2_12 = valDK2_12 + weights->at(k) *
6064 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6065 -sigma11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6066 valDK2_21 = valDK2_21 + weights->at(k) *
6067 ( -sigma22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6068 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6069 valDK2_22 = valDK2_22 + weights->at(k) *
6070 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6071 -sigma21[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] );
6072
6073 // DN
6074 valDN_11 = valDN_11 + weights->at(k) *
6075 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) +
6076 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
6077 valDN_12 = valDN_12 + weights->at(k) *
6078 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u11[0][k] * phiU->at(k).at(i) -
6079 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u12[0][k] * phiU->at(k).at(i) );
6080 valDN_21 = valDN_21 + weights->at(k) *
6081 ( -(u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) +
6082 (u2Loc[0][k] - w2Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
6083 valDN_22 = valDN_22 + weights->at(k) *
6084 ( (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][1] * u21[0][k] * phiU->at(k).at(i) -
6085 (u1Loc[0][k] - w1Loc[0][k]) * dPhiTransU[k][j][0] * u22[0][k] * phiU->at(k).at(i) );
6086
6087 // DW
6088 valDW_11 = valDW_11 + weights->at(k) *
6089 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6090 valDW_12 = valDW_12 + weights->at(k) *
6091 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6092 valDW_21 = valDW_21 + weights->at(k) *
6093 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6094 valDW_22 = valDW_22 + weights->at(k) *
6095 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6096
6097 // DP
6098 valDP_11 = valDP_11 + weights->at(k) *
6099 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
6100 valDP_12 = valDP_12 + weights->at(k) *
6101 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u1Loc[0][k] * phiU->at(k).at(i) );
6102 valDP_21 = valDP_21 + weights->at(k) *
6103 ( ( -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
6104 valDP_22 = valDP_22 + weights->at(k) *
6105 ( ( w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] ) * u2Loc[0][k] * phiU->at(k).at(i) );
6106
6107 // DM
6108 valDM_11 = valDM_11 + weights->at(k) *
6109 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
6110 valDM_12 = valDM_12 + weights->at(k) *
6111 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
6112 valDM_21 = valDM_21 + weights->at(k) *
6113 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
6114 valDM_22 = valDM_22 + weights->at(k) *
6115 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
6116 }
6117
6118 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;
6119 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;
6120 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;
6121 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;
6122
6123 val11 = absDetB * val11;
6124 val12 = absDetB * val12;
6125 val21 = absDetB * val21;
6126 val22 = absDetB * val22;
6127
6128 value11[0] = val11; // x-x
6129 value12[0] = val12; // x-y
6130 value21[0] = val21; // y-x
6131 value22[0] = val22; // y-y
6132
6133 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6134 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6135 indices[0] = glob_j;
6136
6137 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
6138 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6139 glob_j++;
6140 indices[0] = glob_j;
6141 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
6142 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6143 }
6144 }
6145 }
6146 if (callFillComplete)
6147 {
6148 D->fillComplete();
6149 }
6150 }
6151 else if(dim == 3)
6152 {
6153 double val11, val12, val13, val21, val22, val23, val31, val32, val33;
6154 double valDK1_11, valDK1_12, valDK1_13, valDK1_21, valDK1_22, valDK1_23, valDK1_31, valDK1_32, valDK1_33;
6155 double valDK2_11, valDK2_12, valDK2_13, valDK2_21, valDK2_22, valDK2_23, valDK2_31, valDK2_32, valDK2_33;
6156 double valDN_11, valDN_12, valDN_13, valDN_21, valDN_22, valDN_23, valDN_31, valDN_32, valDN_33;
6157 double valDW_11, valDW_12, valDW_13, valDW_21, valDW_22, valDW_23, valDW_31, valDW_32, valDW_33;
6158 double valDP_11, valDP_12, valDP_13, valDP_21, valDP_22, valDP_23, valDP_31, valDP_32, valDP_33;
6159 double valDM_11, valDM_12, valDM_13, valDM_21, valDM_22, valDM_23, valDM_31, valDM_32, valDM_33;
6160 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6161
6162 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6163 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6164 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6165 vec2D_dbl_Type u1Loc(1, vec_dbl_Type(weights->size(), -1.));
6166 vec2D_dbl_Type u2Loc(1, vec_dbl_Type(weights->size(), -1.));
6167 vec2D_dbl_Type u3Loc(1, vec_dbl_Type(weights->size(), -1.));
6168 vec2D_dbl_Type w1Loc(1, vec_dbl_Type(weights->size(), -1.));
6169 vec2D_dbl_Type w2Loc(1, vec_dbl_Type(weights->size(), -1.));
6170 vec2D_dbl_Type w3Loc(1, vec_dbl_Type(weights->size(), -1.));
6171 vec2D_dbl_Type pLoc(1, vec_dbl_Type(weights->size(), -1.));
6172 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6173 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6174 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
6175 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6176 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6177 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
6178 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
6179 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
6180 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
6181 vec2D_dbl_Type w11(1, vec_dbl_Type(weights->size(), -1.));
6182 vec2D_dbl_Type w12(1, vec_dbl_Type(weights->size(), -1.));
6183 vec2D_dbl_Type w13(1, vec_dbl_Type(weights->size(), -1.));
6184 vec2D_dbl_Type w21(1, vec_dbl_Type(weights->size(), -1.));
6185 vec2D_dbl_Type w22(1, vec_dbl_Type(weights->size(), -1.));
6186 vec2D_dbl_Type w23(1, vec_dbl_Type(weights->size(), -1.));
6187 vec2D_dbl_Type w31(1, vec_dbl_Type(weights->size(), -1.));
6188 vec2D_dbl_Type w32(1, vec_dbl_Type(weights->size(), -1.));
6189 vec2D_dbl_Type w33(1, vec_dbl_Type(weights->size(), -1.));
6190 vec2D_dbl_Type sigma11(1, vec_dbl_Type(weights->size(), -1.));
6191 vec2D_dbl_Type sigma12(1, vec_dbl_Type(weights->size(), -1.));
6192 vec2D_dbl_Type sigma13(1, vec_dbl_Type(weights->size(), -1.));
6193 vec2D_dbl_Type sigma21(1, vec_dbl_Type(weights->size(), -1.));
6194 vec2D_dbl_Type sigma22(1, vec_dbl_Type(weights->size(), -1.));
6195 vec2D_dbl_Type sigma23(1, vec_dbl_Type(weights->size(), -1.));
6196 vec2D_dbl_Type sigma31(1, vec_dbl_Type(weights->size(), -1.));
6197 vec2D_dbl_Type sigma32(1, vec_dbl_Type(weights->size(), -1.));
6198 vec2D_dbl_Type sigma33(1, vec_dbl_Type(weights->size(), -1.));
6199
6200 for (int T = 0; T < elements->numberElements(); T++)
6201 {
6202 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6203 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6204 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6205 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6206
6207 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6208 detB = B.computeInverse(Binv);
6209 absDetB = std::fabs(detB);
6210
6211 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6212 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6213 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6214
6215 // Diskrete Vektoren u1, u2, w1 und w2 berechnen
6216 for(int k = 0; k < phiU->size(); k++) // Quadraturpunkte
6217 {
6218 u1Loc[0][k] = 0.0;
6219 u2Loc[0][k] = 0.0;
6220 u3Loc[0][k] = 0.0;
6221 w1Loc[0][k] = 0.0;
6222 w2Loc[0][k] = 0.0;
6223 w3Loc[0][k] = 0.0;
6224 for(int i = 0; i < phiU->at(0).size(); i++)
6225 {
6226 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
6227 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
6228 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
6229 u1Loc[0][k] += uArray[index1] * phiU->at(k).at(i);
6230 u2Loc[0][k] += uArray[index2] * phiU->at(k).at(i);
6231 u3Loc[0][k] += uArray[index3] * phiU->at(k).at(i);
6232 w1Loc[0][k] += wArray[index1] * phiU->at(k).at(i);
6233 w2Loc[0][k] += wArray[index2] * phiU->at(k).at(i);
6234 w3Loc[0][k] += wArray[index3] * phiU->at(k).at(i);
6235 }
6236 }
6237
6238 // Diskreten Vektor p berechnen
6239 // Beachte: phiP->size() = phiU->size()
6240 for(int k = 0; k < phiP->size(); k++) // Quadraturpunkte
6241 {
6242 pLoc[0][k] = 0.0;
6243 for(int i = 0; i < phiP->at(0).size(); i++)
6244 {
6245 // Die ersten Eintraege in der Elementliste sind P1
6246 LO index = elements->getElement(T).getNode(i) + 0;
6247 pLoc[0][k] += pArray[index] * phiP->at(k).at(i);
6248 }
6249 }
6250
6251 // Diskrete Grad-Vektoren berechnen,
6252 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6253 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6254 {
6255 u11[0][k] = 0.0;
6256 u12[0][k] = 0.0;
6257 u13[0][k] = 0.0;
6258 u21[0][k] = 0.0;
6259 u22[0][k] = 0.0;
6260 u23[0][k] = 0.0;
6261 u31[0][k] = 0.0;
6262 u32[0][k] = 0.0;
6263 u33[0][k] = 0.0;
6264 w11[0][k] = 0.0;
6265 w12[0][k] = 0.0;
6266 w13[0][k] = 0.0;
6267 w21[0][k] = 0.0;
6268 w22[0][k] = 0.0;
6269 w23[0][k] = 0.0;
6270 w31[0][k] = 0.0;
6271 w32[0][k] = 0.0;
6272 w33[0][k] = 0.0;
6273 for(int i = 0; i < dPhiTransU[0].size(); i++)
6274 {
6275 LO index1 = dim * elements->getElement(T).getNode(i) + 0; // x
6276 LO index2 = dim * elements->getElement(T).getNode(i) + 1; // y
6277 LO index3 = dim * elements->getElement(T).getNode(i) + 2; // z
6278 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6279 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6280 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
6281 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6282 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6283 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
6284 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
6285 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
6286 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
6287 w11[0][k] += wArray[index1] * dPhiTransU[k][i][0];
6288 w12[0][k] += wArray[index1] * dPhiTransU[k][i][1];
6289 w13[0][k] += wArray[index1] * dPhiTransU[k][i][2];
6290 w21[0][k] += wArray[index2] * dPhiTransU[k][i][0];
6291 w22[0][k] += wArray[index2] * dPhiTransU[k][i][1];
6292 w23[0][k] += wArray[index2] * dPhiTransU[k][i][2];
6293 w31[0][k] += wArray[index3] * dPhiTransU[k][i][0];
6294 w32[0][k] += wArray[index3] * dPhiTransU[k][i][1];
6295 w33[0][k] += wArray[index3] * dPhiTransU[k][i][2];
6296 }
6297 }
6298
6299 // Diskretes \sigma = \rho * \nu * ( grad u + (grad u)^T ) - pI berechnen
6300 // Beachte: phiP->size() = phiU->size()
6301 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6302 {
6303 sigma11[0][k] = rho * nu * (u11[0][k] + u11[0][k]) - pLoc[0][k];
6304 sigma12[0][k] = rho * nu * (u12[0][k] + u21[0][k]);
6305 sigma13[0][k] = rho * nu * (u13[0][k] + u31[0][k]);
6306 sigma21[0][k] = rho * nu * (u21[0][k] + u12[0][k]);
6307 sigma22[0][k] = rho * nu * (u22[0][k] + u22[0][k]) - pLoc[0][k];
6308 sigma23[0][k] = rho * nu * (u23[0][k] + u32[0][k]);
6309 sigma31[0][k] = rho * nu * (u31[0][k] + u13[0][k]);
6310 sigma32[0][k] = rho * nu * (u32[0][k] + u23[0][k]);
6311 sigma33[0][k] = rho * nu * (u33[0][k] + u33[0][k]) - pLoc[0][k];
6312 }
6313
6314
6315 for (int i = 0; i < dPhiU->at(0).size(); i++)
6316 {
6317 Teuchos::Array<SC> value11( 1, 0. ); // x-x
6318 Teuchos::Array<SC> value12( 1, 0. ); // x-y
6319 Teuchos::Array<SC> value13( 1, 0. ); // x-z
6320 Teuchos::Array<SC> value21( 1, 0. ); // y-x
6321 Teuchos::Array<SC> value22( 1, 0. ); // y-y
6322 Teuchos::Array<SC> value23( 1, 0. ); // y-z
6323 Teuchos::Array<SC> value31( 1, 0. ); // z-x
6324 Teuchos::Array<SC> value32( 1, 0. ); // z-y
6325 Teuchos::Array<SC> value33( 1, 0. ); // z-z
6326 Teuchos::Array<GO> indices( 1, 0 );
6327
6328 for (int j = 0; j < dPhiU->at(0).size(); j++)
6329 {
6330 // DK1
6331 valDK1_11 = 0.0;
6332 valDK1_12 = 0.0;
6333 valDK1_13 = 0.0;
6334 valDK1_21 = 0.0;
6335 valDK1_22 = 0.0;
6336 valDK1_23 = 0.0;
6337 valDK1_31 = 0.0;
6338 valDK1_32 = 0.0;
6339 valDK1_33 = 0.0;
6340
6341 // DK2
6342 valDK2_11 = 0.0;
6343 valDK2_12 = 0.0;
6344 valDK2_13 = 0.0;
6345 valDK2_21 = 0.0;
6346 valDK2_22 = 0.0;
6347 valDK2_23 = 0.0;
6348 valDK2_31 = 0.0;
6349 valDK2_32 = 0.0;
6350 valDK2_33 = 0.0;
6351
6352 // DN
6353 valDN_11 = 0.0;
6354 valDN_12 = 0.0;
6355 valDN_13 = 0.0;
6356 valDN_21 = 0.0;
6357 valDN_22 = 0.0;
6358 valDN_23 = 0.0;
6359 valDN_31 = 0.0;
6360 valDN_32 = 0.0;
6361 valDN_33 = 0.0;
6362
6363 // DW
6364 valDW_11 = 0.0;
6365 valDW_12 = 0.0;
6366 valDW_13 = 0.0;
6367 valDW_21 = 0.0;
6368 valDW_22 = 0.0;
6369 valDW_23 = 0.0;
6370 valDW_31 = 0.0;
6371 valDW_32 = 0.0;
6372 valDW_33 = 0.0;
6373
6374 // DP
6375 valDP_11 = 0.0;
6376 valDP_12 = 0.0;
6377 valDP_13 = 0.0;
6378 valDP_21 = 0.0;
6379 valDP_22 = 0.0;
6380 valDP_23 = 0.0;
6381 valDP_31 = 0.0;
6382 valDP_32 = 0.0;
6383 valDP_33 = 0.0;
6384
6385 // DM
6386 valDM_11 = 0.0;
6387 valDM_12 = 0.0;
6388 valDM_13 = 0.0;
6389 valDM_21 = 0.0;
6390 valDM_22 = 0.0;
6391 valDM_23 = 0.0;
6392 valDM_31 = 0.0;
6393 valDM_32 = 0.0;
6394 valDM_33 = 0.0;
6395
6396 for (int k = 0; k < dPhiU->size(); k++)
6397 {
6398 // DK1
6399 valDK1_11 = valDK1_11 + weights->at(k) *
6400 ( 2 * u11[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6401 ( u11[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6402 ( u11[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6403 valDK1_12 = valDK1_12 + weights->at(k) *
6404 ( 2 * u12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6405 ( u12[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6406 ( u12[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6407 valDK1_13 = valDK1_13 + weights->at(k) *
6408 ( 2 * u13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][0] +
6409 ( u13[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][1] +
6410 ( u13[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) * dPhiTransU[k][i][2] );
6411 valDK1_21 = valDK1_21 + weights->at(k) *
6412 ( ( u21[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6413 2 * u21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6414 ( u21[0][k] * dPhiTransU[k][j][2] + u31[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6415 valDK1_22 = valDK1_22 + weights->at(k) *
6416 ( ( u22[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6417 2 * u22[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6418 ( u22[0][k] * dPhiTransU[k][j][2] + u32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6419 valDK1_23 = valDK1_23 + weights->at(k) *
6420 ( ( u23[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][0] +
6421 2 * u23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][1] +
6422 ( u23[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6423 valDK1_31 = valDK1_31 + weights->at(k) *
6424 ( ( u31[0][k] * dPhiTransU[k][j][0] + u11[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6425 ( u31[0][k] * dPhiTransU[k][j][1] + u21[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6426 2 * u31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6427 valDK1_32 = valDK1_32 + weights->at(k) *
6428 ( ( u32[0][k] * dPhiTransU[k][j][0] + u12[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6429 ( u32[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6430 2 * u32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6431 valDK1_33 = valDK1_33 + weights->at(k) *
6432 ( ( u33[0][k] * dPhiTransU[k][j][0] + u13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6433 ( u33[0][k] * dPhiTransU[k][j][1] + u23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] ) +
6434 2 * u33[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][2];
6435
6436 // DK2
6437 valDK2_11 = valDK2_11 + weights->at(k) *
6438 ( ( -sigma12[0][k] * dPhiTransU[k][j][1] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6439 sigma12[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6440 sigma13[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6441 valDK2_12 = valDK2_12 + weights->at(k) *
6442 ( sigma11[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6443 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma13[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6444 sigma13[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6445 valDK2_13 = valDK2_13 + weights->at(k) *
6446 ( sigma11[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6447 sigma12[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6448 ( -sigma11[0][k] * dPhiTransU[k][j][0] - sigma12[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6449 valDK2_21 = valDK2_21 + weights->at(k) *
6450 ( ( -sigma22[0][k] * dPhiTransU[k][j][1] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6451 sigma22[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6452 sigma23[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6453 valDK2_22 = valDK2_22 + weights->at(k) *
6454 ( sigma21[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6455 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma23[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6456 sigma23[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6457 valDK2_23 = valDK2_23 + weights->at(k) *
6458 ( sigma21[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6459 sigma22[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6460 ( -sigma21[0][k] * dPhiTransU[k][j][0] - sigma22[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6461 valDK2_31 = valDK2_31 + weights->at(k) *
6462 ( ( -sigma32[0][k] * dPhiTransU[k][j][1] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][0] +
6463 sigma32[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][1] +
6464 sigma33[0][k] * dPhiTransU[k][j][0] * dPhiTransU[k][i][2] );
6465 valDK2_32 = valDK2_32 + weights->at(k) *
6466 ( sigma31[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][0] +
6467 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma33[0][k] * dPhiTransU[k][j][2] ) * dPhiTransU[k][i][1] +
6468 sigma33[0][k] * dPhiTransU[k][j][1] * dPhiTransU[k][i][2] );
6469 valDK2_33 = valDK2_33 + weights->at(k) *
6470 ( sigma31[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][0] +
6471 sigma32[0][k] * dPhiTransU[k][j][2] * dPhiTransU[k][i][1] +
6472 ( -sigma31[0][k] * dPhiTransU[k][j][0] - sigma32[0][k] * dPhiTransU[k][j][1] ) * dPhiTransU[k][i][2] );
6473
6474 // DN
6475 double ZN_11; // Die Z_i fuer das DN wie in der Masterarbeit definiert
6476 double ZN_12;
6477 double ZN_13;
6478 double ZN_21;
6479 double ZN_22;
6480 double ZN_23;
6481 double ZN_31;
6482 double ZN_32;
6483 double ZN_33;
6484 ZN_11 = - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
6485 ZN_12 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][0];
6486 ZN_13 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][0];
6487 ZN_21 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][1];
6488 ZN_22 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][2];
6489 ZN_23 = ( u3Loc[0][k] - w3Loc[0][k] ) * dPhiTransU[k][j][1];
6490 ZN_31 = ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][2];
6491 ZN_32 = ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][2];
6492 ZN_33 = - ( u1Loc[0][k] - w1Loc[0][k] ) * dPhiTransU[k][j][0] - ( u2Loc[0][k] - w2Loc[0][k] ) * dPhiTransU[k][j][1];
6493
6494 valDN_11 = valDN_11 + weights->at(k) *
6495 ( ZN_11 * u11[0][k] * phiU->at(k).at(i) +
6496 ZN_12 * u12[0][k] * phiU->at(k).at(i) +
6497 ZN_13 * u13[0][k] * phiU->at(k).at(i) );
6498 valDN_12 = valDN_12 + weights->at(k) *
6499 ( ZN_21 * u11[0][k] * phiU->at(k).at(i) +
6500 ZN_22 * u12[0][k] * phiU->at(k).at(i) +
6501 ZN_23 * u13[0][k] * phiU->at(k).at(i) );
6502 valDN_13 = valDN_13 + weights->at(k) *
6503 ( ZN_31 * u11[0][k] * phiU->at(k).at(i) +
6504 ZN_32 * u12[0][k] * phiU->at(k).at(i) +
6505 ZN_33 * u13[0][k] * phiU->at(k).at(i) );
6506 valDN_21 = valDN_21 + weights->at(k) *
6507 ( ZN_11 * u21[0][k] * phiU->at(k).at(i) +
6508 ZN_12 * u22[0][k] * phiU->at(k).at(i) +
6509 ZN_13 * u23[0][k] * phiU->at(k).at(i) );
6510 valDN_22 = valDN_22 + weights->at(k) *
6511 ( ZN_21 * u21[0][k] * phiU->at(k).at(i) +
6512 ZN_22 * u22[0][k] * phiU->at(k).at(i) +
6513 ZN_23 * u23[0][k] * phiU->at(k).at(i) );
6514 valDN_23 = valDN_23 + weights->at(k) *
6515 ( ZN_31 * u21[0][k] * phiU->at(k).at(i) +
6516 ZN_32 * u22[0][k] * phiU->at(k).at(i) +
6517 ZN_33 * u23[0][k] * phiU->at(k).at(i) );
6518 valDN_31 = valDN_31 + weights->at(k) *
6519 ( ZN_11 * u31[0][k] * phiU->at(k).at(i) +
6520 ZN_12 * u32[0][k] * phiU->at(k).at(i) +
6521 ZN_13 * u33[0][k] * phiU->at(k).at(i) );
6522 valDN_32 = valDN_32 + weights->at(k) *
6523 ( ZN_21 * u31[0][k] * phiU->at(k).at(i) +
6524 ZN_22 * u32[0][k] * phiU->at(k).at(i) +
6525 ZN_23 * u33[0][k] * phiU->at(k).at(i) );
6526 valDN_33 = valDN_33 + weights->at(k) *
6527 ( ZN_31 * u31[0][k] * phiU->at(k).at(i) +
6528 ZN_32 * u32[0][k] * phiU->at(k).at(i) +
6529 ZN_33 * u33[0][k] * phiU->at(k).at(i) );
6530
6531 // DW
6532 valDW_11 = valDW_11 + weights->at(k) *
6533 ( u11[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6534 valDW_12 = valDW_12 + weights->at(k) *
6535 ( u12[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6536 valDW_13 = valDW_13 + weights->at(k) *
6537 ( u13[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6538 valDW_21 = valDW_21 + weights->at(k) *
6539 ( u21[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6540 valDW_22 = valDW_22 + weights->at(k) *
6541 ( u22[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6542 valDW_23 = valDW_23 + weights->at(k) *
6543 ( u23[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6544 valDW_31 = valDW_31 + weights->at(k) *
6545 ( u31[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6546 valDW_32 = valDW_32 + weights->at(k) *
6547 ( u32[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6548 valDW_33 = valDW_33 + weights->at(k) *
6549 ( u33[0][k] * phiU->at(k).at(j) * phiU->at(k).at(i) );
6550
6551 // DP
6552 double ZP_1; // Die Z_i fuer das DP wie in der Masterarbeit definiert
6553 double ZP_2;
6554 double ZP_3;
6555 ZP_1 = -w21[0][k] * dPhiTransU[k][j][1] + w22[0][k] * dPhiTransU[k][j][0] -
6556 w31[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][0];
6557 ZP_2 = w11[0][k] * dPhiTransU[k][j][1] - w12[0][k] * dPhiTransU[k][j][0] -
6558 w32[0][k] * dPhiTransU[k][j][2] + w33[0][k] * dPhiTransU[k][j][1];
6559 ZP_3 = w11[0][k] * dPhiTransU[k][j][2] - w13[0][k] * dPhiTransU[k][j][0] +
6560 w22[0][k] * dPhiTransU[k][j][2] - w23[0][k] * dPhiTransU[k][j][1];
6561
6562 valDP_11 = valDP_11 + weights->at(k) *
6563 ( ZP_1 * u1Loc[0][k] * phiU->at(k).at(i) );
6564 valDP_12 = valDP_12 + weights->at(k) *
6565 ( ZP_2 * u1Loc[0][k] * phiU->at(k).at(i) );
6566 valDP_13 = valDP_13 + weights->at(k) *
6567 ( ZP_3 * u1Loc[0][k] * phiU->at(k).at(i) );
6568 valDP_21 = valDP_21 + weights->at(k) *
6569 ( ZP_1 * u2Loc[0][k] * phiU->at(k).at(i) );
6570 valDP_22 = valDP_22 + weights->at(k) *
6571 ( ZP_2 * u2Loc[0][k] * phiU->at(k).at(i) );
6572 valDP_23 = valDP_23 + weights->at(k) *
6573 ( ZP_3 * u2Loc[0][k] * phiU->at(k).at(i) );
6574 valDP_31 = valDP_31 + weights->at(k) *
6575 ( ZP_1 * u3Loc[0][k] * phiU->at(k).at(i) );
6576 valDP_32 = valDP_32 + weights->at(k) *
6577 ( ZP_2 * u3Loc[0][k] * phiU->at(k).at(i) );
6578 valDP_33 = valDP_33 + weights->at(k) *
6579 ( ZP_3 * u3Loc[0][k] * phiU->at(k).at(i) );
6580
6581 // DM
6582 valDM_11 = valDM_11 + weights->at(k) *
6583 ( dPhiTransU[k][j][0] * u1Loc[0][k] * phiU->at(k).at(i) );
6584 valDM_12 = valDM_12 + weights->at(k) *
6585 ( dPhiTransU[k][j][1] * u1Loc[0][k] * phiU->at(k).at(i) );
6586 valDM_13 = valDM_13 + weights->at(k) *
6587 ( dPhiTransU[k][j][2] * u1Loc[0][k] * phiU->at(k).at(i) );
6588 valDM_21 = valDM_21 + weights->at(k) *
6589 ( dPhiTransU[k][j][0] * u2Loc[0][k] * phiU->at(k).at(i) );
6590 valDM_22 = valDM_22 + weights->at(k) *
6591 ( dPhiTransU[k][j][1] * u2Loc[0][k] * phiU->at(k).at(i) );
6592 valDM_23 = valDM_23 + weights->at(k) *
6593 ( dPhiTransU[k][j][2] * u2Loc[0][k] * phiU->at(k).at(i) );
6594 valDM_31 = valDM_31 + weights->at(k) *
6595 ( dPhiTransU[k][j][0] * u3Loc[0][k] * phiU->at(k).at(i) );
6596 valDM_32 = valDM_32 + weights->at(k) *
6597 ( dPhiTransU[k][j][1] * u3Loc[0][k] * phiU->at(k).at(i) );
6598 valDM_33 = valDM_33 + weights->at(k) *
6599 ( dPhiTransU[k][j][2] * u3Loc[0][k] * phiU->at(k).at(i) );
6600 }
6601
6602 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;
6603 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;
6604 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;
6605 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;
6606 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;
6607 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;
6608 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;
6609 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;
6610 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;
6611
6612 val11 = absDetB * val11;
6613 val12 = absDetB * val12;
6614 val13 = absDetB * val13;
6615 val21 = absDetB * val21;
6616 val22 = absDetB * val22;
6617 val23 = absDetB * val23;
6618 val31 = absDetB * val31;
6619 val32 = absDetB * val32;
6620 val33 = absDetB * val33;
6621
6622 value11[0] = val11; // x-x
6623 value12[0] = val12; // x-y
6624 value13[0] = val13; // x-z
6625 value21[0] = val21; // y-x
6626 value22[0] = val22; // y-y
6627 value23[0] = val23; // y-z
6628 value31[0] = val31; // z-x
6629 value32[0] = val32; // z-y
6630 value33[0] = val33; // z-z
6631
6632
6633 glob_j = dim * map->getGlobalElement(elements->getElement(T).getNode(j));
6634 glob_i = dim * map->getGlobalElement(elements->getElement(T).getNode(i));
6635 indices[0] = glob_j;
6636
6637 D->insertGlobalValues(glob_i, indices(), value11()); // x-x
6638 D->insertGlobalValues(glob_i+1, indices(), value21()); // y-x
6639 D->insertGlobalValues(glob_i+2, indices(), value31()); // z-x
6640 glob_j++;
6641 indices[0] = glob_j;
6642 D->insertGlobalValues(glob_i, indices(), value12()); // x-y
6643 D->insertGlobalValues(glob_i+1, indices(), value22()); // y-y
6644 D->insertGlobalValues(glob_i+2, indices(), value32()); // z-y
6645 glob_j++;
6646 indices[0] = glob_j;
6647 D->insertGlobalValues(glob_i, indices(), value13()); // x-z
6648 D->insertGlobalValues(glob_i+1, indices(), value23()); // y-z
6649 D->insertGlobalValues(glob_i+2, indices(), value33()); // z-z
6650 }
6651 }
6652 }
6653 if (callFillComplete)
6654 {
6655 D->fillComplete();
6656 }
6657 }
6658
6659}
6660
6661
6662template <class SC, class LO, class GO, class NO>
6663void FE<SC,LO,GO,NO>::assemblyShapeDerivativeDivergence(int dim,
6664 std::string FEType1,
6665 std::string FEType2,
6666 MatrixPtr_Type &DB,
6667 int FEloc1, // 1 = Fluid-Pressure
6668 int FEloc2, // 0 = Fluid-Velocity
6669 MapConstPtr_Type map1_unique, // Pressure-Map
6670 MapConstPtr_Type map2_unique, // Velocity-Map unique als VecField
6671 MultiVectorPtr_Type u, // Geschwindigkeit
6672 bool callFillComplete)
6673{
6674 DomainConstPtr_Type domain1 = domainVec_.at(FEloc1);
6675 ElementsPtr_Type elements = domain1->getElementsC();
6676 vec2D_dbl_ptr_Type pointsRep = domain1->getPointsRepeated();
6677 MapConstPtr_Type map1_rep = domain1->getMapRepeated();
6678
6679 // Fuer die Fluid-Velocity-Map
6680 DomainConstPtr_Type domain2 = domainVec_.at(FEloc2);
6681 MapConstPtr_Type map2_rep = domain2->getMapRepeated();
6682 ElementsPtr_Type elements2 = domain2->getElementsC();
6683
6684 vec3D_dbl_ptr_Type dPhiU;
6685 vec2D_dbl_ptr_Type phiU;
6686 vec2D_dbl_ptr_Type phiP;
6687 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
6688 vec2D_dbl_ptr_Type quadPts;
6689
6690 UN extraDeg = Helper::determineDegree( dim, FEType1, Helper::Deriv1);
6691 UN deg = Helper::determineDegree( dim, FEType1, Helper::Deriv0) + 2*extraDeg;
6692
6693
6694 Helper::getDPhi(dPhiU, weights, dim, FEType1, deg);
6695 Helper::getPhi(phiU, weights, dim, FEType1, deg);
6696 Helper::getPhi(phiP, weights, dim, FEType2, deg);
6697 Helper::getQuadratureValues(dim, deg, quadPts, weights, FEType1);
6698
6699 // SC = double, GO = long, UN = int
6700 SC detB;
6701 SC absDetB;
6702 SmallMatrix<SC> B(dim);
6703 SmallMatrix<SC> Binv(dim);
6704 GO glob_i, glob_j;
6705
6706 // Der nichtlineare Teil als Array
6707 Teuchos::ArrayRCP< const SC > uArray = u->getData(0);
6708
6709 if (dim == 2)
6710 {
6711 double val1, val2;
6712 double valDB_1, valDB_2;
6713 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0);
6714
6715 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6716 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6717 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6718 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6719 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6720 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6721 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6722
6723 for (int T = 0; T < elements->numberElements(); T++)
6724 {
6725 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6726 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6727 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6728
6729 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6730 detB = B.computeInverse(Binv);
6731 absDetB = std::fabs(detB);
6732
6733 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6734 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6735 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6736
6737 // Diskrete Grad-Vektoren berechnen,
6738 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6739 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6740 {
6741 u11[0][k] = 0.0;
6742 u12[0][k] = 0.0;
6743 u21[0][k] = 0.0;
6744 u22[0][k] = 0.0;
6745 for(int i = 0; i < dPhiTransU[0].size(); i++)
6746 {
6747 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
6748 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
6749 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6750 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6751 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6752 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6753
6754 }
6755 }
6756
6757 for (int i = 0; i < phiP->at(0).size(); i++)
6758 {
6759 Teuchos::Array<SC> value1( 1, 0. ); // p-x
6760 Teuchos::Array<SC> value2( 1, 0. ); // p-y
6761 Teuchos::Array<GO> indices( 1, 0 );
6762
6763 for (int j = 0; j < dPhiU->at(0).size(); j++)
6764 {
6765 valDB_1 = 0.0;
6766 valDB_2 = 0.0;
6767
6768 for (int k = 0; k < dPhiU->size(); k++)
6769 {
6770 // DB
6771 valDB_1 = valDB_1 + weights->at(k) *
6772 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] ) );
6773 valDB_2 = valDB_2 + weights->at(k) *
6774 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] ) );
6775 }
6776
6777 val1 = valDB_1;
6778 val2 = valDB_2;
6779
6780 val1 = absDetB * val1;
6781 val2 = absDetB * val2;
6782
6783 value1[0] = val1; // p-x
6784 value2[0] = val2; // p-y
6785
6786 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
6787 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
6788 indices[0] = glob_j;
6789
6790 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
6791 glob_j++;
6792 indices[0] = glob_j;
6793 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
6794 }
6795 }
6796 }
6797 if (callFillComplete)
6798 {
6799 DB->fillComplete(map2_unique, map1_unique);
6800 }
6801 }
6802 else if(dim == 3)
6803 {
6804 double val1, val2, val3;
6805 double valDB_1, valDB_2, valDB_3;
6806 vec_dbl_Type p1(3,0.0), p2(3,0.0), p3(3,0.0), p4(3,0.0);
6807
6808 // Alle diskreten Vektoren aufstellen, dabei bezeichnet Xij = X_ij,
6809 // also i-te Komponenten von X nach der j-ten Variablen abgeleitet.
6810 // Der Gradient ist bei mir wie folgt definiert: \grad(u) = [u11, u12; u21 u22] = [grad(u_1)^T; grad(u_2)^T]
6811 vec2D_dbl_Type u11(1, vec_dbl_Type(weights->size(), -1.));
6812 vec2D_dbl_Type u12(1, vec_dbl_Type(weights->size(), -1.));
6813 vec2D_dbl_Type u13(1, vec_dbl_Type(weights->size(), -1.));
6814 vec2D_dbl_Type u21(1, vec_dbl_Type(weights->size(), -1.));
6815 vec2D_dbl_Type u22(1, vec_dbl_Type(weights->size(), -1.));
6816 vec2D_dbl_Type u23(1, vec_dbl_Type(weights->size(), -1.));
6817 vec2D_dbl_Type u31(1, vec_dbl_Type(weights->size(), -1.));
6818 vec2D_dbl_Type u32(1, vec_dbl_Type(weights->size(), -1.));
6819 vec2D_dbl_Type u33(1, vec_dbl_Type(weights->size(), -1.));
6820
6821 for (int T = 0; T < elements->numberElements(); T++)
6822 {
6823 p1 = pointsRep->at(elements->getElement(T).getNode(0));
6824 p2 = pointsRep->at(elements->getElement(T).getNode(1));
6825 p3 = pointsRep->at(elements->getElement(T).getNode(2));
6826 p4 = pointsRep->at(elements->getElement(T).getNode(3));
6827
6828 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B,FEType1);
6829 detB = B.computeInverse(Binv);
6830 absDetB = std::fabs(detB);
6831
6832 // dPhiTrans sind die transformierten Basifunktionen, also \grad_phi * B^(-T)
6833 vec3D_dbl_Type dPhiTransU( dPhiU->size(), vec2D_dbl_Type( dPhiU->at(0).size(), vec_dbl_Type(dim,0.) ) );
6834 applyBTinv( dPhiU, dPhiTransU, Binv ); //dPhiTrans berechnen
6835
6836 // Diskrete Grad-Vektoren berechnen,
6837 // wobei z.B. w_ij = \frac{\partial w_i}{\partial x_j} ist.
6838 for(int k = 0; k < dPhiTransU.size(); k++) // Quadraturpunkte
6839 {
6840 u11[0][k] = 0.0;
6841 u12[0][k] = 0.0;
6842 u13[0][k] = 0.0;
6843 u21[0][k] = 0.0;
6844 u22[0][k] = 0.0;
6845 u23[0][k] = 0.0;
6846 u31[0][k] = 0.0;
6847 u32[0][k] = 0.0;
6848 u33[0][k] = 0.0;
6849
6850 for(int i = 0; i < dPhiTransU[0].size(); i++)
6851 {
6852 LO index1 = dim * elements2->getElement(T).getNode(i) + 0; // x
6853 LO index2 = dim * elements2->getElement(T).getNode(i) + 1; // y
6854 LO index3 = dim * elements2->getElement(T).getNode(i) + 2; // z
6855 u11[0][k] += uArray[index1] * dPhiTransU[k][i][0];
6856 u12[0][k] += uArray[index1] * dPhiTransU[k][i][1];
6857 u13[0][k] += uArray[index1] * dPhiTransU[k][i][2];
6858 u21[0][k] += uArray[index2] * dPhiTransU[k][i][0];
6859 u22[0][k] += uArray[index2] * dPhiTransU[k][i][1];
6860 u23[0][k] += uArray[index2] * dPhiTransU[k][i][2];
6861 u31[0][k] += uArray[index3] * dPhiTransU[k][i][0];
6862 u32[0][k] += uArray[index3] * dPhiTransU[k][i][1];
6863 u33[0][k] += uArray[index3] * dPhiTransU[k][i][2];
6864 }
6865 }
6866
6867 for (int i = 0; i < phiP->at(0).size(); i++)
6868 {
6869 Teuchos::Array<SC> value1( 1, 0. ); // p-x
6870 Teuchos::Array<SC> value2( 1, 0. ); // p-y
6871 Teuchos::Array<SC> value3( 1, 0. ); // p-z
6872 Teuchos::Array<GO> indices( 1, 0 );
6873
6874 for (int j = 0; j < dPhiU->at(0).size(); j++)
6875 {
6876 valDB_1 = 0.0;
6877 valDB_2 = 0.0;
6878 valDB_3 = 0.0;
6879
6880 for (int k = 0; k < dPhiU->size(); k++)
6881 {
6882 // DB
6883 valDB_1 = valDB_1 + weights->at(k) *
6884 ( phiP->at(k).at(i) * ( -u21[0][k] * dPhiTransU[k][j][1] + u22[0][k] * dPhiTransU[k][j][0] -
6885 u31[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][0] ) );
6886 valDB_2 = valDB_2 + weights->at(k) *
6887 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][1] - u12[0][k] * dPhiTransU[k][j][0] -
6888 u32[0][k] * dPhiTransU[k][j][2] + u33[0][k] * dPhiTransU[k][j][1] ) );
6889 valDB_3 = valDB_3 + weights->at(k) *
6890 ( phiP->at(k).at(i) * ( u11[0][k] * dPhiTransU[k][j][2] - u13[0][k] * dPhiTransU[k][j][0] +
6891 u22[0][k] * dPhiTransU[k][j][2] - u23[0][k] * dPhiTransU[k][j][1] ) );
6892 }
6893
6894 val1 = valDB_1;
6895 val2 = valDB_2;
6896 val3 = valDB_3;
6897
6898 val1 = absDetB * val1;
6899 val2 = absDetB * val2;
6900 val3 = absDetB * val3;
6901
6902 value1[0] = val1; // p-x
6903 value2[0] = val2; // p-y
6904 value3[0] = val3; // p-z
6905
6906 glob_j = dim * map2_rep->getGlobalElement(elements2->getElement(T).getNode(j));
6907 glob_i = map1_rep->getGlobalElement(elements->getElement(T).getNode(i));
6908 indices[0] = glob_j;
6909
6910 DB->insertGlobalValues(glob_i, indices(), value1()); // p-x
6911 glob_j++;
6912 indices[0] = glob_j;
6913 DB->insertGlobalValues(glob_i, indices(), value2()); // p-y
6914 glob_j++;
6915 indices[0] = glob_j;
6916 DB->insertGlobalValues(glob_i, indices(), value3()); // p-z
6917 }
6918 }
6919 }
6920 if (callFillComplete)
6921 {
6922 DB->fillComplete(map2_unique, map1_unique);
6923 }
6924 }
6925
6926}
6927
6928template <class SC, class LO, class GO, class NO>
6929void FE<SC,LO,GO,NO>::assemblySurfaceIntegralExternal(int dim,
6930 std::string FEType,
6931 MultiVectorPtr_Type f,
6932 MultiVectorPtr_Type d_rep,
6933 std::vector<SC>& funcParameter,
6934 RhsFunc_Type func,
6935 ParameterListPtr_Type params,
6936 int FEloc) {
6937
6938 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
6939
6940 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
6941
6942 SC elScaling;
6943 SmallMatrix<SC> B(dim);
6944 vec_dbl_Type b(dim);
6945 f->putScalar(0.);
6946 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
6947
6948 int flagSurface = params->sublist("Parameter Solid").get("Flag Surface",5);
6949
6950 std::vector<double> valueFunc(dim);
6951
6952 SC* paramsFunc = &(funcParameter[0]);
6953
6954 // The second last entry is a placeholder for the surface element flag. It will be set below
6955 for (UN T=0; T<elements->numberElements(); T++) {
6956 FiniteElement fe = elements->getElement( T );
6957 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
6958 for (int surface=0; surface<fe.numSubElements(); surface++) {
6959 FiniteElement feSub = subEl->getElement( surface );
6960 if(subEl->getDimension() == dim-1 ){
6961
6962 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
6963
6964
6965 vec_dbl_Type solution_d = getSolution(nodeList, d_rep,dim);
6966 vec2D_dbl_Type nodes;
6967 nodes = getCoordinates(nodeList, pointsRep);
6968
6969
6970 double positions[18];
6971 int count =0;
6972 for(int i=0;i<6;i++)
6973 for(int j=0;j<3;j++){
6974 positions[count] = nodes[i][j];
6975 count++;
6976
6977 }
6978
6979
6980 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
6981 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
6982 func( &p1[0], &valueFunc[0], paramsFunc);
6983
6984 if(valueFunc[0] != 0.){
6985
6986 double *residuumVector;
6987 #ifdef FEDD_HAVE_ACEGENINTERFACE
6988
6989 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1., 35, &positions[0], &solution_d[0]);
6990 pt.computeTangentResidual();
6991 residuumVector = pt.getResiduum();
6992 #endif
6993
6994 for(int i=0; i< nodeList.size() ; i++){
6995 for(int d=0; d<dim; d++)
6996 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
6997 }
6998
6999 // free(residuumVector);
7000 }
7001
7002 }
7003 }
7004 }
7005 //f->scale(-1.);
7006
7007}
7008
7011
7012template <class SC, class LO, class GO, class NO>
7014 std::string FEType,
7015 MultiVectorPtr_Type f,
7016 MultiVectorPtr_Type d_rep,
7017 MatrixPtr_Type &Kext,
7018 std::vector<SC>& funcParameter,
7019 RhsFunc_Type func,
7020 ParameterListPtr_Type params,
7021 int FEloc) {
7022
7023 // degree of function funcParameter[0]
7024
7025 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7026
7027 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7028
7029 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7030 SC elScaling;
7031 SmallMatrix<SC> B(dim);
7032 vec_dbl_Type b(dim);
7033 f->putScalar(0.);
7034 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
7035
7036 std::vector<double> valueFunc(dim);
7037
7038 SC* paramsFunc = &(funcParameter[0]);
7039
7040 // The second last entry is a placeholder for the surface element flag. It will be set below
7041 for (UN T=0; T<elements->numberElements(); T++) {
7042 FiniteElement fe = elements->getElement( T );
7043 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
7044 for (int surface=0; surface<fe.numSubElements(); surface++) {
7045 FiniteElement feSub = subEl->getElement( surface );
7046 if(subEl->getDimension() == dim-1 ){
7047 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
7048
7049 vec_dbl_Type solution_d = getSolution(nodeList, d_rep,dim);
7050 vec2D_dbl_Type nodes;
7051 nodes = getCoordinates(nodeList, pointsRep);
7052
7053
7054 double positions[18];
7055 int count =0;
7056 for(int i=0;i<6;i++){
7057 for(int j=0;j<3;j++){
7058 positions[count] = nodes[i][j];
7059 count++;
7060
7061 }
7062 }
7063
7064 vec_dbl_Type p1 = {0.,0.,0.}; // Dummy vector
7065 paramsFunc[ funcParameter.size() - 1 ] = feSub.getFlag();
7066 func( &p1[0], &valueFunc[0], paramsFunc);
7067
7068 if(valueFunc[0] != 0.){
7069
7070 double *residuumVector;
7071 double **stiffMat;
7072
7073 #ifdef FEDD_HAVE_ACEGENINTERFACE
7074 AceGenInterface::PressureTriangle3D6 pt(valueFunc[0], 1.0, 35, &positions[0], &solution_d[0]);
7075 pt.computeTangentResidual();
7076
7077 residuumVector = pt.getResiduum();
7078 stiffMat = pt.getStiffnessMatrix();
7079 #endif
7080
7081
7082
7083 int dofs1 = dim;
7084 int numNodes1 =nodeList.size();
7085
7086 SmallMatrix_Type elementMatrixPrint(18,0.);
7087 for(int i=0; i< 18 ; i++){
7088 for(int j=0; j< 18; j++){
7089 if(std::fabs(stiffMat[i][j]) >1e-13)
7090 elementMatrixPrint[i][j] = stiffMat[i][j];
7091
7092 }
7093 }
7094
7095 SmallMatrix_Type elementMatrixWrite(18,0.);
7096
7097 SmallMatrix_Type elementMatrixIDsRow(18,0.);
7098 SmallMatrix_Type elementMatrixIDsCol(18,0.);
7099
7100
7101 for (UN i=0; i < numNodes1 ; i++) {
7102 for(int di=0; di<dim; di++){
7103 Teuchos::Array<SC> value1( numNodes1*dim, 0. );
7104 Teuchos::Array<GO> columnIndices1( numNodes1*dim, 0 );
7105 GO row =GO (dim* map->getGlobalElement( nodeList[i] )+di);
7106 LO rowLO = dim*i+di;
7107 // Zeilenweise werden die Einträge global assembliert
7108 for (UN j=0; j <numNodes1; j++){
7109 for(int d=0; d<dim; d++){
7110 columnIndices1[dim*j+d] = GO ( dim * map->getGlobalElement( nodeList[j] ) + d );
7111 value1[dim*j+d] = stiffMat[rowLO][dim*j+d];
7112 }
7113 }
7114 Kext->insertGlobalValues( row, columnIndices1(), value1() ); // Automatically adds entries if a value already exists
7115 }
7116 }
7117
7118
7119
7120 for(int i=0; i< nodeList.size() ; i++){
7121 for(int d=0; d<dim; d++){
7122 valuesF[nodeList[i]*dim+d] += residuumVector[i*dim+d];
7123 }
7124 }
7125
7126
7127 }
7128
7129
7130 }
7131 }
7132 }
7133 //f->scale(-1.);
7134 Kext->fillComplete(domainVec_.at(FEloc)->getMapVecFieldUnique(),domainVec_.at(FEloc)->getMapVecFieldUnique());
7135 // Kext->writeMM("K_ext1");
7136}
7137
7139template <class SC, class LO, class GO, class NO>
7140void FE<SC,LO,GO,NO>::computeSurfaceNormal(int dim,
7141 vec2D_dbl_ptr_Type pointsRep,
7142 vec_int_Type nodeList,
7143 vec_dbl_Type &v_E,
7144 double &norm_v_E)
7145{
7146
7147 vec_dbl_Type p1(dim),p2(dim);
7148
7149 if(dim==2){
7150 v_E[0] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
7151 v_E[1] = -(pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0));
7152 norm_v_E = std::sqrt(std::pow(v_E[0],2)+std::pow(v_E[1],2));
7153
7154 }
7155 else if(dim==3){
7156
7157 p1[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[1]).at(0);
7158 p1[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[1]).at(1);
7159 p1[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[1]).at(2);
7160
7161 p2[0] = pointsRep->at(nodeList[0]).at(0) - pointsRep->at(nodeList[2]).at(0);
7162 p2[1] = pointsRep->at(nodeList[0]).at(1) - pointsRep->at(nodeList[2]).at(1);
7163 p2[2] = pointsRep->at(nodeList[0]).at(2) - pointsRep->at(nodeList[2]).at(2);
7164
7165 v_E[0] = p1[1]*p2[2] - p1[2]*p2[1];
7166 v_E[1] = p1[2]*p2[0] - p1[0]*p2[2];
7167 v_E[2] = p1[0]*p2[1] - p1[1]*p2[0];
7168
7169 norm_v_E = std::sqrt(std::pow(v_E[0],2)+std::pow(v_E[1],2)+std::pow(v_E[2],2));
7170
7171 }
7172
7173}
7174
7175template <class SC, class LO, class GO, class NO>
7176void FE<SC,LO,GO,NO>::assemblySurfaceIntegral(int dim,
7177 std::string FEType,
7178 MultiVectorPtr_Type f,
7179 std::string fieldType,
7180 RhsFunc_Type func,
7181 std::vector<SC>& funcParameter) {
7182
7183 // degree of function funcParameter[0]
7184 //TEUCHOS_TEST_FOR_EXCEPTION( funcParameter[funcParameter.size()-1] > 0., std::logic_error, "We only support constant functions for now.");
7185 UN FEloc = checkFE(dim,FEType);
7186
7187 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7188
7189 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7190
7191 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7192 vec2D_dbl_ptr_Type phi;
7193 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7194
7195 UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // Degree from function set/determined externally
7196 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
7197
7198 Helper::getPhi(phi, weights, dim-1, FEType, deg);
7199
7200 vec2D_dbl_ptr_Type quadPoints;
7201 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7202 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
7203 w.reset();
7204
7205 SC elScaling;
7206 SmallMatrix<SC> B(dim);
7207 vec_dbl_Type b(dim);
7208 f->putScalar(0.);
7209 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
7210 int parameters;
7211
7212
7213 std::vector<double> valueFunc(dim);
7214 // The second last entry is a placeholder for the surface element flag. It will be set below
7215 SC* params = &(funcParameter[0]);
7216 for (UN T=0; T<elements->numberElements(); T++) {
7217 FiniteElement fe = elements->getElement( T );
7218 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
7219 for (int surface=0; surface<fe.numSubElements(); surface++) {
7220 FiniteElement feSub = subEl->getElement( surface );
7221 if(subEl->getDimension() == dim-1){
7222 // Setting flag to the placeholder (second last entry). The last entry at (funcParameter.size() - 1) should always be the degree of the surface function
7223 params[ funcParameter.size() - 1 ] = feSub.getFlag();
7224
7225 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
7226
7227 vec_dbl_Type v_E(dim,1.);
7228 double norm_v_E=1.;
7229
7230 Helper::computeSurfaceNormal(dim, pointsRep,nodeList,v_E,norm_v_E);
7231
7232 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
7233 elScaling = B.computeScaling( );
7234 // loop over basis functions
7235 for (UN i=0; i < phi->at(0).size(); i++) {
7236 Teuchos::Array<SC> value(0);
7237 if ( fieldType == "Scalar" )
7238 value.resize( 1, 0. );
7239 else if ( fieldType == "Vector" )
7240 value.resize( dim, 0. );
7241 // loop over basis functions quadrature points
7242 for (UN w=0; w<phi->size(); w++) {
7243 vec_dbl_Type x(dim,0.); //coordinates
7244 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7245 for (int l=0; l<dim-1; l++){
7246 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
7247 }
7248 x[k] += b[k];
7249 }
7250
7251 func( &x[0], &valueFunc[0], params);
7252 if ( fieldType == "Scalar" )
7253 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7254 else if ( fieldType == "Vector" ){
7255 for (int j=0; j<value.size(); j++){
7256 value[j] += weights->at(w) * valueFunc[j]*v_E[j]/norm_v_E * (*phi)[w][i];
7257 }
7258 }
7259 }
7260
7261 for (int j=0; j<value.size(); j++)
7262 value[j] *= elScaling;
7263
7264 if ( fieldType== "Scalar" )
7265 valuesF[ nodeList[ i ] ] += value[0];
7266
7267
7268 else if ( fieldType== "Vector" ){
7269 for (int j=0; j<value.size(); j++)
7270 valuesF[ dim * nodeList[ i ] + j ] += value[j];
7271 }
7272 }
7273 }
7274 }
7275 }
7276 f->scale(-1.); // Generally the pressure is definied in opposite direction of the normal
7277}
7278
7279template <class SC, class LO, class GO, class NO>
7280void FE<SC,LO,GO,NO>::assemblySurfaceIntegralFlag(int dim,
7281 std::string FEType,
7282 MultiVectorPtr_Type f,
7283 std::string fieldType,
7284 BC_func_Type func,
7285 std::vector<SC>& funcParameter) {
7286
7287// degree of function funcParameter[0]
7288 TEUCHOS_TEST_FOR_EXCEPTION(funcParameter[0]!=0,std::logic_error, "We only support constant functions for now.");
7289
7290 UN FEloc = checkFE(dim,FEType);
7291
7292 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7293
7294 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7295
7296 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7297 vec2D_dbl_ptr_Type phi;
7298 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7299 UN degFunc = funcParameter[0] + 1.e-14;
7300 UN deg = Helper::determineDegree( dim-1, FEType, Helper::Deriv0) + degFunc;
7301
7302 Helper::getPhi(phi, weights, dim-1, FEType, deg);
7303
7304 vec2D_dbl_ptr_Type quadPoints;
7305 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7306 Helper::getQuadratureValues(dim-1, deg, quadPoints, w, FEType);
7307 w.reset();
7308
7309 SC elScaling;
7310 SmallMatrix<SC> B(dim);
7311 vec_dbl_Type b(dim);
7312 f->putScalar(0.);
7313 Teuchos::ArrayRCP< SC > valuesF = f->getDataNonConst(0);
7314 int parameters;
7315
7316 std::vector<double> valueFunc(dim);
7317 SC* params = &(funcParameter[1]);
7318 for (UN T=0; T<elements->numberElements(); T++) {
7319 FiniteElement fe = elements->getElement( T );
7320 ElementsPtr_Type subEl = fe.getSubElements(); // might be null
7321 for (int surface=0; surface<fe.numSubElements(); surface++) {
7322 FiniteElement feSub = subEl->getElement( surface );
7323 if (params[1] == feSub.getFlag()){
7324 FiniteElement feSub = subEl->getElement( surface );
7325 vec_int_Type nodeList = feSub.getVectorNodeListNonConst ();
7326 Helper::buildTransformationSurface( nodeList, pointsRep, B, b, FEType);
7327 elScaling = B.computeScaling( );
7328 // loop over basis functions
7329 for (UN i=0; i < phi->at(0).size(); i++) {
7330 Teuchos::Array<SC> value(0);
7331 if ( fieldType == "Scalar" )
7332 value.resize( 1, 0. );
7333 else if ( fieldType == "Vector" )
7334 value.resize( dim, 0. );
7335 // loop over basis functions quadrature points
7336 for (UN w=0; w<phi->size(); w++) {
7337 vec_dbl_Type x(dim,0.); //coordinates
7338 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7339 for (int l=0; l<dim-1; l++)
7340 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ];
7341 x[k] += b[k];
7342 }
7343
7344 func( &x[0], &valueFunc[0], params[0], params);
7345// func( &x[0], &valueFunc[0], params);
7346 if ( fieldType == "Scalar" )
7347 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7348 else if ( fieldType == "Vector" ){
7349 for (int j=0; j<value.size(); j++){
7350 value[j] += weights->at(w) * valueFunc[j] * (*phi)[w][i];
7351 }
7352 }
7353 }
7354
7355 for (int j=0; j<value.size(); j++)
7356 value[j] *= elScaling;
7357
7358 if ( fieldType== "Scalar" )
7359 valuesF[ nodeList[ i ] ] += value[0];
7360
7361
7362 else if ( fieldType== "Vector" ){
7363 for (int j=0; j<value.size(); j++)
7364 valuesF[ dim * nodeList[ i ] + j ] += value[j];
7365 }
7366 }
7367 }
7368 }
7369
7370 }
7371}
7372
7373template <class SC, class LO, class GO, class NO>
7374void FE<SC,LO,GO,NO>::assemblyRHS( int dim,
7375 std::string FEType,
7376 MultiVectorPtr_Type a,
7377 std::string fieldType,
7378 RhsFunc_Type func,
7379 std::vector<SC>& funcParameter
7380 ) {
7381
7382 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7383
7384 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
7385 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
7386 UN FEloc;
7387 FEloc = checkFE(dim,FEType);
7388
7389 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7390
7391 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7392
7393 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7394 vec2D_dbl_ptr_Type phi;
7395 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7396
7397 // last parameter should alwayss be the degree
7398 //UN degFunc = funcParameter[funcParameter.size()-1] + 1.e-14; // TODO: [JK] Can we remove this?
7399 // inner( f(x), phi(x) ) requires the integration degree of the basis function + some
7400 // extra user-provided degree that accounts for the heterogeneity of f(x).
7401 UN degFunc = 2; // TODO: [JK] Hard coded for now, but needs to be passed by the user. See GitHub issue #66.
7402 UN deg = Helper::determineDegree( dim, FEType, Helper::Deriv0) + degFunc;
7403
7404 vec2D_dbl_ptr_Type quadPoints;
7405 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
7406
7407
7408 Helper::getPhi(phi, weights, dim, FEType, deg);
7409
7410 SC detB;
7411 SC absDetB;
7412 SmallMatrix<SC> B(dim);
7413 GO glob_i, glob_j;
7414 vec_dbl_Type v_i(dim);
7415 vec_dbl_Type v_j(dim);
7416
7417 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
7418 int parameters;
7419 double x;
7420 //for now just const!
7421 std::vector<double> valueFunc(dim);
7422 SC* paras = &(funcParameter[0]);
7423
7424 func( &x, &valueFunc[0], paras );
7425 SC value;
7426
7427 for (UN T=0; T<elements->numberElements(); T++) {
7428
7429 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
7430 detB = B.computeDet( );
7431 absDetB = std::fabs(detB);
7432
7433 vec2D_dbl_Type quadPointsTrans(weights->size(),vec_dbl_Type(dim));
7434 for(int i=0; i< weights->size(); i++){
7435 for(int j=0; j< dim ; j++){
7436 for(int k=0; k< dim; k++){
7437 quadPointsTrans[i][j] += B[j][k]* quadPoints->at(i).at(k) ;
7438 }
7439 quadPointsTrans[i][j] += pointsRep->at(elements->getElement(T).getNode(0)).at(j);
7440 }
7441 }
7442 for (UN i=0; i < phi->at(0).size(); i++) {
7443 if ( !fieldType.compare("Scalar") ) {
7444 value = Teuchos::ScalarTraits<SC>::zero();
7445 for (UN w=0; w<weights->size(); w++){
7446 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
7447 value += weights->at(w) * phi->at(w).at(i)*valueFunc[0];
7448 }
7449 value *= absDetB;
7450 LO row = (LO) elements->getElement(T).getNode(i);
7451 valuesRhs[row] += value;
7452 }
7453 else if( !fieldType.compare("Vector") ) {
7454 for (UN d=0; d<dim; d++) {
7455 value = Teuchos::ScalarTraits<SC>::zero();
7456 for (UN w=0; w<weights->size(); w++){
7457 func(&quadPointsTrans[w][0], &valueFunc[0] ,paras);
7458 value += weights->at(w) * phi->at(w).at(i)*valueFunc[d];
7459 }
7460 value *= absDetB;
7461 SC v_i = value;
7462 LO row = (LO) ( dim * elements->getElement(T).getNode(i) + d );
7463 valuesRhs[row] += v_i;
7464 }
7465 }
7466 else
7467 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
7468 }
7469 }
7470}
7471
7476template <class SC, class LO, class GO, class NO>
7478 std::string FEType,
7479 MatrixPtr_Type a,
7480 MatrixPtr_Type aT)
7481 {
7482
7483 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7484
7485 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "Matrix is null." );
7486
7487 UN FEloc;
7488 FEloc = checkFE(dim,FEType);
7489
7490 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7491
7492 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7493
7494 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7495 vec2D_dbl_ptr_Type phi;
7496 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7497 // last parameter should alwayss be the degree
7498 UN deg = 2;
7499
7500 vec2D_dbl_ptr_Type quadPoints;
7501 Helper::getQuadratureValues(dim, deg, quadPoints, weights, FEType); // quad points for rhs values
7502
7503 Helper::getPhi(phi, weights, dim, FEType, deg);
7504
7505 SC detB;
7506 SC absDetB;
7507 SmallMatrix<SC> B(dim);
7508 GO glob_i, glob_j;
7509 vec_dbl_Type v_i(dim);
7510 vec_dbl_Type v_j(dim);
7511
7512
7513 for (UN T=0; T<elements->numberElements(); T++) {
7514
7515 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, FEType);
7516 detB = B.computeDet( );
7517 absDetB = std::fabs(detB);
7518
7519 for (UN i=0; i < phi->at(0).size(); i++) {
7520 Teuchos::Array<SC> value( 1, 0. );
7521 for (UN w=0; w<weights->size(); w++){
7522 value[0] += weights->at(w) * phi->at(w).at(i)*1.0;
7523 }
7524 value[0] *= absDetB;
7525 LO row = (LO) elements->getElement(T).getNode(i);
7526 Teuchos::Array<GO> columnIndices( 1, 0 ); // We only have on column
7527
7528 a->insertGlobalValues( row, columnIndices(), value() ); // Automatically adds entries if a value already exists
7529 columnIndices[0] = row;
7530 aT->insertGlobalValues( 0, columnIndices(), value() ); // Automatically adds entries if a value already exists
7531 }
7532 }
7533 a->fillComplete();
7534 //a->print();
7535
7536}
7537
7538
7539template <class SC, class LO, class GO, class NO>
7540void FE<SC,LO,GO,NO>::assemblyRHSDegTest( int dim,
7541 std::string FEType,
7542 MultiVectorPtr_Type a,
7543 std::string fieldType,
7544 RhsFunc_Type func,
7545 std::vector<SC>& funcParameter,
7546 int degree) {
7547 // TODO: [JK] What is the aim of this function? It is not called by any problems, only by a test.
7548 TEUCHOS_TEST_FOR_EXCEPTION(FEType == "P0",std::logic_error, "Not implemented for P0");
7549
7550 TEUCHOS_TEST_FOR_EXCEPTION( a.is_null(), std::runtime_error, "MultiVector in assemblyConstRHS is null." );
7551 TEUCHOS_TEST_FOR_EXCEPTION( a->getNumVectors()>1, std::logic_error, "Implement for numberMV > 1 ." );
7552
7553 UN FEloc = checkFE(dim,FEType);
7554
7555 ElementsPtr_Type elements = domainVec_.at(FEloc)->getElementsC();
7556
7557 vec2D_dbl_ptr_Type pointsRep = domainVec_.at(FEloc)->getPointsRepeated();
7558
7559 MapConstPtr_Type map = domainVec_.at(FEloc)->getMapRepeated();
7560 vec2D_dbl_ptr_Type phi;
7561 vec_dbl_ptr_Type weights = Teuchos::rcp(new vec_dbl_Type(0));
7562 Helper::getPhi(phi, weights, dim, FEType, degree);
7563
7564 vec2D_dbl_ptr_Type quadPoints;
7565 vec_dbl_ptr_Type w = Teuchos::rcp(new vec_dbl_Type(0));
7566 Helper::getQuadratureValues(dim, degree, quadPoints, w, FEType);
7567 w.reset();
7568
7569
7570 SC detB;
7571 SC absDetB;
7572 SmallMatrix<SC> B(dim);
7573 vec_dbl_Type b(dim);
7574 GO glob_i, glob_j;
7575 vec_dbl_Type v_i(dim);
7576 vec_dbl_Type v_j(dim);
7577
7578 Teuchos::ArrayRCP< SC > valuesRhs = a->getDataNonConst(0);
7579 int parameters;
7580 double x;
7581 //for now just const!
7582 std::vector<double> valueFunc(dim);
7583 SC* params = &(funcParameter[1]);
7584 for (UN T=0; T<elements->numberElements(); T++) {
7585
7586 Helper::buildTransformation(elements->getElement(T).getVectorNodeList(), pointsRep, B, b, FEType);
7587 detB = B.computeDet( );
7588 absDetB = std::fabs(detB);
7589
7590 for (UN i=0; i < phi->at(0).size(); i++) {
7591 Teuchos::Array<SC> value(1);
7592 for (UN w=0; w<weights->size(); w++){
7593 vec_dbl_Type x(dim,0.); //coordinates
7594 for (int k=0; k<dim; k++) {// transform quad points to global coordinates
7595 for (int l=0; l<dim; l++)
7596 x[ k ] += B[k][l] * (*quadPoints)[ w ][ l ] + b[k];
7597 }
7598
7599 func( &x[0], &valueFunc[0], params);
7600 if ( !fieldType.compare("Scalar") ) {
7601 value[0] += weights->at(w) * valueFunc[0] * (*phi)[w][i];
7602 }
7603 else if( !fieldType.compare("Vector") ) {
7604 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "No test for field type Vector." );
7605 }
7606 else
7607 TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error, "Invalid field type." );
7608
7609 }
7610 value[0] *= absDetB;
7611 LO row = (LO) elements->getElement(T).getNode(i);
7612 valuesRhs[row] += value[0];
7613
7614 }
7615 }
7616}
7617
7618
7619template <class SC, class LO, class GO, class NO>
7620void FE<SC,LO,GO,NO>::buildFullDPhi(vec3D_dbl_ptr_Type dPhi, Teuchos::Array<SmallMatrix<double> >& dPhiMat){
7621
7622 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.");
7623
7624 int dim = dPhi->at(0).at(0).size();
7625 int nmbBasisFunc = dPhi->at(0).size();
7626 int nmbTotalBasisFunc = nmbBasisFunc * dim;
7627 if (dim==2) {
7628 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
7629 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
7630 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
7631 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
7632 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
7633 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
7634
7635 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
7636 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
7637 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
7638 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
7639 }
7640 }
7641 }
7642 else if(dim==3){
7643 for (int p=0; p<dPhi->size(); p++) { //loop over quad points
7644 for (int i=0; i<nmbBasisFunc; i++) { //loop over basis functions
7645 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][0] = dPhi->at(p).at(i).at(0);
7646 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][1] = dPhi->at(p).at(i).at(1);
7647 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][0][2] = dPhi->at(p).at(i).at(2);
7648 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][0] = 0.;
7649 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][1] = 0.;
7650 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][1][2] = 0.;
7651 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][0] = 0.;
7652 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][1] = 0.;
7653 dPhiMat[ p * nmbTotalBasisFunc + dim*i ][2][2] = 0.;
7654
7655 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][0] = 0.;
7656 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][1] = 0.;
7657 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][0][2] = 0.;
7658 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][0] = dPhi->at(p).at(i).at(0);
7659 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][1] = dPhi->at(p).at(i).at(1);
7660 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][1][2] = dPhi->at(p).at(i).at(2);
7661 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][0] = 0.;
7662 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][1] = 0.;
7663 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 1 ][2][2] = 0.;
7664
7665 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][0] = 0.;
7666 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][1] = 0.;
7667 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][0][2] = 0.;
7668 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][0] = 0.;
7669 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][1] = 0.;
7670 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][1][2] = 0.;
7671 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][0] = dPhi->at(p).at(i).at(0);
7672 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][1] = dPhi->at(p).at(i).at(1);
7673 dPhiMat[ p * nmbTotalBasisFunc + dim*i + 2 ][2][2] = dPhi->at(p).at(i).at(2);
7674 }
7675 }
7676 }
7677}
7678
7679template <class SC, class LO, class GO, class NO>
7680void FE<SC,LO,GO,NO>::fillMatrixArray(SmallMatrix<double> &matIn, double* matArrayOut, std::string order,int offset){
7681 if (!order.compare("cols")) {
7682 for (int j=0; j<matIn.size(); j++) {
7683 for (int i=0; i<matIn.size(); i++) {
7684 matArrayOut[ j * matIn.size() + i + offset ] = matIn[i][j]; //Spalten der Matrix werden hintereinander in array geschrieben
7685 }
7686 }
7687 }
7688 else if(!order.compare("rows")) {
7689 for (int i=0; i<matIn.size(); i++) {
7690 for (int j=0; j<matIn.size(); j++) {
7691 matArrayOut[ i * matIn.size() + j + offset ] = matIn[i][j]; //Zeilen der Matrix werden hintereinander in array geschrieben
7692 }
7693 }
7694 }
7695 else
7696 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Unknown ordering for matrix to array conversion. Choose rows or cols.");
7697}
7698
7699template <class SC, class LO, class GO, class NO>
7700void FE<SC,LO,GO,NO>::epsilonTensor(vec_dbl_Type &basisValues, SmallMatrix<SC> &epsilonValues, int activeDof){
7701
7702 for (int i=0; i<epsilonValues.size(); i++) {
7703 for (int j=0; j<epsilonValues.size(); j++) {
7704 epsilonValues[i][j] = 0.;
7705 if (i==activeDof) {
7706 epsilonValues[i][j] += 0.5*basisValues.at(j);
7707 }
7708 if (j==activeDof) {
7709 epsilonValues[i][j] += 0.5*basisValues.at(i);
7710 }
7711 }
7712 }
7713}
7714
7715template <class SC, class LO, class GO, class NO>
7716int FE<SC,LO,GO,NO>::checkFE(int dim,
7717 std::string FEType){
7718
7719 int FEloc;
7720 std::vector<int> matches;
7721 for (int i = 0; i < domainVec_.size(); i++) {
7722 if (domainVec_.at(i)->getDimension() == dim)
7723 matches.push_back(i);
7724 }
7725
7726 bool found = false;
7727 for (int i = 0; i < matches.size();i++) {
7728 if (domainVec_.at( matches.at(i) )->getFEType() == FEType) {
7729 FEloc = matches.at(i);
7730 found = true;
7731 }
7732 }
7733
7734 TEUCHOS_TEST_FOR_EXCEPTION(!found, std::logic_error ,"Combination of dimenson(2/3) and FE Type(P1/P2) not defined yet. Use addFE(domain)");
7735
7736 return FEloc;
7737}
7738
7739
7740/*************************************************************
7741 * AceGen 6.921 MacOSX (29 Jan 19) *
7742 * Co. J. Korelc 2013 12 Feb 19 12:07:04 *
7743 **************************************************************
7744 User : Full professional version
7745 Notebook : nh3d_C
7746 Evaluation time : 6 s Mode : Optimal
7747 Number of formulae : 181 Method: Automatic
7748 Subroutine : nh3d size: 4928
7749 Total size of Mathematica code : 4928 subexpressions
7750 Total size of C code : 10178 bytes */
7751/******************* S U B R O U T I N E *********************/
7752template <class SC, class LO, class GO, class NO>
7753void FE<SC,LO,GO,NO>::nh3d(double* v, double (*E), double (*Nu), double** F , double** Pmat, double**** Amat)
7754{
7755 v[356]=2e0*F[0][2];
7756 v[354]=2e0*F[0][1];
7757 v[323]=(*E)/(1e0+(*Nu));
7758 v[3]=((*Nu)*v[323])/(1e0-2e0*(*Nu));
7759 v[5]=v[323]/2e0;
7760 v[36]=v[5]/2e0;
7761 v[65]=2e0*F[0][1];
7762 v[86]=2e0*F[0][2];
7763 v[57]=2e0*F[1][0];
7764 v[66]=2e0*F[1][1];
7765 v[87]=2e0*F[1][2];
7766 v[58]=2e0*F[2][0];
7767 v[67]=2e0*F[2][1];
7768 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
7769 v[335]=(v[18]*v[18]);
7770 v[88]=2e0*F[2][2];
7771 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
7772 v[334]=(v[24]*v[24]);
7773 v[325]=v[18]*v[24];
7774 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
7775 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
7776 v[228]=-(F[2][1]*v[18]);
7777 v[225]=F[2][2]*v[18];
7778 v[217]=-(F[1][1]*v[18]);
7779 v[214]=F[1][2]*v[18];
7780 v[194]=-(F[2][0]*v[18]);
7781 v[185]=-(F[1][0]*v[18]);
7782 v[268]=F[2][1]*v[22];
7783 v[264]=-(F[2][2]*v[22]);
7784 v[255]=F[1][1]*v[22];
7785 v[251]=-(F[1][2]*v[22]);
7786 v[190]=-(F[2][0]*v[22]);
7787 v[181]=-(F[1][0]*v[22]);
7788 v[172]=-(F[0][0]*v[22]);
7789 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
7790 v[324]=-(v[20]*v[22]);
7791 v[327]=2e0*(v[324]+v[325]);
7792 v[94]=v[20]*v[88];
7793 v[92]=v[20]*v[87];
7794 v[90]=v[20]*v[86];
7795 v[138]=v[15]*v[20]-v[335];
7796 v[270]=F[2][0]*v[24];
7797 v[260]=-(F[2][2]*v[24]);
7798 v[257]=F[1][0]*v[24];
7799 v[247]=-(F[1][2]*v[24]);
7800 v[244]=F[0][0]*v[24];
7801 v[232]=-(F[0][2]*v[24]);
7802 v[222]=-(F[2][1]*v[24]);
7803 v[211]=-(F[1][1]*v[24]);
7804 v[198]=-(F[0][1]*v[24]);
7805 v[168]=v[18]*v[22]-v[15]*v[24];
7806 v[331]=2e0*v[168];
7807 v[329]=2e0*v[168];
7808 v[326]=2e0*v[168];
7809 v[38]=-(v[22]*v[22]);
7810 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
7811 v[333]=v[20]*v[26]-v[334];
7812 v[351]=2e0*F[0][0]*v[333];
7813 v[236]=v[22]*v[24]-v[18]*v[26];
7814 v[332]=2e0*v[236];
7815 v[330]=2e0*v[236];
7816 v[328]=2e0*v[236];
7817 v[99]=v[26]*v[58];
7818 v[97]=v[26]*v[57];
7819 v[93]=v[26]*v[67];
7820 v[91]=v[26]*v[66];
7821 v[89]=v[26]*v[65];
7822 v[148]=v[15]*v[26]+v[38];
7823 v[29]=v[148]*v[20]+2e0*v[22]*v[325]-v[15]*v[334]-v[26]*v[335];
7824 v[336]=1e0/Power(v[29],2);
7825 v[32]=-v[5]+v[3]*std::log(std::sqrt(v[29]));
7826 v[337]=(v[3]/4e0-v[32]/2e0)*v[336];
7827 v[137]=v[337]*(F[2][1]*v[326]+F[2][0]*v[327]-v[335]*v[88]+v[15]*v[94]);
7828 v[147]=v[137]*v[138];
7829 v[136]=v[337]*(F[2][2]*v[329]+F[2][0]*v[330]+v[38]*v[67]+v[15]*v[93]);
7830 v[156]=v[136]*v[148];
7831 v[135]=v[337]*(F[2][2]*v[327]+F[2][1]*v[328]-v[334]*v[58]+v[20]*v[99]);
7832 v[165]=v[135]*v[333];
7833 v[134]=v[337]*(F[1][1]*v[326]+F[1][0]*v[327]-v[335]*v[87]+v[15]*v[92]);
7834 v[144]=v[134]*v[138];
7835 v[133]=v[337]*(F[1][2]*v[331]+F[1][0]*v[332]+v[38]*v[66]+v[15]*v[91]);
7836 v[153]=v[133]*v[148];
7837 v[132]=v[337]*(F[1][2]*v[327]+F[1][1]*v[328]-v[334]*v[57]+v[20]*v[97]);
7838 v[162]=v[132]*v[333];
7839 v[131]=v[337]*(F[0][0]*v[327]+F[0][1]*v[329]-v[335]*v[86]+v[15]*v[90]);
7840 v[130]=v[337]*(F[0][2]*v[331]+F[0][0]*v[332]+v[38]*v[65]+v[15]*v[89]);
7841 v[128]=v[337]*(F[0][2]*v[327]+F[0][1]*v[330]+v[351]);
7842 v[37]=v[32]/(2e0*v[29]);
7843 v[355]=v[37]*(2e0*v[172]+v[15]*v[86]);
7844 v[353]=v[37]*(2e0*v[232]+v[89]);
7845 v[352]=v[37]*(2e0*v[198]+v[90]);
7846 v[349]=-2e0*(F[1][0]*v[20]+v[217])*v[37];
7847 v[348]=-(v[37]*(2e0*v[185]+v[15]*v[66]));
7848 v[347]=-2e0*(F[2][0]*v[20]+v[228])*v[37];
7849 v[346]=-(v[37]*(2e0*v[194]+v[15]*v[67]));
7850 v[345]=-(v[37]*(2e0*v[251]+v[97]));
7851 v[344]=-(v[37]*(2e0*v[181]+v[15]*v[87]));
7852 v[343]=-(v[37]*(2e0*v[264]+v[99]));
7853 v[342]=-(v[37]*(2e0*v[190]+v[15]*v[88]));
7854 v[341]=-(v[37]*(2e0*v[247]+v[91]));
7855 v[340]=-(v[37]*(2e0*v[211]+v[92]));
7856 v[339]=-(v[37]*(2e0*v[260]+v[93]));
7857 v[338]=-(v[37]*(2e0*v[222]+v[94]));
7858 v[272]=v[137]*v[328]+v[37]*(2e0*v[268]+2e0*v[270]-2e0*v[18]*v[88]);
7859 v[267]=v[136]*v[328]+v[343];
7860 v[263]=v[135]*v[328]+v[339];
7861 v[259]=v[134]*v[328]+v[37]*(2e0*v[255]+2e0*v[257]-2e0*v[18]*v[87]);
7862 v[254]=v[133]*v[328]+v[345];
7863 v[250]=v[132]*v[328]+v[341];
7864 v[246]=v[131]*v[328]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[244]-2e0*v[18]*v[86]);
7865 v[241]=v[130]*v[328]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
7866 v[231]=v[137]*v[327]+v[347];
7867 v[227]=v[136]*v[327]+v[37]*(2e0*v[225]+2e0*v[270]-2e0*v[22]*v[67]);
7868 v[224]=v[135]*v[327]+v[338];
7869 v[301]=2e0*F[1][0]*v[165]+F[1][2]*v[224]+F[1][1]*v[263];
7870 v[279]=2e0*F[0][0]*v[165]+F[0][2]*v[224]+F[0][1]*v[263];
7871 v[220]=v[134]*v[327]+v[349];
7872 v[216]=v[133]*v[327]+v[37]*(2e0*v[214]+2e0*v[257]-2e0*v[22]*v[66]);
7873 v[213]=v[132]*v[327]+v[340];
7874 v[276]=2e0*F[0][0]*v[162]+F[0][2]*v[213]+F[0][1]*v[250];
7875 v[209]=v[131]*v[327]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
7876 v[196]=v[137]*v[326]+v[346];
7877 v[314]=2e0*F[1][2]*v[147]+F[1][1]*v[196]+F[1][0]*v[231];
7878 v[296]=2e0*F[0][2]*v[147]+F[0][1]*v[196]+F[0][0]*v[231];
7879 v[192]=v[136]*v[326]+v[342];
7880 v[308]=2e0*F[1][1]*v[156]+F[1][2]*v[192]+F[1][0]*v[267];
7881 v[288]=2e0*F[0][1]*v[156]+F[0][2]*v[192]+F[0][0]*v[267];
7882 v[188]=v[135]*v[326]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[24]*v[58]);
7883 v[187]=v[134]*v[326]+v[348];
7884 v[293]=2e0*F[0][2]*v[144]+F[0][1]*v[187]+F[0][0]*v[220];
7885 v[183]=v[133]*v[326]+v[344];
7886 v[285]=2e0*F[0][1]*v[153]+F[0][2]*v[183]+F[0][0]*v[254];
7887 v[179]=v[132]*v[326]+v[37]*(2e0*v[214]+2e0*v[255]-2e0*v[24]*v[57]);
7888 v[178]=v[131]*v[326]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
7889 v[167]=v[137]*v[333]-v[338];
7890 v[303]=2e0*F[1][0]*v[167]+F[1][2]*v[231]+F[1][1]*v[272];
7891 v[281]=2e0*F[0][0]*v[167]+F[0][2]*v[231]+F[0][1]*v[272];
7892 v[166]=v[136]*v[333]-v[339];
7893 v[302]=2e0*F[1][0]*v[166]+F[1][2]*v[227]+F[1][1]*v[267];
7894 v[280]=2e0*F[0][0]*v[166]+F[0][2]*v[227]+F[0][1]*v[267];
7895 v[164]=v[134]*v[333]-v[340];
7896 v[278]=2e0*F[0][0]*v[164]+F[0][2]*v[220]+F[0][1]*v[259];
7897 v[163]=v[133]*v[333]-v[341];
7898 v[277]=2e0*F[0][0]*v[163]+F[0][2]*v[216]+F[0][1]*v[254];
7899 v[157]=v[137]*v[148]-v[342];
7900 v[309]=2e0*F[1][1]*v[157]+F[1][2]*v[196]+F[1][0]*v[272];
7901 v[289]=2e0*F[0][1]*v[157]+F[0][2]*v[196]+F[0][0]*v[272];
7902 v[155]=v[135]*v[148]-v[343];
7903 v[307]=2e0*F[1][1]*v[155]+F[1][2]*v[188]+F[1][0]*v[263];
7904 v[287]=2e0*F[0][1]*v[155]+F[0][2]*v[188]+F[0][0]*v[263];
7905 v[154]=v[134]*v[148]-v[344];
7906 v[286]=2e0*F[0][1]*v[154]+F[0][2]*v[187]+F[0][0]*v[259];
7907 v[284]=F[0][2]*v[179]+F[0][0]*v[250]+2e0*F[0][1]*(v[132]*v[148]-v[345]);
7908 v[146]=v[136]*v[138]-v[346];
7909 v[313]=2e0*F[1][2]*v[146]+F[1][1]*v[192]+F[1][0]*v[227];
7910 v[295]=2e0*F[0][2]*v[146]+F[0][1]*v[192]+F[0][0]*v[227];
7911 v[145]=v[135]*v[138]-v[347];
7912 v[312]=2e0*F[1][2]*v[145]+F[1][1]*v[188]+F[1][0]*v[224];
7913 v[294]=2e0*F[0][2]*v[145]+F[0][1]*v[188]+F[0][0]*v[224];
7914 v[292]=F[0][1]*v[183]+F[0][0]*v[216]+2e0*F[0][2]*(v[133]*v[138]-v[348]);
7915 v[291]=F[0][1]*v[179]+F[0][0]*v[213]+(v[132]*v[138]-v[349])*v[356];
7916 v[35]=v[36]+v[138]*v[37];
7917 v[310]=2e0*v[35];
7918 v[40]=v[36]+v[148]*v[37];
7919 v[304]=2e0*v[40];
7920 v[43]=v[36]+v[333]*v[37];
7921 v[297]=2e0*v[43];
7922 v[44]=v[326]*v[37];
7923 v[319]=2e0*F[2][1]*v[157]+F[2][2]*v[196]+F[2][0]*v[272]+v[44];
7924 v[306]=2e0*F[1][1]*v[154]+F[1][2]*v[187]+F[1][0]*v[259]+v[44];
7925 v[283]=F[0][2]*v[178]+F[0][0]*v[246]+v[354]*(v[131]*v[148]+v[355])+v[44];
7926 v[45]=v[327]*v[37];
7927 v[317]=2e0*F[2][0]*v[167]+F[2][2]*v[231]+F[2][1]*v[272]+v[45];
7928 v[300]=2e0*F[1][0]*v[164]+F[1][2]*v[220]+F[1][1]*v[259]+v[45];
7929 v[275]=F[0][2]*v[209]+F[0][1]*v[246]+2e0*F[0][0]*(v[131]*v[333]+v[352])+v[45];
7930 v[46]=v[328]*v[37];
7931 v[316]=2e0*F[2][0]*v[166]+F[2][2]*v[227]+F[2][1]*v[267]+v[46];
7932 v[299]=2e0*F[1][0]*v[163]+F[1][2]*v[216]+F[1][1]*v[254]+v[46];
7933 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]*
7934 (2e0*F[0][2]*v[18]+2e0*v[244]-2e0*v[22]*v[65]));
7935 Pmat[0][0]=F[0][0]*v[297]+F[0][2]*v[45]+F[0][1]*v[46];
7936 Pmat[0][1]=F[0][1]*v[304]+F[0][2]*v[44]+F[0][0]*v[46];
7937 Pmat[0][2]=F[0][2]*v[310]+F[0][1]*v[44]+F[0][0]*v[45];
7938 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[45]+F[1][1]*v[46];
7939 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[44]+F[1][0]*v[46];
7940 Pmat[1][2]=2e0*F[1][2]*v[35]+F[1][1]*v[44]+F[1][0]*v[45];
7941 Pmat[2][0]=F[2][0]*v[297]+F[2][2]*v[45]+F[2][1]*v[46];
7942 Pmat[2][1]=F[2][1]*v[304]+F[2][2]*v[44]+F[2][0]*v[46];
7943 Pmat[2][2]=F[2][2]*v[310]+F[2][1]*v[44]+F[2][0]*v[45];
7944 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]
7945 );
7946 Amat[0][0][0][1]=v[274];
7947 Amat[0][0][0][2]=v[275];
7948 Amat[0][0][1][0]=v[276];
7949 Amat[0][0][1][1]=v[277];
7950 Amat[0][0][1][2]=v[278];
7951 Amat[0][0][2][0]=v[279];
7952 Amat[0][0][2][1]=v[280];
7953 Amat[0][0][2][2]=v[281];
7954 Amat[0][1][0][0]=v[274];
7955 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]);
7956 Amat[0][1][0][2]=v[283];
7957 Amat[0][1][1][0]=v[284];
7958 Amat[0][1][1][1]=v[285];
7959 Amat[0][1][1][2]=v[286];
7960 Amat[0][1][2][0]=v[287];
7961 Amat[0][1][2][1]=v[288];
7962 Amat[0][1][2][2]=v[289];
7963 Amat[0][2][0][0]=v[275];
7964 Amat[0][2][0][1]=v[283];
7965 Amat[0][2][0][2]=F[0][1]*v[178]+F[0][0]*v[209]+v[310]+v[131]*v[138]*v[356];
7966 Amat[0][2][1][0]=v[291];
7967 Amat[0][2][1][1]=v[292];
7968 Amat[0][2][1][2]=v[293];
7969 Amat[0][2][2][0]=v[294];
7970 Amat[0][2][2][1]=v[295];
7971 Amat[0][2][2][2]=v[296];
7972 Amat[1][0][0][0]=v[276];
7973 Amat[1][0][0][1]=v[284];
7974 Amat[1][0][0][2]=v[291];
7975 Amat[1][0][1][0]=2e0*F[1][0]*v[162]+F[1][2]*v[213]+F[1][1]*v[250]+v[297];
7976 Amat[1][0][1][1]=v[299];
7977 Amat[1][0][1][2]=v[300];
7978 Amat[1][0][2][0]=v[301];
7979 Amat[1][0][2][1]=v[302];
7980 Amat[1][0][2][2]=v[303];
7981 Amat[1][1][0][0]=v[277];
7982 Amat[1][1][0][1]=v[285];
7983 Amat[1][1][0][2]=v[292];
7984 Amat[1][1][1][0]=v[299];
7985 Amat[1][1][1][1]=2e0*F[1][1]*v[153]+F[1][2]*v[183]+F[1][0]*v[254]+v[304];
7986 Amat[1][1][1][2]=v[306];
7987 Amat[1][1][2][0]=v[307];
7988 Amat[1][1][2][1]=v[308];
7989 Amat[1][1][2][2]=v[309];
7990 Amat[1][2][0][0]=v[278];
7991 Amat[1][2][0][1]=v[286];
7992 Amat[1][2][0][2]=v[293];
7993 Amat[1][2][1][0]=v[300];
7994 Amat[1][2][1][1]=v[306];
7995 Amat[1][2][1][2]=2e0*F[1][2]*v[144]+F[1][1]*v[187]+F[1][0]*v[220]+v[310];
7996 Amat[1][2][2][0]=v[312];
7997 Amat[1][2][2][1]=v[313];
7998 Amat[1][2][2][2]=v[314];
7999 Amat[2][0][0][0]=v[279];
8000 Amat[2][0][0][1]=v[287];
8001 Amat[2][0][0][2]=v[294];
8002 Amat[2][0][1][0]=v[301];
8003 Amat[2][0][1][1]=v[307];
8004 Amat[2][0][1][2]=v[312];
8005 Amat[2][0][2][0]=2e0*F[2][0]*v[165]+F[2][2]*v[224]+F[2][1]*v[263]+v[297];
8006 Amat[2][0][2][1]=v[316];
8007 Amat[2][0][2][2]=v[317];
8008 Amat[2][1][0][0]=v[280];
8009 Amat[2][1][0][1]=v[288];
8010 Amat[2][1][0][2]=v[295];
8011 Amat[2][1][1][0]=v[302];
8012 Amat[2][1][1][1]=v[308];
8013 Amat[2][1][1][2]=v[313];
8014 Amat[2][1][2][0]=v[316];
8015 Amat[2][1][2][1]=2e0*F[2][1]*v[156]+F[2][2]*v[192]+F[2][0]*v[267]+v[304];
8016 Amat[2][1][2][2]=v[319];
8017 Amat[2][2][0][0]=v[281];
8018 Amat[2][2][0][1]=v[289];
8019 Amat[2][2][0][2]=v[296];
8020 Amat[2][2][1][0]=v[303];
8021 Amat[2][2][1][1]=v[309];
8022 Amat[2][2][1][2]=v[314];
8023 Amat[2][2][2][0]=v[317];
8024 Amat[2][2][2][1]=v[319];
8025 Amat[2][2][2][2]=2e0*F[2][2]*v[147]+F[2][1]*v[196]+F[2][0]*v[231]+v[310];
8026}
8027
8028
8029/*************************************************************
8030 * AceGen 6.921 MacOSX (29 Jan 19) *
8031 * Co. J. Korelc 2013 12 Feb 19 12:06:46 *
8032 **************************************************************
8033 User : Full professional version
8034 Notebook : mr3d_C
8035 Evaluation time : 7 s Mode : Optimal
8036 Number of formulae : 190 Method: Automatic
8037 Subroutine : mr3d size: 5215
8038 Total size of Mathematica code : 5215 subexpressions
8039 Total size of C code : 10798 bytes */
8040
8041/******************* S U B R O U T I N E *********************/
8042template <class SC, class LO, class GO, class NO>
8043void FE<SC,LO,GO,NO>::mr3d(double* v,double (*E),double (*Nu),double (*C)
8044 ,double** F,double** Pmat,double**** Amat)
8045{
8046 v[366]=2e0*F[0][2];
8047 v[364]=2e0*F[0][1];
8048 v[4]=(*E)/(2e0+2e0*(*Nu));
8049 v[139]=((*C)*v[4])/2e0;
8050 v[5]=(*E)/(3e0-6e0*(*Nu));
8051 v[57]=2e0*F[0][0];
8052 v[150]=v[139]*v[57];
8053 v[66]=2e0*F[0][1];
8054 v[165]=v[139]*v[66];
8055 v[87]=2e0*F[0][2];
8056 v[167]=v[139]*v[87];
8057 v[58]=2e0*F[1][0];
8058 v[155]=v[139]*v[58];
8059 v[67]=2e0*F[1][1];
8060 v[170]=v[139]*v[67];
8061 v[88]=2e0*F[1][2];
8062 v[172]=v[139]*v[88];
8063 v[59]=2e0*F[2][0];
8064 v[159]=v[139]*v[59];
8065 v[68]=2e0*F[2][1];
8066 v[175]=v[139]*v[68];
8067 v[18]=F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1];
8068 v[345]=(v[18]*v[18]);
8069 v[89]=2e0*F[2][2];
8070 v[177]=v[139]*v[89];
8071 v[24]=F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2];
8072 v[344]=(v[24]*v[24]);
8073 v[335]=v[18]*v[24];
8074 v[22]=F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2];
8075 v[15]=Power(F[0][0],2)+Power(F[1][0],2)+Power(F[2][0],2);
8076 v[239]=-(F[2][1]*v[18]);
8077 v[236]=F[2][2]*v[18];
8078 v[228]=-(F[1][1]*v[18]);
8079 v[225]=F[1][2]*v[18];
8080 v[205]=-(F[2][0]*v[18]);
8081 v[196]=-(F[1][0]*v[18]);
8082 v[279]=F[2][1]*v[22];
8083 v[275]=-(F[2][2]*v[22]);
8084 v[266]=F[1][1]*v[22];
8085 v[262]=-(F[1][2]*v[22]);
8086 v[201]=-(F[2][0]*v[22]);
8087 v[192]=-(F[1][0]*v[22]);
8088 v[183]=-(F[0][0]*v[22]);
8089 v[20]=Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2);
8090 v[334]=-(v[20]*v[22]);
8091 v[337]=2e0*(v[334]+v[335]);
8092 v[95]=v[20]*v[89];
8093 v[93]=v[20]*v[88];
8094 v[91]=v[20]*v[87];
8095 v[140]=v[15]*v[20]-v[345];
8096 v[281]=F[2][0]*v[24];
8097 v[271]=-(F[2][2]*v[24]);
8098 v[268]=F[1][0]*v[24];
8099 v[258]=-(F[1][2]*v[24]);
8100 v[255]=F[0][0]*v[24];
8101 v[243]=-(F[0][2]*v[24]);
8102 v[233]=-(F[2][1]*v[24]);
8103 v[222]=-(F[1][1]*v[24]);
8104 v[209]=-(F[0][1]*v[24]);
8105 v[179]=v[18]*v[22]-v[15]*v[24];
8106 v[341]=2e0*v[179];
8107 v[339]=2e0*v[179];
8108 v[336]=2e0*v[179];
8109 v[38]=-(v[22]*v[22]);
8110 v[26]=Power(F[0][2],2)+Power(F[1][2],2)+Power(F[2][2],2);
8111 v[343]=v[20]*v[26]-v[344];
8112 v[361]=v[343]*v[57];
8113 v[247]=v[22]*v[24]-v[18]*v[26];
8114 v[342]=2e0*v[247];
8115 v[340]=2e0*v[247];
8116 v[338]=2e0*v[247];
8117 v[100]=v[26]*v[59];
8118 v[98]=v[26]*v[58];
8119 v[94]=v[26]*v[68];
8120 v[92]=v[26]*v[67];
8121 v[90]=v[26]*v[66];
8122 v[151]=v[15]*v[26]+v[38];
8123 v[29]=v[151]*v[20]+2e0*v[22]*v[335]-v[15]*v[344]-v[26]*v[345];
8124 v[346]=1e0/Power(v[29],2);
8125 v[33]=-2e0*v[139]-v[4]+v[5]*std::log(std::sqrt(v[29]));
8126 v[347]=v[346]*(-v[33]/2e0+v[5]/4e0);
8127 v[138]=v[347]*(F[2][1]*v[336]+F[2][0]*v[337]-v[345]*v[89]+v[15]*v[95]);
8128 v[149]=v[138]*v[140];
8129 v[137]=v[347]*(F[2][2]*v[339]+F[2][0]*v[340]+v[38]*v[68]+v[15]*v[94]);
8130 v[161]=v[137]*v[151];
8131 v[136]=v[347]*(v[100]*v[20]+F[2][2]*v[337]+F[2][1]*v[338]-v[344]*v[59]);
8132 v[174]=v[136]*v[343];
8133 v[135]=v[347]*(F[1][1]*v[336]+F[1][0]*v[337]-v[345]*v[88]+v[15]*v[93]);
8134 v[146]=v[135]*v[140];
8135 v[134]=v[347]*(F[1][2]*v[341]+F[1][0]*v[342]+v[38]*v[67]+v[15]*v[92]);
8136 v[157]=v[134]*v[151];
8137 v[133]=v[347]*(F[1][2]*v[337]+F[1][1]*v[338]-v[344]*v[58]+v[20]*v[98]);
8138 v[169]=v[133]*v[343];
8139 v[132]=v[347]*(F[0][0]*v[337]+F[0][1]*v[339]-v[345]*v[87]+v[15]*v[91]);
8140 v[131]=v[347]*(F[0][2]*v[341]+F[0][0]*v[342]+v[38]*v[66]+v[15]*v[90]);
8141 v[129]=v[347]*(F[0][2]*v[337]+F[0][1]*v[340]+v[361]);
8142 v[37]=v[33]/(2e0*v[29]);
8143 v[365]=v[37]*(2e0*v[183]+v[15]*v[87]);
8144 v[363]=v[37]*(2e0*v[243]+v[90]);
8145 v[362]=v[37]*(2e0*v[209]+v[91]);
8146 v[359]=-2e0*(F[1][0]*v[20]+v[228])*v[37];
8147 v[358]=-(v[37]*(2e0*v[196]+v[15]*v[67]));
8148 v[357]=-2e0*(F[2][0]*v[20]+v[239])*v[37];
8149 v[356]=-(v[37]*(2e0*v[205]+v[15]*v[68]));
8150 v[355]=-(v[37]*(2e0*v[262]+v[98]));
8151 v[354]=-(v[37]*(2e0*v[192]+v[15]*v[88]));
8152 v[353]=-((v[100]+2e0*v[275])*v[37]);
8153 v[352]=-(v[37]*(2e0*v[201]+v[15]*v[89]));
8154 v[351]=-(v[37]*(2e0*v[258]+v[92]));
8155 v[350]=-(v[37]*(2e0*v[222]+v[93]));
8156 v[349]=-(v[37]*(2e0*v[271]+v[94]));
8157 v[348]=-(v[37]*(2e0*v[233]+v[95]));
8158 v[283]=v[138]*v[338]+v[37]*(2e0*v[279]+2e0*v[281]-2e0*v[18]*v[89]);
8159 v[278]=-v[159]+v[137]*v[338]+v[353];
8160 v[274]=-v[175]+v[136]*v[338]+v[349];
8161 v[270]=v[135]*v[338]+v[37]*(2e0*v[266]+2e0*v[268]-2e0*v[18]*v[88]);
8162 v[265]=-v[155]+v[134]*v[338]+v[355];
8163 v[261]=-v[170]+v[133]*v[338]+v[351];
8164 v[257]=v[132]*v[338]+v[37]*(2e0*F[0][1]*v[22]+2e0*v[255]-2e0*v[18]*v[87]);
8165 v[252]=-v[150]+v[131]*v[338]+2e0*(F[0][2]*v[22]-F[0][0]*v[26])*v[37];
8166 v[242]=-v[159]+v[138]*v[337]+v[357];
8167 v[238]=v[137]*v[337]+v[37]*(2e0*v[236]+2e0*v[281]-2e0*v[22]*v[68]);
8168 v[235]=-v[177]+v[136]*v[337]+v[348];
8169 v[312]=2e0*F[1][0]*v[174]+F[1][2]*v[235]+F[1][1]*v[274];
8170 v[290]=2e0*F[0][0]*v[174]+F[0][2]*v[235]+F[0][1]*v[274];
8171 v[231]=-v[155]+v[135]*v[337]+v[359];
8172 v[227]=v[134]*v[337]+v[37]*(2e0*v[225]+2e0*v[268]-2e0*v[22]*v[67]);
8173 v[224]=-v[172]+v[133]*v[337]+v[350];
8174 v[287]=2e0*F[0][0]*v[169]+F[0][2]*v[224]+F[0][1]*v[261];
8175 v[220]=-v[150]+v[132]*v[337]+2e0*(F[0][1]*v[18]-F[0][0]*v[20])*v[37];
8176 v[207]=-v[175]+v[138]*v[336]+v[356];
8177 v[325]=2e0*F[1][2]*v[149]+F[1][1]*v[207]+F[1][0]*v[242];
8178 v[307]=2e0*F[0][2]*v[149]+F[0][1]*v[207]+F[0][0]*v[242];
8179 v[203]=-v[177]+v[137]*v[336]+v[352];
8180 v[319]=2e0*F[1][1]*v[161]+F[1][2]*v[203]+F[1][0]*v[278];
8181 v[299]=2e0*F[0][1]*v[161]+F[0][2]*v[203]+F[0][0]*v[278];
8182 v[199]=v[136]*v[336]+v[37]*(2e0*v[236]+2e0*v[279]-2e0*v[24]*v[59]);
8183 v[198]=-v[170]+v[135]*v[336]+v[358];
8184 v[304]=2e0*F[0][2]*v[146]+F[0][1]*v[198]+F[0][0]*v[231];
8185 v[194]=-v[172]+v[134]*v[336]+v[354];
8186 v[296]=2e0*F[0][1]*v[157]+F[0][2]*v[194]+F[0][0]*v[265];
8187 v[190]=v[133]*v[336]+v[37]*(2e0*v[225]+2e0*v[266]-2e0*v[24]*v[58]);
8188 v[189]=-v[165]+v[132]*v[336]+2e0*(-(F[0][1]*v[15])+F[0][0]*v[18])*v[37];
8189 v[178]=v[177]+v[138]*v[343]-v[348];
8190 v[314]=2e0*F[1][0]*v[178]+F[1][2]*v[242]+F[1][1]*v[283];
8191 v[292]=2e0*F[0][0]*v[178]+F[0][2]*v[242]+F[0][1]*v[283];
8192 v[176]=v[175]+v[137]*v[343]-v[349];
8193 v[313]=2e0*F[1][0]*v[176]+F[1][2]*v[238]+F[1][1]*v[278];
8194 v[291]=2e0*F[0][0]*v[176]+F[0][2]*v[238]+F[0][1]*v[278];
8195 v[173]=v[172]+v[135]*v[343]-v[350];
8196 v[289]=2e0*F[0][0]*v[173]+F[0][2]*v[231]+F[0][1]*v[270];
8197 v[171]=v[170]+v[134]*v[343]-v[351];
8198 v[288]=2e0*F[0][0]*v[171]+F[0][2]*v[227]+F[0][1]*v[265];
8199 v[162]=v[138]*v[151]+v[177]-v[352];
8200 v[320]=2e0*F[1][1]*v[162]+F[1][2]*v[207]+F[1][0]*v[283];
8201 v[300]=2e0*F[0][1]*v[162]+F[0][2]*v[207]+F[0][0]*v[283];
8202 v[160]=v[136]*v[151]+v[159]-v[353];
8203 v[318]=2e0*F[1][1]*v[160]+F[1][2]*v[199]+F[1][0]*v[274];
8204 v[298]=2e0*F[0][1]*v[160]+F[0][2]*v[199]+F[0][0]*v[274];
8205 v[158]=v[135]*v[151]+v[172]-v[354];
8206 v[297]=2e0*F[0][1]*v[158]+F[0][2]*v[198]+F[0][0]*v[270];
8207 v[295]=F[0][2]*v[190]+F[0][0]*v[261]+2e0*F[0][1]*(v[133]*v[151]+v[155]-v[355]);
8208 v[148]=v[137]*v[140]+v[175]-v[356];
8209 v[324]=2e0*F[1][2]*v[148]+F[1][1]*v[203]+F[1][0]*v[238];
8210 v[306]=2e0*F[0][2]*v[148]+F[0][1]*v[203]+F[0][0]*v[238];
8211 v[147]=v[136]*v[140]+v[159]-v[357];
8212 v[323]=2e0*F[1][2]*v[147]+F[1][1]*v[199]+F[1][0]*v[235];
8213 v[305]=2e0*F[0][2]*v[147]+F[0][1]*v[199]+F[0][0]*v[235];
8214 v[303]=F[0][1]*v[194]+F[0][0]*v[227]+2e0*F[0][2]*(v[134]*v[140]+v[170]-v[358]);
8215 v[302]=F[0][1]*v[190]+F[0][0]*v[224]+(v[133]*v[140]+v[155]-v[359])*v[366];
8216 v[36]=v[140]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[20]))*v[4])/2e0;
8217 v[321]=2e0*v[36];
8218 v[40]=v[151]*v[37]+((1e0+(*C)*(-1e0+v[15]+v[26]))*v[4])/2e0;
8219 v[315]=2e0*v[40];
8220 v[43]=v[343]*v[37]+((1e0+(*C)*(-1e0+v[20]+v[26]))*v[4])/2e0;
8221 v[308]=2e0*v[43];
8222 v[45]=-2e0*v[139]*v[24]+v[336]*v[37];
8223 v[330]=2e0*F[2][1]*v[162]+F[2][2]*v[207]+F[2][0]*v[283]+v[45];
8224 v[317]=2e0*F[1][1]*v[158]+F[1][2]*v[198]+F[1][0]*v[270]+v[45];
8225 v[294]=F[0][2]*v[189]+F[0][0]*v[257]+v[364]*(v[132]*v[151]+v[167]+v[365])+v[45];
8226 v[46]=-2e0*v[139]*v[22]+v[337]*v[37];
8227 v[328]=2e0*F[2][0]*v[178]+F[2][2]*v[242]+F[2][1]*v[283]+v[46];
8228 v[311]=2e0*F[1][0]*v[173]+F[1][2]*v[231]+F[1][1]*v[270]+v[46];
8229 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];
8230 v[47]=-2e0*v[139]*v[18]+v[338]*v[37];
8231 v[327]=2e0*F[2][0]*v[176]+F[2][2]*v[238]+F[2][1]*v[278]+v[47];
8232 v[310]=2e0*F[1][0]*v[171]+F[1][2]*v[227]+F[1][1]*v[265]+v[47];
8233 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]*
8234 (2e0*F[0][2]*v[18]+2e0*v[255]-2e0*v[22]*v[66]));
8235 Pmat[0][0]=F[0][0]*v[308]+F[0][2]*v[46]+F[0][1]*v[47];
8236 Pmat[0][1]=F[0][1]*v[315]+F[0][2]*v[45]+F[0][0]*v[47];
8237 Pmat[0][2]=F[0][2]*v[321]+F[0][1]*v[45]+F[0][0]*v[46];
8238 Pmat[1][0]=2e0*F[1][0]*v[43]+F[1][2]*v[46]+F[1][1]*v[47];
8239 Pmat[1][1]=2e0*F[1][1]*v[40]+F[1][2]*v[45]+F[1][0]*v[47];
8240 Pmat[1][2]=2e0*F[1][2]*v[36]+F[1][1]*v[45]+F[1][0]*v[46];
8241 Pmat[2][0]=F[2][0]*v[308]+F[2][2]*v[46]+F[2][1]*v[47];
8242 Pmat[2][1]=F[2][1]*v[315]+F[2][2]*v[45]+F[2][0]*v[47];
8243 Pmat[2][2]=F[2][2]*v[321]+F[2][1]*v[45]+F[2][0]*v[46];
8244 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]
8245 +v[129]*v[338]-v[363]);
8246 Amat[0][0][0][1]=v[285];
8247 Amat[0][0][0][2]=v[286];
8248 Amat[0][0][1][0]=v[287];
8249 Amat[0][0][1][1]=v[288];
8250 Amat[0][0][1][2]=v[289];
8251 Amat[0][0][2][0]=v[290];
8252 Amat[0][0][2][1]=v[291];
8253 Amat[0][0][2][2]=v[292];
8254 Amat[0][1][0][0]=v[285];
8255 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]);
8256 Amat[0][1][0][2]=v[294];
8257 Amat[0][1][1][0]=v[295];
8258 Amat[0][1][1][1]=v[296];
8259 Amat[0][1][1][2]=v[297];
8260 Amat[0][1][2][0]=v[298];
8261 Amat[0][1][2][1]=v[299];
8262 Amat[0][1][2][2]=v[300];
8263 Amat[0][2][0][0]=v[286];
8264 Amat[0][2][0][1]=v[294];
8265 Amat[0][2][0][2]=F[0][1]*v[189]+F[0][0]*v[220]+v[321]+v[132]*v[140]*v[366];
8266 Amat[0][2][1][0]=v[302];
8267 Amat[0][2][1][1]=v[303];
8268 Amat[0][2][1][2]=v[304];
8269 Amat[0][2][2][0]=v[305];
8270 Amat[0][2][2][1]=v[306];
8271 Amat[0][2][2][2]=v[307];
8272 Amat[1][0][0][0]=v[287];
8273 Amat[1][0][0][1]=v[295];
8274 Amat[1][0][0][2]=v[302];
8275 Amat[1][0][1][0]=2e0*F[1][0]*v[169]+F[1][2]*v[224]+F[1][1]*v[261]+v[308];
8276 Amat[1][0][1][1]=v[310];
8277 Amat[1][0][1][2]=v[311];
8278 Amat[1][0][2][0]=v[312];
8279 Amat[1][0][2][1]=v[313];
8280 Amat[1][0][2][2]=v[314];
8281 Amat[1][1][0][0]=v[288];
8282 Amat[1][1][0][1]=v[296];
8283 Amat[1][1][0][2]=v[303];
8284 Amat[1][1][1][0]=v[310];
8285 Amat[1][1][1][1]=2e0*F[1][1]*v[157]+F[1][2]*v[194]+F[1][0]*v[265]+v[315];
8286 Amat[1][1][1][2]=v[317];
8287 Amat[1][1][2][0]=v[318];
8288 Amat[1][1][2][1]=v[319];
8289 Amat[1][1][2][2]=v[320];
8290 Amat[1][2][0][0]=v[289];
8291 Amat[1][2][0][1]=v[297];
8292 Amat[1][2][0][2]=v[304];
8293 Amat[1][2][1][0]=v[311];
8294 Amat[1][2][1][1]=v[317];
8295 Amat[1][2][1][2]=2e0*F[1][2]*v[146]+F[1][1]*v[198]+F[1][0]*v[231]+v[321];
8296 Amat[1][2][2][0]=v[323];
8297 Amat[1][2][2][1]=v[324];
8298 Amat[1][2][2][2]=v[325];
8299 Amat[2][0][0][0]=v[290];
8300 Amat[2][0][0][1]=v[298];
8301 Amat[2][0][0][2]=v[305];
8302 Amat[2][0][1][0]=v[312];
8303 Amat[2][0][1][1]=v[318];
8304 Amat[2][0][1][2]=v[323];
8305 Amat[2][0][2][0]=2e0*F[2][0]*v[174]+F[2][2]*v[235]+F[2][1]*v[274]+v[308];
8306 Amat[2][0][2][1]=v[327];
8307 Amat[2][0][2][2]=v[328];
8308 Amat[2][1][0][0]=v[291];
8309 Amat[2][1][0][1]=v[299];
8310 Amat[2][1][0][2]=v[306];
8311 Amat[2][1][1][0]=v[313];
8312 Amat[2][1][1][1]=v[319];
8313 Amat[2][1][1][2]=v[324];
8314 Amat[2][1][2][0]=v[327];
8315 Amat[2][1][2][1]=2e0*F[2][1]*v[161]+F[2][2]*v[203]+F[2][0]*v[278]+v[315];
8316 Amat[2][1][2][2]=v[330];
8317 Amat[2][2][0][0]=v[292];
8318 Amat[2][2][0][1]=v[300];
8319 Amat[2][2][0][2]=v[307];
8320 Amat[2][2][1][0]=v[314];
8321 Amat[2][2][1][1]=v[320];
8322 Amat[2][2][1][2]=v[325];
8323 Amat[2][2][2][0]=v[328];
8324 Amat[2][2][2][1]=v[330];
8325 Amat[2][2][2][2]=2e0*F[2][2]*v[149]+F[2][1]*v[207]+F[2][0]*v[242]+v[321];
8326};
8327
8328
8329/*************************************************************
8330 * AceGen 6.921 MacOSX (29 Jan 19) *
8331 * Co. J. Korelc 2013 17 Jul 19 15:09:55 *
8332 **************************************************************
8333 User : Full professional version
8334 Notebook : st_venant_kirchhoff_3d
8335 Evaluation time : 3 s Mode : Optimal
8336 Number of formulae : 91 Method: Automatic
8337 Subroutine : stvk3d size: 2846
8338 Total size of Mathematica code : 2846 subexpressions
8339 Total size of C code : 5830 bytes */
8340
8341/******************* S U B R O U T I N E *********************/
8342template <class SC, class LO, class GO, class NO>
8343void FE<SC,LO,GO,NO>::stvk3d(double* v,double (*lam),double (*mue),double** F
8344 ,double** Pmat,double**** Amat)
8345{
8346 v[169]=Power(F[0][0],2);
8347 v[168]=2e0*(*mue);
8348 v[167]=Power(F[0][2],2);
8349 v[166]=F[2][2]*(*mue);
8350 v[165]=F[2][1]*(*mue);
8351 v[164]=F[2][0]*(*mue);
8352 v[163]=F[1][2]*(*mue);
8353 v[162]=F[1][1]*(*mue);
8354 v[161]=F[1][0]*(*mue);
8355 v[88]=F[0][0]*(*mue);
8356 v[116]=F[0][0]*v[88];
8357 v[70]=F[0][1]*(*lam);
8358 v[93]=F[0][1]*(*mue);
8359 v[117]=F[0][1]*v[93];
8360 v[71]=F[0][2]*(*lam);
8361 v[105]=(*mue)*v[167];
8362 v[72]=F[1][0]*(*lam);
8363 v[85]=2e0*v[161]+v[72];
8364 v[142]=F[1][0]*v[161];
8365 v[121]=F[0][0]*v[161];
8366 v[73]=F[1][1]*(*lam);
8367 v[100]=F[0][1]*v[161]+F[0][0]*v[73];
8368 v[82]=2e0*v[162]+v[73];
8369 v[143]=F[1][1]*v[162];
8370 v[122]=F[0][1]*v[162];
8371 v[108]=F[0][0]*v[162]+F[0][1]*v[72];
8372 v[74]=F[1][2]*(*lam);
8373 v[111]=F[0][2]*v[162]+F[0][1]*v[74];
8374 v[101]=F[0][2]*v[161]+F[0][0]*v[74];
8375 v[79]=2e0*v[163]+v[74];
8376 v[123]=v[121]+v[122]+F[0][2]*v[79];
8377 v[135]=F[1][2]*v[163];
8378 v[120]=F[0][1]*v[163]+F[0][2]*v[73];
8379 v[119]=F[0][0]*v[163]+F[0][2]*v[72];
8380 v[109]=F[0][2]*v[163];
8381 v[110]=v[109]+v[121]+F[0][1]*v[82];
8382 v[99]=v[109]+v[122]+F[0][0]*v[85];
8383 v[75]=F[2][0]*(*lam);
8384 v[86]=2e0*v[164]+v[75];
8385 v[156]=F[2][0]*v[164];
8386 v[147]=F[1][0]*v[164];
8387 v[126]=F[0][0]*v[164];
8388 v[76]=F[2][1]*(*lam);
8389 v[133]=F[1][1]*v[164]+F[1][0]*v[76];
8390 v[103]=F[0][1]*v[164]+F[0][0]*v[76];
8391 v[83]=2e0*v[165]+v[76];
8392 v[157]=F[2][1]*v[165];
8393 v[148]=F[1][1]*v[165];
8394 v[138]=F[1][0]*v[165]+F[1][1]*v[75];
8395 v[127]=F[0][1]*v[165];
8396 v[112]=F[0][0]*v[165]+F[0][1]*v[75];
8397 v[77]=F[2][2]*(*lam);
8398 v[141]=F[1][2]*v[165]+F[1][1]*v[77];
8399 v[134]=F[1][2]*v[164]+F[1][0]*v[77];
8400 v[115]=F[0][2]*v[165]+F[0][1]*v[77];
8401 v[104]=F[0][2]*v[164]+F[0][0]*v[77];
8402 v[80]=2e0*v[166]+v[77];
8403 v[149]=v[147]+v[148]+F[1][2]*v[80];
8404 v[128]=v[126]+v[127]+F[0][2]*v[80];
8405 v[153]=F[2][2]*v[166];
8406 v[146]=F[1][1]*v[166]+F[1][2]*v[76];
8407 v[145]=F[1][0]*v[166]+F[1][2]*v[75];
8408 v[139]=F[1][2]*v[166];
8409 v[140]=v[139]+v[147]+F[1][1]*v[83];
8410 v[132]=v[139]+v[148]+F[1][0]*v[86];
8411 v[125]=F[0][1]*v[166]+F[0][2]*v[76];
8412 v[124]=F[0][0]*v[166]+F[0][2]*v[75];
8413 v[113]=F[0][2]*v[166];
8414 v[114]=v[113]+v[126]+F[0][1]*v[83];
8415 v[102]=v[113]+v[127]+F[0][0]*v[86];
8416 v[24]=(-1e0+Power(F[1][0],2)+Power(F[2][0],2)+v[169])/2e0;
8417 v[28]=(-1e0+Power(F[0][1],2)+Power(F[1][1],2)+Power(F[2][1],2))/2e0;
8418 v[32]=(-1e0+Power(F[1][2],2)+Power(F[2][2],2)+v[167])/2e0;
8419 v[36]=(*lam)*(v[24]+v[28]+v[32]);
8420 v[35]=2e0*(*mue)*v[32]+v[36];
8421 v[37]=2e0*(*mue)*v[28]+v[36];
8422 v[38]=2e0*(*mue)*v[24]+v[36];
8423 v[39]=(F[0][0]*F[0][2]+F[1][0]*F[1][2]+F[2][0]*F[2][2])*(*mue);
8424 v[152]=F[2][2]*v[164]+v[39]+F[2][0]*v[77];
8425 v[131]=F[1][2]*v[161]+v[39]+F[1][0]*v[74];
8426 v[98]=v[39]+F[0][0]*v[71]+F[0][2]*v[88];
8427 v[40]=(F[0][1]*F[0][2]+F[1][1]*F[1][2]+F[2][1]*F[2][2])*(*mue);
8428 v[155]=F[2][2]*v[165]+v[40]+F[2][1]*v[77];
8429 v[137]=F[1][2]*v[162]+v[40]+F[1][1]*v[74];
8430 v[107]=v[40]+F[0][1]*v[71]+F[0][2]*v[93];
8431 v[41]=(F[0][0]*F[0][1]+F[1][0]*F[1][1]+F[2][0]*F[2][1])*(*mue);
8432 v[151]=F[2][1]*v[164]+v[41]+F[2][0]*v[76];
8433 v[130]=F[1][1]*v[161]+v[41]+F[1][0]*v[73];
8434 v[97]=v[41]+F[0][0]*v[70]+F[0][1]*v[88];
8435 Pmat[0][0]=F[0][0]*v[38]+F[0][2]*v[39]+F[0][1]*v[41];
8436 Pmat[0][1]=F[0][1]*v[37]+F[0][2]*v[40]+F[0][0]*v[41];
8437 Pmat[0][2]=F[0][2]*v[35]+F[0][0]*v[39]+F[0][1]*v[40];
8438 Pmat[1][0]=F[1][0]*v[38]+F[1][2]*v[39]+F[1][1]*v[41];
8439 Pmat[1][1]=F[1][1]*v[37]+F[1][2]*v[40]+F[1][0]*v[41];
8440 Pmat[1][2]=F[1][2]*v[35]+F[1][0]*v[39]+F[1][1]*v[40];
8441 Pmat[2][0]=F[2][0]*v[38]+F[2][2]*v[39]+F[2][1]*v[41];
8442 Pmat[2][1]=F[2][1]*v[37]+F[2][2]*v[40]+F[2][0]*v[41];
8443 Pmat[2][2]=F[2][2]*v[35]+F[2][0]*v[39]+F[2][1]*v[40];
8444 Amat[0][0][0][0]=v[105]+v[117]+((*lam)+v[168])*v[169]+v[38];
8445 Amat[0][0][0][1]=v[97];
8446 Amat[0][0][0][2]=v[98];
8447 Amat[0][0][1][0]=v[99];
8448 Amat[0][0][1][1]=v[100];
8449 Amat[0][0][1][2]=v[101];
8450 Amat[0][0][2][0]=v[102];
8451 Amat[0][0][2][1]=v[103];
8452 Amat[0][0][2][2]=v[104];
8453 Amat[0][1][0][0]=v[97];
8454 Amat[0][1][0][1]=v[105]+v[116]+v[37]+F[0][1]*(v[70]+2e0*v[93]);
8455 Amat[0][1][0][2]=v[107];
8456 Amat[0][1][1][0]=v[108];
8457 Amat[0][1][1][1]=v[110];
8458 Amat[0][1][1][2]=v[111];
8459 Amat[0][1][2][0]=v[112];
8460 Amat[0][1][2][1]=v[114];
8461 Amat[0][1][2][2]=v[115];
8462 Amat[0][2][0][0]=v[98];
8463 Amat[0][2][0][1]=v[107];
8464 Amat[0][2][0][2]=v[116]+v[117]+v[35]+F[0][2]*(F[0][2]*v[168]+v[71]);
8465 Amat[0][2][1][0]=v[119];
8466 Amat[0][2][1][1]=v[120];
8467 Amat[0][2][1][2]=v[123];
8468 Amat[0][2][2][0]=v[124];
8469 Amat[0][2][2][1]=v[125];
8470 Amat[0][2][2][2]=v[128];
8471 Amat[1][0][0][0]=v[99];
8472 Amat[1][0][0][1]=v[108];
8473 Amat[1][0][0][2]=v[119];
8474 Amat[1][0][1][0]=v[135]+v[143]+v[38]+F[1][0]*v[85];
8475 Amat[1][0][1][1]=v[130];
8476 Amat[1][0][1][2]=v[131];
8477 Amat[1][0][2][0]=v[132];
8478 Amat[1][0][2][1]=v[133];
8479 Amat[1][0][2][2]=v[134];
8480 Amat[1][1][0][0]=v[100];
8481 Amat[1][1][0][1]=v[110];
8482 Amat[1][1][0][2]=v[120];
8483 Amat[1][1][1][0]=v[130];
8484 Amat[1][1][1][1]=v[135]+v[142]+v[37]+F[1][1]*v[82];
8485 Amat[1][1][1][2]=v[137];
8486 Amat[1][1][2][0]=v[138];
8487 Amat[1][1][2][1]=v[140];
8488 Amat[1][1][2][2]=v[141];
8489 Amat[1][2][0][0]=v[101];
8490 Amat[1][2][0][1]=v[111];
8491 Amat[1][2][0][2]=v[123];
8492 Amat[1][2][1][0]=v[131];
8493 Amat[1][2][1][1]=v[137];
8494 Amat[1][2][1][2]=v[142]+v[143]+v[35]+F[1][2]*v[79];
8495 Amat[1][2][2][0]=v[145];
8496 Amat[1][2][2][1]=v[146];
8497 Amat[1][2][2][2]=v[149];
8498 Amat[2][0][0][0]=v[102];
8499 Amat[2][0][0][1]=v[112];
8500 Amat[2][0][0][2]=v[124];
8501 Amat[2][0][1][0]=v[132];
8502 Amat[2][0][1][1]=v[138];
8503 Amat[2][0][1][2]=v[145];
8504 Amat[2][0][2][0]=v[153]+v[157]+v[38]+F[2][0]*v[86];
8505 Amat[2][0][2][1]=v[151];
8506 Amat[2][0][2][2]=v[152];
8507 Amat[2][1][0][0]=v[103];
8508 Amat[2][1][0][1]=v[114];
8509 Amat[2][1][0][2]=v[125];
8510 Amat[2][1][1][0]=v[133];
8511 Amat[2][1][1][1]=v[140];
8512 Amat[2][1][1][2]=v[146];
8513 Amat[2][1][2][0]=v[151];
8514 Amat[2][1][2][1]=v[153]+v[156]+v[37]+F[2][1]*v[83];
8515 Amat[2][1][2][2]=v[155];
8516 Amat[2][2][0][0]=v[104];
8517 Amat[2][2][0][1]=v[115];
8518 Amat[2][2][0][2]=v[128];
8519 Amat[2][2][1][0]=v[134];
8520 Amat[2][2][1][1]=v[141];
8521 Amat[2][2][1][2]=v[149];
8522 Amat[2][2][2][0]=v[152];
8523 Amat[2][2][2][1]=v[155];
8524 Amat[2][2][2][2]=v[156]+v[157]+v[35]+F[2][2]*v[80];
8525};
8526/*************************************************************
8527 * AceGen 6.921 MacOSX (29 Jan 19) *
8528 * Co. J. Korelc 2013 17 Jul 19 16:01:42 *
8529 **************************************************************
8530 User : Full professional version
8531 Notebook : st_venant_kirchhoff_2d
8532 Evaluation time : 1 s Mode : Optimal
8533 Number of formulae : 25 Method: Automatic
8534 Subroutine : stvk2d size: 772
8535 Total size of Mathematica code : 772 subexpressions
8536 Total size of C code : 1672 bytes */
8537
8538
8539/******************* S U B R O U T I N E *********************/
8540template <class SC, class LO, class GO, class NO>
8541void FE<SC,LO,GO,NO>::stvk2d(double* v, double (*lam),double (*mue),double** F
8542 ,double** Pmat,double**** Amat)
8543{
8544 v[43]=F[0][0]*F[1][0];
8545 v[42]=F[0][1]*F[1][1];
8546 v[37]=Power(F[0][0],2);
8547 v[12]=F[0][0]/2e0;
8548 v[36]=Power(F[0][1],2);
8549 v[34]=F[0][0]*F[0][1];
8550 v[11]=F[0][1]/2e0;
8551 v[27]=Power(F[1][0],2);
8552 v[31]=-1e0+v[27]+v[37];
8553 v[14]=F[1][0]/2e0;
8554 v[25]=Power(F[1][1],2);
8555 v[26]=-1e0+v[25]+v[36];
8556 v[23]=F[1][0]*F[1][1];
8557 v[22]=v[23]+v[34];
8558 v[35]=(*lam)*v[34]+(*mue)*(v[22]+v[34]);
8559 v[24]=(*lam)*v[23]+(*mue)*(v[22]+v[23]);
8560 v[21]=(*lam)*v[42]+2e0*(*mue)*(2e0*v[12]*v[14]+v[42]);
8561 v[20]=F[0][0]*F[1][1]*(*lam)+4e0*(*mue)*v[11]*v[14];
8562 v[13]=F[1][1]/2e0;
8563 v[30]=F[0][1]*F[1][0]*(*lam)+4e0*(*mue)*v[12]*v[13];
8564 v[29]=(*lam)*v[43]+2e0*(*mue)*(2e0*v[11]*v[13]+v[43]);
8565 v[44]=2e0*v[22];
8566 v[32]=((*lam)*(v[26]+v[31]))/2e0;
8567 Pmat[0][0]=F[0][0]*v[32]+(*mue)*(F[0][0]*v[31]+v[11]*v[44]);
8568 Pmat[0][1]=F[0][1]*v[32]+(*mue)*(F[0][1]*v[26]+v[12]*v[44]);
8569 Pmat[1][0]=F[1][0]*v[32]+(*mue)*(F[1][0]*v[31]+v[13]*v[44]);
8570 Pmat[1][1]=F[1][1]*v[32]+(*mue)*(F[1][1]*v[26]+v[14]*v[44]);
8571 Amat[0][0][0][0]=v[32]+(*lam)*v[37]+(*mue)*(v[31]+v[36]+2e0*v[37]);
8572 Amat[0][0][0][1]=v[35];
8573 Amat[0][0][1][0]=v[29];
8574 Amat[0][0][1][1]=v[20];
8575 Amat[0][1][0][0]=v[35];
8576 Amat[0][1][0][1]=v[32]+(*lam)*v[36]+(*mue)*(v[26]+2e0*v[36]+v[37]);
8577 Amat[0][1][1][0]=v[30];
8578 Amat[0][1][1][1]=v[21];
8579 Amat[1][0][0][0]=v[29];
8580 Amat[1][0][0][1]=v[30];
8581 Amat[1][0][1][0]=(*lam)*v[27]+(*mue)*(v[25]+2e0*v[27]+v[31])+v[32];
8582 Amat[1][0][1][1]=v[24];
8583 Amat[1][1][0][0]=v[20];
8584 Amat[1][1][0][1]=v[21];
8585 Amat[1][1][1][0]=v[24];
8586 Amat[1][1][1][1]=(*lam)*v[25]+(*mue)*(2e0*v[25]+v[26]+v[27])+v[32];
8587};
8588
8589}
8590#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:7013
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:3883
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:3970
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:4459
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:824
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:451
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:364
void assemblyBDStabilization(int dim, std::string FEType, MatrixPtr_Type &A, bool callFillComplete=true)
Bochev- Dohrmann Stabilization.
Definition FE_def.hpp:4194
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:4100
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:7477
void assemblyLaplaceXDim(int dim, std::string FEType, MatrixPtr_Type &A, CoeffFuncDbl_Type func, double *parameters, bool callFillComplete=true)
Definition FE_def.hpp:4277
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:3698
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:3792
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:1254
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:5149
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:2737
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:5461
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:1080
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:1865
void assemblyLinElasXDim(int dim, std::string FEType, MatrixPtr_Type &A, double lambda, double mu, bool callFillComplete=true)
Definition FE_def.hpp:4793
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:646
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