OOFEM 3.0
Loading...
Searching...
No Matches
tet21ghostsolid.C
Go to the documentation of this file.
1/*
2 *
3 * ##### ##### ###### ###### ### ###
4 * ## ## ## ## ## ## ## ### ##
5 * ## ## ## ## #### #### ## # ##
6 * ## ## ## ## ## ## ## ##
7 * ## ## ## ## ## ## ## ##
8 * ##### ##### ## ###### ## ##
9 *
10 *
11 * OOFEM : Object Oriented Finite Element Code
12 *
13 * Copyright (C) 1993 - 2025 Borek Patzak
14 *
15 *
16 *
17 * Czech Technical University, Faculty of Civil Engineering,
18 * Department of Structural Mechanics, 166 29 Prague, Czech Republic
19 *
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
29 *
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
33 */
34
38#include "fei3dtetquad.h"
39#include "fei3dtetlin.h"
40#include "classfactory.h"
41#include "gausspoint.h"
43#include "load.h"
44#include "element.h"
45#include "dofmanager.h"
46#include "load.h"
47#include "bodyload.h"
48#include "boundaryload.h"
49#include "neumannmomentload.h"
50#include "dof.h"
51#include "mathfem.h"
52
53#include <iostream>
54
55#ifdef __FM_MODULE
57 #include "fluidcrosssection.h"
58#endif
59
60namespace oofem {
61#define FIXEDJ 0
62#define FIXEDFinvT 0
63#define FIXEDpressure 0
64#define USEUNCOUPLED 1
65#define USENUMTAN 0
66#define TESTTANGENT 0
67
68#define VELOCITYCOEFF 1.0
69
71
74
79 1, 2, 3, 8, 9, 10, 15, 16, 17, 22, 23, 24, 28, 29, 30, 34, 35, 36
80};
82 4, 5, 6, 11, 12, 13, 18, 19, 20, 25, 26, 27, 31, 32, 33, 37, 38, 39
83};
84
86{
88 numberOfDofMans = 10;
89 computeItransform = true;
90
91 double nu = .25, E = 1;
92 Dghost.resize(6, 6);
93 Dghost.zero();
94 Dghost.at(1, 1) = 1 - nu;
95 Dghost.at(1, 2) = Dghost.at(1, 3) = nu;
96 Dghost.at(2, 2) = 1 - nu;
97 Dghost.at(2, 1) = Dghost.at(2, 3) = nu;
98 Dghost.at(3, 3) = 1 - nu;
99 Dghost.at(3, 1) = Dghost.at(3, 2) = nu;
100 Dghost.at(4, 4) = Dghost.at(5, 5) = Dghost.at(6, 6) = .5 * ( 1 - 2 * nu );
101 Dghost.times(E / ( 1 + nu ) / ( 1 - 2 * nu ) );
102
104 7, 14, 21, 28
105 };
106
107 for ( int i = 0, j = 1; i < 10; ++i ) {
108 momentum_ordering [ i * 3 + 0 ] = j++;
109 momentum_ordering [ i * 3 + 1 ] = j++;
110 momentum_ordering [ i * 3 + 2 ] = j++;
111 if ( i <= 3 ) {
112 j++;
113 }
114 j += 3;
115 }
116
117 for ( int i = 0, j = 1; i < 10; ++i ) {
118 j += 3;
119 ghostdisplacement_ordering [ i * 3 + 0 ] = j++;
120 ghostdisplacement_ordering [ i * 3 + 1 ] = j++;
121 ghostdisplacement_ordering [ i * 3 + 2 ] = j++;
122 if ( i <= 3 ) {
123 j++;
124 }
125 }
126}
127
130{
131 return & interpolation;
132}
133
136{
137 if ( id == P_f ) {
138 return & interpolation_lin;
139 } else {
140 return & interpolation;
141 }
142}
143
144void
146// Sets up the array containing the four Gauss points of the receiver.
147{
148 if ( integrationRulesArray.size() == 0 ) {
149 integrationRulesArray.resize(1);
150 integrationRulesArray [ 0 ] = std::make_unique< GaussIntegrationRule >(1, this, 1, 6);
152 }
153}
154
155void
157{
158 FloatArray a, aPert, intF, intFPert, DintF;
159 double eps = 1e-9;
160
161 answer.resize(64, 64);
162 answer.zero();
163
164 this->computeVectorOf(VM_Total, tStep, a);
165
166 giveInternalForcesVectorGivenSolution(intF, tStep, 0, a);
167
168 for ( int i = 1; i <= answer.giveNumberOfColumns(); i++ ) {
169 aPert = a;
170 aPert.at(i) = aPert.at(i) + eps;
171
172 giveInternalForcesVectorGivenSolution(intFPert, tStep, 0, aPert);
173
174 DintF.operator=(intF - intFPert);
175 DintF.times(-1 / eps);
176 answer.setColumn(DintF, i);
177 }
178}
179
180void
182{
183 FloatArray a, aPert, intF, intFPert, DintF;
184 double eps = 1e-9;
185
186 answer.resize(64, 64);
187 answer.zero();
188
189 this->computeVectorOf(VM_Total, tStep, a);
190
191 giveInternalForcesVectorGivenSolutionDebug(intF, tStep, 0, a, true);
192
193 for ( int i = 1; i <= answer.giveNumberOfColumns(); i++ ) {
194 aPert = a;
195 aPert.at(i) = aPert.at(i) + eps;
196
197 giveInternalForcesVectorGivenSolutionDebug(intFPert, tStep, 0, aPert, false);
198
199 DintF.operator=(intF - intFPert);
200 DintF.times(-1 / eps);
201 answer.setColumn(DintF, i);
202 }
203}
204
205
206void
208{
209 answer = this->giveStructuralCrossSection()->giveRealStress_3d(strain, gp, tStep);
210}
211
212void
214{
215 answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_3d(rMode, gp, tStep);
216}
217
218
219void
221{
222 answer = this->giveStructuralCrossSection()->giveStiffnessMatrix_dPdF_3d(rMode, gp, tStep);
223}
224
225void
226tet21ghostsolid::computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
227{
228#ifdef __FM_MODULE
229 #if USENUMTAN == 1
230 computeNumericStiffnessMatrix(answer, rMode, tStep);
231 return;
232
233 #endif
234
235 FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
236
237 FloatMatrix afDu, afDw, bfuDu, bfuDp, bfpDu, bfpDw, cfwDu;
238 FloatMatrix Kf, G, Kx, Ed, EdB, dNx;
239 FloatArray Nlin, dNv, a, a_prev, a_inc;
240 FloatArray aVelocity, aPressure, aGhostDisplacement, aIncGhostDisplacement;
241
242 afDu.resize(30, 30);
243 afDu.zero();
244 bfuDu.resize(30, 30); // Remove?
245 bfuDu.zero();
246 bfuDp.resize(30, 4);
247 bfuDp.zero();
248 bfpDu.resize(4, 30);
249 bfpDu.zero();
250 bfpDw.resize(4, 30);
251 bfpDw.zero();
252 cfwDu.resize(30, 30);
253 cfwDu.zero();
254
255 this->computeVectorOf(VM_Total, tStep, a);
256 if ( !tStep->isTheFirstStep() ) {
257 this->computeVectorOf(VM_Total, tStep->givePreviousStep(), a_prev);
258 } else {
259 a_prev.resize(a.giveSize() );
260 a_prev.zero();
261 }
262 a_inc.operator=(a - a_prev);
263
264 aVelocity.beSubArrayOf(a, momentum_ordering);
266 aGhostDisplacement.beSubArrayOf(a, ghostdisplacement_ordering);
267 aIncGhostDisplacement.beSubArrayOf(a_inc, ghostdisplacement_ordering);
268
269 FloatArray aTotal;
270 aTotal.operator=(aVelocity + aIncGhostDisplacement * VELOCITYCOEFF); // Assume deltaT=1 gives that the increment is the velocity
271
272 for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) {
273 // gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0);
274 const FloatArray &lcoords = gp->giveNaturalCoordinates();
275 double detJ = fabs( ( this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ) );
276 double weight = gp->giveWeight();
277
278 this->interpolation.evaldNdx(dNx, lcoords, FEIElementGeometryWrapper(this) );
279 this->interpolation_lin.evalN(Nlin, lcoords, FEIElementGeometryWrapper(this) );
280
281 // Move to small deformations
282 dNv.resize(30); // dNv = [dN1/dx dN1/dy dN1/dz dN2/dx dN2/dy dN2/dz ... dN10/dz]
283 for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) {
284 dNv.at(k * 3 + 1) = dNx.at(k + 1, 1);
285 dNv.at(k * 3 + 2) = dNx.at(k + 1, 2);
286 dNv.at(k * 3 + 3) = dNx.at(k + 1, 3);
287 }
288
289 gp->setMaterialMode(_3dFlow);
290 Ed = fluidMaterial->computeTangent3D(TangentStiffness, gp, tStep);
291 gp->setMaterialMode(_3dMat);
292
293 if ( nlGeometry == 0 ) {
294 FloatMatrix B;
295 this->computeBmatrixAt(gp, B);
296
297 // Fluid part
298 EdB.beProductOf(Ed, B);
299 Kf.plusProductSymmUpper(B, EdB, detJ * weight);
300 Kf.symmetrized();
301
302 // Ghost solid part
303 Kx.plusProductSymmUpper(B, EdB, detJ * weight);
304
305 // Incompressibility part
306 G.plusDyadUnsym(dNv, Nlin, -detJ * weight);
307 } else {
308 int Voigt6[ 3 ] [ 3 ] = { { 1, 6, 5 }, { 6, 2, 4 }, { 5, 4, 3 } };
309 int Voigt9[ 3 ] [ 3 ] = { { 1, 6, 5 }, { 9, 2, 4 }, { 8, 7, 3 } };
310
311 // Compute commonly used matrices
312 FloatArray Fa, Finva, FinvTa;
313 FloatMatrix F, Finv, FinvT, BH, B;
314
315 this->computeBHmatrixAt(gp, BH);
316 this->computeBmatrixAt(gp, B);
317
318 computeDeformationGradientVectorFromDispl(Fa, gp, tStep, aGhostDisplacement);
319 F.beMatrixForm(Fa);
320 Finv.beInverseOf(F);
321 Finva.beVectorForm(Finv);
322 FinvT.beTranspositionOf(Finv);
323 FinvTa.beVectorForm(FinvT);
324
325 FloatArray FinvTaB;
326 FinvTaB.beTProductOf(BH, FinvTa);
327
328 FloatMatrix NlinFinvTaB;
329 NlinFinvTaB.beDyadicProductOf(Nlin, FinvTaB);
330
331 double J = F.giveDeterminant();
332 #if FIXEDJ == 1
333 J = 1;
334 #endif
335
336 // Compute Cauchy stress
337 FloatArray fluidCauchyArray, epsf;
338 FloatMatrix fluidCauchyMatrix;
339 double pressure;
340
341 epsf.beProductOf(B, aTotal);
342 pressure = Nlin.dotProduct(aPressure);
343
344 #if FIXEDpressure == 1
345 pressure = 1.0;
346 #endif
347
348 gp->setMaterialMode(_3dFlow);
349 auto stress_eps = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep);
350 fluidCauchyArray = stress_eps.first;
351 gp->setMaterialMode(_3dMat);
352 fluidCauchyMatrix.beMatrixFormOfStress(fluidCauchyArray);
353
354 // afDu terms ==========
355 // 1st term ------------
356 FloatArray fluidTwoPointStressArray, BTS;
357 FloatMatrix fluidTwoPointStressMatrix, afuT1;
358
359 fluidTwoPointStressMatrix.beProductOf(fluidCauchyMatrix, FinvT);
360 fluidTwoPointStressArray.beVectorForm(fluidTwoPointStressMatrix);
361
362 BTS.beTProductOf(BH, fluidTwoPointStressArray);
363
364 afuT1.beDyadicProductOf(BTS, FinvTaB);
365 afuT1.times(J * weight * detJ);
366 #if FIXEDJ == 1
367 afuT1.times(0.0);
368 #endif
369 afDu.add(afuT1);
370
371 // 2nd term ------------ // Works
372 FloatMatrix afuT2;
373 FloatMatrix G, BTG;
374
375 G.resize(9, 9);
376 G.zero();
377
378 for ( int i = 1; i <= 3; i++ ) {
379 for ( int j = 1; j <= 3; j++ ) {
380 for ( int k = 1; k <= 3; k++ ) {
381 for ( int l = 1; l <= 3; l++ ) {
382 for ( int m = 1; m <= 3; m++ ) {
383 G.at(Voigt9 [ i - 1 ] [ j - 1 ], Voigt9 [ k - 1 ] [ l - 1 ]) +=
384 Ed.at(Voigt6 [ i - 1 ] [ m - 1 ], Voigt6 [ k - 1 ] [ l - 1 ]) * FinvT.at(m, j);
385 }
386 }
387 }
388 }
389 }
390
391 BTG.beTProductOf(BH, G);
392 afuT2.beProductOf(BTG, BH);
393 afuT2.times(J * weight * detJ);
394
395 afDu.add(afuT2);
396
397 // 3rd term ------------
398 FloatMatrix afuT3;
399 FloatMatrix K, BTK;
400
401 K.resize(9, 9);
402 K.zero();
403
404 for ( int i = 1; i <= 3; i++ ) {
405 for ( int j = 1; j <= 3; j++ ) {
406 for ( int k = 1; k <= 3; k++ ) {
407 for ( int l = 1; l <= 3; l++ ) {
408 for ( int m = 1; m <= 3; m++ ) {
409 K.at(Voigt9 [ i - 1 ] [ j - 1 ], Voigt9 [ m - 1 ] [ l - 1 ]) +=
410 fluidCauchyArray.at(Voigt6 [ i - 1 ] [ k - 1 ]) * FinvT.at(k, l) * FinvT.at(m, j);
411 }
412 }
413 }
414 }
415 }
416
417 BTK.beTProductOf(BH, K);
418 afuT3.beProductOf(BTK, BH);
419 afuT3.times(-J * weight * detJ);
420 #if FIXEDFinvT == 1
421 afuT3.times(0.0);
422 #endif
423 afDu.add(afuT3);
424
425 // afDw terms ========== // Works
426 afDw.add(afuT2);
427
428 // bfuDu term ==========
429 // 1st term ------------ // Works
430 FloatMatrix bfuT1;
431 bfuT1.beDyadicProductOf(FinvTaB, FinvTaB);
432 bfuT1.times(-J * pressure * weight * detJ);
433
434 bfuDu.add(bfuT1);
435
436 // 2nd term ------------ // Works
437 FloatMatrix C, bfuT2, BTC;
438 C.resize(9, 9);
439 C.zero();
440
441 for ( int i = 1; i <= 3; i++ ) {
442 for ( int j = 1; j <= 3; j++ ) {
443 for ( int k = 1; k <= 3; k++ ) {
444 for ( int l = 1; l <= 3; l++ ) {
445 C.at(Voigt9 [ i - 1 ] [ j - 1 ], Voigt9 [ k - 1 ] [ l - 1 ]) +=
446 FinvT.at(i, l) * FinvT.at(k, j);
447 }
448 }
449 }
450 }
451
452 BTC.beTProductOf(BH, C);
453 bfuT2.beProductOf(BTC, BH);
454 bfuT2.times(pressure * J * weight * detJ);
455
456 bfuDu.add(bfuT2);
457
458 // bfuDp term ========== // Works
459 FloatMatrix bfuT3;
460 bfuT3.beDyadicProductOf(FinvTaB, Nlin);
461 bfuT3.times(-J * detJ * weight);
462
463 bfuDp.add(bfuT3);
464
465 // bfpDu term ==========
466 // 1st term ------------
467 FloatMatrix bfpT1, A_IVm, Bvm;
468 FloatArray A_IVa, Bv;
469
470 Bv.beProductOf(BH, aTotal);
471 Bvm.beMatrixForm(Bv);
472 double FinvTaBv = FinvTa.dotProduct(Bv);
473
474 A_IVm.resize(3, 3);
475 A_IVm.zero();
476
477 for ( int k = 1; k <= 3; k++ ) {
478 for ( int l = 1; l <= 3; l++ ) {
479 for ( int i = 1; i <= 3; i++ ) {
480 for ( int j = 1; j <= 3; j++ ) {
481 A_IVm.at(k, l) += Bvm.at(i, j) * FinvT.at(i, l) * FinvT.at(k, j);
482 }
483 }
484 }
485 }
486
487 A_IVa.beVectorForm(A_IVm);
488
489 bfpT1 = NlinFinvTaB;
490 bfpT1.times(-J * detJ * weight * FinvTaBv);
491 #if FIXEDJ == 1
492 bfpT1.times(0.0);
493 #endif
494
495 bfpDu.add(bfpT1);
496
497 // 2nd term ------------
498 FloatMatrix bfpT2;
499 FloatArray AiiB;
500
501 AiiB.beTProductOf(BH, A_IVa);
502 bfpT2.beDyadicProductOf(Nlin, AiiB);
503 bfpT2.times(J * detJ * weight);
504 #if FIXEDFinvT == 1
505 bfpT2.times(0.0);
506 #endif
507 bfpDu.add(bfpT2);
508
509
510 // 3rd term ------------ // Works
511 FloatMatrix bfpT3;
512 bfpT3 = NlinFinvTaB;
513 bfpT3.times(-J * detJ * weight);
514 bfpDu.add(bfpT3);
515
516 // bfpDw term ========== // Works
517 // bfpT1 = NlinFinvTaB;
518 // bfpT1.times(-J*detJ*weight);
519 bfpDw.add(bfpT3);
520
521 // cfwDu term ========== // Works
522 FloatMatrix BTEX, cfwT1;
523 BTEX.beTProductOf(B, Dghost);
524 cfwT1.beProductOf(BTEX, B);
525 cfwT1.times(detJ * weight);
526
527 cfwDu.add(cfwT1);
528 }
529 }
530
531 //if (this->globalNumber == 373) { dJda.printYourself("dJda_analytical"); }
532 FloatMatrix GT, temp;
533
534 GT.beTranspositionOf(G);
535 Kf.symmetrized();
536 Kx.symmetrized();
537
538 answer.resize(64, 64);
539 answer.zero();
540 temp.resize(64, 64);
541 temp.zero();
542
550
551 if ( this->computeItransform ) {
553 }
554
555 answer.beProductOf(Itransform, temp);
556
557 // ******************* This is for development purposes only. Compare to numerical stiffness tangent
558 #if TESTTANGENT
559 if ( ( this->globalNumber == 292 ) && ( tStep->giveNumber() > 0 ) ) {
560 double MaxErr = 0.0;
561 FloatMatrix numtan;
562 int imax, jmax;
563
564 temp.zero();
572
573 computeNumericStiffnessMatrixDebug(numtan, rMode, tStep);
574 for ( int i = 1; i <= numtan.giveNumberOfRows(); i++ ) {
575 for ( int j = 1; j <= numtan.giveNumberOfRows(); j++ ) {
576 double difference = numtan.at(i, j) - temp.at(i, j);
577 if ( fabs(difference) > fabs(MaxErr) ) {
578 MaxErr = difference;
579 imax = i;
580 jmax = j;
581 }
582 if ( fabs(numtan.at(i, j) < 1e-15) ) {
583 numtan.at(i, j) = 0.0;
584 }
585 if ( fabs(temp.at(i, j) < 1e-15) ) {
586 temp.at(i, j) = 0.0;
587 }
588 }
589 }
590
591 printf("globalNumber: %u, i:%u, j:%u, MaxErr: %e, Numtan=%f, Analytic=%f\n", this->globalNumber, imax, jmax, MaxErr, numtan.at(imax, jmax), temp.at(imax, jmax) );
592
593 numtan.printYourselfToFile("/tmp/numtan.txt", false);
594 temp.printYourselfToFile("/tmp/analytic.txt", false);
595 if ( fabs(MaxErr) > 1e-5 ) {
596 printf("The error is actually quite large..\n");
597 }
598 }
599 #endif
600#else // ifdef __FM_MODULE
601 OOFEM_ERROR("Fluid module missing\n");
602#endif// ifdef __FM_MODULE
603
604
605 // *******************
606 //computeNumericStiffnessMatrix(answer, rMode, tStep);
607}
608
609void
610tet21ghostsolid::computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep)
611{
612 // Compute displacements used to compute J
613
614 answer.resize(64);
615 answer.zero();
616
617 if ( type != ExternalForcesVector ) {
618 answer.resize(0);
619 return;
620 }
621
622#ifdef __FM_MODULE
623 FluidDynamicMaterial *mat = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
624#endif
625 FloatArray N, gVector, temparray(30), dNv, inc, a, a_prev, u, u_prev, vload;
626 FloatMatrix dNx, G;
627
628 load->computeComponentArrayAt(gVector, tStep, VM_Total);
629 temparray.zero();
630
631 vload.resize(4);
632 vload.zero();
633
634 this->giveUnknownData(a_prev, a, inc, tStep);
637
638 for ( auto &gp : * this->integrationRulesArray [ 0 ] ) {
639 const FloatArray &lcoords = gp->giveNaturalCoordinates();
640
641 double detJ = fabs(this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) );
642 double dA = detJ * gp->giveWeight();
643
644 // Body load
645 if ( gVector.giveSize() ) {
646#ifdef __FM_MODULE
647 double rho = mat->give('d', gp);
648#else
649 OOFEM_ERROR("Missing FM module");
650 double rho = 1.0;
651#endif
652
653 if ( this->nlGeometry ) {
654 FloatArray Fa, temp;
655 FloatMatrix F, Finv, FinvT;
657 F.beMatrixForm(Fa);
658 Finv.beInverseOf(F);
659 FinvT.beTranspositionOf(Finv);
660
661 dA = dA * F.giveDeterminant();
662
663 temp.beProductOf(Finv, gVector);
664 gVector = temp;
665 }
666
667 this->interpolation.evalN(N, lcoords, FEIElementGeometryWrapper(this) );
668
669 for ( int j = 0; j < N.giveSize(); j++ ) {
670 temparray(3 * j + 0) += N(j) * rho * gVector(0) * dA;
671 temparray(3 * j + 1) += N(j) * rho * gVector(1) * dA;
672 temparray(3 * j + 2) += N(j) * rho * gVector(2) * dA;
673 }
674 }
675
676 // "load" from previous step
677 this->interpolation.evaldNdx(dNx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
678 this->interpolation_lin.evalN(N, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
679
680 dNv.resize(30);
681 for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) {
682 dNv.at(k * 3 + 1) = dNx.at(k + 1, 1);
683 dNv.at(k * 3 + 2) = dNx.at(k + 1, 2);
684 dNv.at(k * 3 + 3) = dNx.at(k + 1, 3);
685 }
686
687 G.plusDyadUnsym(N, dNv, dA);
688 FloatMatrix GT;
689 GT.beTranspositionOf(G);
690
691 vload.plusProduct(GT, u_prev, -0.0);
692 //vload.printYourself();
693 }
694
695 if ( this->computeItransform ) {
697 }
698
699 FloatArray temp;
700
701 temp.resize(64);
702 temp.zero();
703 temp.assemble(temparray, this->ghostdisplacement_ordering);
704 temp.assemble(vload, this->conservation_ordering);
705
706 answer.beProductOf(Itransform, temp);
707}
708
709void
710tet21ghostsolid::giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord)
711{
712 FloatArray a;
713 this->computeVectorOf(VM_Total, tStep, a);
714 giveInternalForcesVectorGivenSolution(answer, tStep, useUpdatedGpRecord, a);
715}
716
717void
719{
720#ifdef __FM_MODULE
721 FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
722#endif
723
724 FloatMatrix Kf, G, Kx, B, Ed, dNx;
725 FloatArray Strain, Stress, Nlin, dNv, a_inc, a_prev, aVelocity, aPressure, aGhostDisplacement, aIncGhostDisplacement, fluidStress, epsf, dpdivv;
726 FloatArray momentum, conservation, auxstress, divv;
727 double pressure;
728
729 if ( !tStep->isTheFirstStep() ) {
730 this->computeVectorOf(VM_Total, tStep->givePreviousStep(), a_prev);
731 } else {
732 a_prev.resize(a.giveSize() );
733 a_prev.zero();
734 }
735 a_inc.operator=(a - a_prev);
736
737 aVelocity.beSubArrayOf(a, momentum_ordering);
739 aGhostDisplacement.beSubArrayOf(a, ghostdisplacement_ordering);
740 aIncGhostDisplacement.beSubArrayOf(a_inc, ghostdisplacement_ordering);
741
742 FloatArray aTotal;
743 aTotal.operator=(aVelocity + aIncGhostDisplacement * VELOCITYCOEFF); // Assume deltaT=1 gives that the increment is the velocity
744
745 for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) {
746 const FloatArray &lcoords = gp->giveNaturalCoordinates();
747 double detJ = fabs( ( this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ) );
748 double weight = gp->giveWeight();
749
750 this->interpolation.evaldNdx(dNx, lcoords, FEIElementGeometryWrapper(this) );
751 this->interpolation_lin.evalN(Nlin, lcoords, FEIElementGeometryWrapper(this) );
752
753 dNv.resize(30);
754 for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) {
755 dNv.at(k * 3 + 1) = dNx.at(k + 1, 1);
756 dNv.at(k * 3 + 2) = dNx.at(k + 1, 2);
757 dNv.at(k * 3 + 3) = dNx.at(k + 1, 3);
758 }
759
760 pressure = Nlin.dotProduct(aPressure);
761
762 if ( nlGeometry == 0 ) {
763 this->computeBmatrixAt(gp, B);
764
765 epsf.beProductOf(B, aTotal);
766
767 // Momentum equation
768 gp->setMaterialMode(_3dFlow);
769#ifdef __FM_MODULE
770 auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep);
771 fluidStress = val.first;
772#else
773 OOFEM_ERROR("Missing FM module");
774#endif
775 gp->setMaterialMode(_3dMat);
776
777 momentum.plusProduct(B, fluidStress, detJ * weight);
778 momentum.add(-pressure * detJ * weight, dNv);
779
780 // Conservation equation
781 divv.beTProductOf(FloatMatrix::fromArray(dNv), aTotal);
782 divv.times(-detJ * weight);
783
784 conservation.add(divv.at(1), Nlin);
785
786 // Ghost solid part
787 Strain.beProductOf(B, aGhostDisplacement);
788 Stress.beProductOf(Dghost, Strain);
789 auxstress.plusProduct(B, Stress, detJ * weight);
790 } else {
791 FloatMatrix BH;
792
793 this->computeBHmatrixAt(gp, BH);
794 this->computeBmatrixAt(gp, B);
795
796 // Compute deformation gradient etc.
797 FloatArray Fa, FinvTa;
798 FloatMatrix F, Finv, FinvT, fluidStressMatrix;
799
800 computeDeformationGradientVectorFromDispl(Fa, gp, tStep, aGhostDisplacement);
801 F.beMatrixForm(Fa);
802 double J = F.giveDeterminant();
803
804 Finv.beInverseOf(F);
805 FinvT.beTranspositionOf(Finv);
806 FinvTa.beVectorForm(FinvT);
807
808 epsf.beProductOf(B, aTotal);
809
810 // Momentum equation --------------------------------------------------
811
812 // Compute fluid cauchy stress
813 FloatArray fluidCauchyArray;
814 FloatMatrix fluidCauchyMatrix;
815
816 gp->setMaterialMode(_3dFlow);
817#ifdef __FM_MODULE
818 auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep);
819 fluidCauchyArray = val.first;
820#else
821 OOFEM_ERROR("Missing FM module");
822#endif
823 gp->setMaterialMode(_3dMat);
824
825 // Transform to 1st Piola-Kirshhoff
826 fluidCauchyMatrix.beMatrixFormOfStress(fluidCauchyArray);
827 fluidStressMatrix.beProductOf(fluidCauchyMatrix, FinvT);
828 fluidStress.beVectorForm(fluidStressMatrix);
829
830 // Add to equation
831 momentum.plusProduct(BH, fluidStress, detJ * J * weight);
832
833 // Pressure term in momentum equation
834 FloatArray ptemp;
835 ptemp.beTProductOf(BH, FinvTa);
836
837 momentum.add(-pressure * detJ * weight * J, ptemp);
838
839 // Conservation equation ---------------------------------------------
840 FloatArray BvaTotal;
841 double FinvTaBvaTotal;
842
843 BvaTotal.beProductOf(BH, aTotal);
844 FinvTaBvaTotal = FinvTa.dotProduct(BvaTotal);
845 conservation.add(-J * detJ * weight * FinvTaBvaTotal, Nlin);
846
847 // Ghost solid part --------------------------------------------------
848 Strain.beProductOf(B, aGhostDisplacement);
849 Stress.beProductOf(Dghost, Strain);
850 auxstress.plusProduct(B, Stress, detJ * weight);
851 }
852 }
853 answer.resize(64);
854 answer.zero();
855
856 FloatArray temp;
857
858 temp.resize(64);
859 temp.zero();
860
861 temp.assemble(momentum, ghostdisplacement_ordering);
862 temp.assemble(conservation, conservation_ordering);
863 temp.assemble(auxstress, momentum_ordering);
864
865 if ( this->computeItransform ) {
867 }
868
869 answer.beProductOf(Itransform, temp);
870}
871
872void
873tet21ghostsolid::giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &a, bool ExtraLogging)
874{
875#ifdef __FM_MODULE
876 FluidDynamicMaterial *fluidMaterial = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial();
877#endif
878
879 FloatMatrix Kf, G, Kx, B, Ed, dNx;
880 FloatArray Strain, Stress, Nlin, dNv, a_inc, a_prev, aVelocity, aPressure, aGhostDisplacement, aIncGhostDisplacement, fluidStress, epsf, dpdivv;
881 FloatArray momentum, conservation, auxstress, divv;
882 double pressure;
883
884 if ( !tStep->isTheFirstStep() ) {
885 this->computeVectorOf(VM_Total, tStep->givePreviousStep(), a_prev);
886 } else {
887 a_prev.resize(a.giveSize() );
888 a_prev.zero();
889 }
890 a_inc.operator=(a - a_prev);
891
892 aVelocity.beSubArrayOf(a, momentum_ordering);
894 aGhostDisplacement.beSubArrayOf(a, ghostdisplacement_ordering);
895 aIncGhostDisplacement.beSubArrayOf(a_inc, ghostdisplacement_ordering);
896
897 FloatArray aTotal;
898 aTotal.operator=(aVelocity + aIncGhostDisplacement * VELOCITYCOEFF); // Assume deltaT=1 gives that the increment is the velocity
899
900 for ( auto &gp : * this->giveDefaultIntegrationRulePtr() ) {
901 // gp = this->giveDefaultIntegrationRulePtr()->getIntegrationPoint(0);
902 const FloatArray &lcoords = gp->giveNaturalCoordinates();
903 double detJ = fabs( ( this->interpolation.giveTransformationJacobian(lcoords, FEIElementGeometryWrapper(this) ) ) );
904 double weight = gp->giveWeight();
905
906 this->interpolation.evaldNdx(dNx, lcoords, FEIElementGeometryWrapper(this) );
907 this->interpolation_lin.evalN(Nlin, lcoords, FEIElementGeometryWrapper(this) );
908
909 dNv.resize(30);
910 for ( int k = 0; k < dNx.giveNumberOfRows(); k++ ) {
911 dNv.at(k * 3 + 1) = dNx.at(k + 1, 1);
912 dNv.at(k * 3 + 2) = dNx.at(k + 1, 2);
913 dNv.at(k * 3 + 3) = dNx.at(k + 1, 3);
914 }
915
916 pressure = Nlin.dotProduct(aPressure);
917#if FIXEDpressure == 1
918 pressure = 1.0;
919#endif
920
921 if ( nlGeometry == 0 ) {
922 this->computeBmatrixAt(gp, B);
923
924 epsf.beProductOf(B, aTotal);
925
926 // Momentum equation
927 gp->setMaterialMode(_3dFlow);
928#ifdef __FM_MODULE
929 auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep);
930 fluidStress = val.first;
931#else
932 OOFEM_ERROR("Missing FM module");
933#endif
934 gp->setMaterialMode(_3dMat);
935
936 momentum.plusProduct(B, fluidStress, detJ * weight);
937 momentum.add(-pressure * detJ * weight, dNv);
938
939 // Conservation equation
940 divv.beTProductOf(FloatMatrix::fromArray(dNv), aTotal);
941 divv.times(-detJ * weight);
942
943 conservation.add(divv.at(1), Nlin);
944
945 // Ghost solid part
946 Strain.beProductOf(B, aGhostDisplacement);
947 Stress.beProductOf(Dghost, Strain);
948 auxstress.plusProduct(B, Stress, detJ * weight);
949 } else {
950 FloatMatrix BH;
951
952 this->computeBHmatrixAt(gp, BH);
953 this->computeBmatrixAt(gp, B);
954
955 // Compute deformation gradient etc.
956 FloatArray Fa, FinvTa;
957 FloatMatrix F, Finv, FinvT, fluidStressMatrix;
958
959 computeDeformationGradientVectorFromDispl(Fa, gp, tStep, aGhostDisplacement);
960 F.beMatrixForm(Fa);
961 double J = F.giveDeterminant();
962#if FIXEDJ == 1
963 J = 1;
964#endif
965
966#if FIXEDFinvT == 1
967 FloatArray aTrue, dispTrue;
968 this->computeVectorOf(VM_Total, tStep, aTrue);
970 computeDeformationGradientVectorFromDispl(Fa, gp, tStep, dispTrue);
971 F.beMatrixForm(Fa);
972#endif
973
974 Finv.beInverseOf(F);
975 FinvT.beTranspositionOf(Finv);
976 FinvTa.beVectorForm(FinvT);
977
978 epsf.beProductOf(B, aTotal);
979
980 // Momentum equation --------------------------------------------------
981
982 // Compute fluid cauchy stress
983 FloatArray fluidCauchy;
984 FloatMatrix fluidCauchyMatrix;
985
986 gp->setMaterialMode(_3dFlow);
987#ifdef __FM_MODULE
988 auto val = fluidMaterial->computeDeviatoricStress3D(epsf, pressure, gp, tStep);
989 fluidCauchy = val.first;
990#else
991 OOFEM_ERROR("Missing FM module");
992#endif
993 gp->setMaterialMode(_3dMat);
994
995 // Transform to 1st Piola-Kirshhoff
996 fluidCauchyMatrix.beMatrixFormOfStress(fluidCauchy);
997 fluidStressMatrix.beProductOf(fluidCauchyMatrix, FinvT);
998 fluidStress.beVectorForm(fluidStressMatrix);
999
1000 /* if ( (this->globalNumber==292) && (ExtraLogging)) {
1001 * std :: cout << "gp@" << gp << " ";
1002 * F.printYourself("F in NUMERIC");
1003 * epsf.printYourself("epsf in NUMERIC");
1004 * fluidCauchy.printYourself("fluidCauchy in NUMERIC");
1005 * } */
1006
1007 // Add to equation
1008 momentum.plusProduct(BH, fluidStress, detJ * J * weight);
1009
1010 // Pressure term in momentum equation
1011 FloatArray ptemp;
1012 ptemp.beTProductOf(BH, FinvTa);
1013 momentum.add(-pressure * detJ * weight * J, ptemp);
1014
1015 // Conservation equation ---------------------------------------------
1016 FloatArray BvaTotal;
1017 double FinvTaBvaTotal;
1018
1019 BvaTotal.beProductOf(BH, aTotal);
1020 FinvTaBvaTotal = FinvTa.dotProduct(BvaTotal);
1021 conservation.add(-J * detJ * weight * FinvTaBvaTotal, Nlin);
1022
1023 // Ghost solid part --------------------------------------------------
1024 Strain.beProductOf(B, aGhostDisplacement);
1025 Stress.beProductOf(Dghost, Strain);
1026 auxstress.plusProduct(B, Stress, detJ * weight);
1027 }
1028 }
1029 answer.resize(64);
1030 answer.zero();
1031
1032 FloatArray temp;
1033
1034 temp.resize(64);
1035 temp.zero();
1036
1037 temp.assemble(momentum, ghostdisplacement_ordering);
1038 temp.assemble(conservation, conservation_ordering);
1039 temp.assemble(auxstress, momentum_ordering);
1040
1041 if ( this->computeItransform ) {
1043 }
1044
1045 answer.beProductOf(Itransform, temp);
1046} // **************** DEBUG
1047
1048void
1050{
1051 // Returns the mask for node number inode of this element.
1052
1053 if ( inode <= 4 ) {
1054 answer = {
1055 V_u, V_v, V_w, D_u, D_v, D_w, P_f
1056 };
1057 } else {
1058 answer = {
1059 V_u, V_v, V_w, D_u, D_v, D_w
1060 };
1061 }
1062}
1063
1064void
1066// Returns the [6x30] strain-displacement matrix {B} of the receiver, eva-
1067// luated at gp.
1068// B matrix - 6 rows : epsilon-X, epsilon-Y, epsilon-Z, gamma-YZ, gamma-ZX, gamma-XY :
1069{
1070 FloatMatrix dnx;
1071
1072 this->interpolation.evaldNdx(dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
1073
1074 answer.resize(6, 30);
1075 answer.zero();
1076
1077 for ( int i = 1; i <= 10; i++ ) {
1078 answer.at(1, 3 * i - 2) = dnx.at(i, 1);
1079 answer.at(2, 3 * i - 1) = dnx.at(i, 2);
1080 answer.at(3, 3 * i - 0) = dnx.at(i, 3);
1081
1082 answer.at(4, 3 * i - 1) = dnx.at(i, 3);
1083 answer.at(4, 3 * i - 0) = dnx.at(i, 2);
1084
1085 answer.at(5, 3 * i - 2) = dnx.at(i, 3);
1086 answer.at(5, 3 * i - 0) = dnx.at(i, 1);
1087
1088 answer.at(6, 3 * i - 2) = dnx.at(i, 2);
1089 answer.at(6, 3 * i - 1) = dnx.at(i, 1);
1090 }
1091}
1092
1093void
1095{
1096 FloatArray F, u;
1097 FloatMatrix dNdx, BH, Fmatrix, Finv;
1099
1100 // Fetch displacements
1101 this->computeVectorOf({ 1, 2, 3 }, VM_Total, tStep, u);
1102
1103 // Compute dNdx in point
1104 interpolation->evaldNdx(dNdx, lcoord, FEIElementGeometryWrapper(this) );
1105
1106 // Compute displacement gradient BH
1107 BH.resize(9, dNdx.giveNumberOfRows() * 3);
1108 BH.zero();
1109
1110 for ( int i = 1; i <= dNdx.giveNumberOfRows(); i++ ) {
1111 BH.at(1, 3 * i - 2) = dNdx.at(i, 1); // du/dx
1112 BH.at(2, 3 * i - 1) = dNdx.at(i, 2); // dv/dy
1113 BH.at(3, 3 * i - 0) = dNdx.at(i, 3); // dw/dz
1114 BH.at(4, 3 * i - 1) = dNdx.at(i, 3); // dv/dz
1115 BH.at(7, 3 * i - 0) = dNdx.at(i, 2); // dw/dy
1116 BH.at(5, 3 * i - 2) = dNdx.at(i, 3); // du/dz
1117 BH.at(8, 3 * i - 0) = dNdx.at(i, 1); // dw/dx
1118 BH.at(6, 3 * i - 2) = dNdx.at(i, 2); // du/dy
1119 BH.at(9, 3 * i - 1) = dNdx.at(i, 1); // dv/dx
1120 }
1121
1122 // Finally, compute deformation gradient F=BH*u+I
1123 F.beProductOf(BH, u);
1124 F.at(1) += 1.0;
1125 F.at(2) += 1.0;
1126 F.at(3) += 1.0;
1127
1128 answer = F;
1129}
1130
1131void
1133{
1134 FloatMatrix dnx;
1135
1136 this->interpolation.evaldNdx(dnx, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
1137
1138 answer.resize(9, 30);
1139 answer.zero();
1140
1141 for ( int i = 1; i <= dnx.giveNumberOfRows(); i++ ) {
1142 answer.at(1, 3 * i - 2) = dnx.at(i, 1); // du/dx
1143 answer.at(2, 3 * i - 1) = dnx.at(i, 2); // dv/dy
1144 answer.at(3, 3 * i - 0) = dnx.at(i, 3); // dw/dz
1145 answer.at(4, 3 * i - 1) = dnx.at(i, 3); // dv/dz
1146 answer.at(7, 3 * i - 0) = dnx.at(i, 2); // dw/dy
1147 answer.at(5, 3 * i - 2) = dnx.at(i, 3); // du/dz
1148 answer.at(8, 3 * i - 0) = dnx.at(i, 1); // dw/dx
1149 answer.at(6, 3 * i - 2) = dnx.at(i, 2); // du/dy
1150 answer.at(9, 3 * i - 1) = dnx.at(i, 1); // dv/dx
1151 }
1152}
1153
1154void
1156{
1157 this->computeVectorOf(VM_Total, tStep, u);
1158
1159 if ( !tStep->isTheFirstStep() ) {
1160 this->computeVectorOf(VM_Total, tStep->givePreviousStep(), u_prev);
1161 this->computeVectorOf(VM_Incremental, tStep, inc);
1162 } else {
1163 inc.resize(u.giveSize() );
1164 inc.zero();
1165 u_prev.operator=(inc);
1166 }
1167}
1168
1169void
1171{
1172 // Computes the deformation gradient in the Voigt format at the Gauss point gp of
1173 // the receiver at time step tStep.
1174 // Order of components: 11, 22, 33, 23, 13, 12, 32, 31, 21 in the 3D.
1175
1176 // Obtain the current displacement vector of the element and subtract initial displacements (if present)
1177 if ( initialDisplacements ) {
1179 }
1180
1181 // Displacement gradient H = du/dX
1182 FloatMatrix BH;
1183 this->computeBHmatrixAt(gp, BH);
1184 answer.beProductOf(BH, u);
1185
1186 // Deformation gradient F = H + I
1187 MaterialMode matMode = gp->giveMaterialMode();
1188 if ( matMode == _3dMat || matMode == _PlaneStrain ) {
1189 answer.at(1) += 1.0;
1190 answer.at(2) += 1.0;
1191 answer.at(3) += 1.0;
1192 } else if ( matMode == _PlaneStress ) {
1193 answer.at(1) += 1.0;
1194 answer.at(2) += 1.0;
1195 } else if ( matMode == _1dMat ) {
1196 answer.at(1) += 1.0;
1197 } else {
1198 OOFEM_ERROR("MaterialMode is not supported yet (%s)", __MaterialModeToString(matMode) );
1199 }
1200}
1201
1202void
1204{
1205 FloatArray u;
1206 this->computeVectorOf({ 1, 2, 3 }, VM_Total, tStep, u);
1207 computeDeformationGradientVectorFromDispl(answer, gp, tStep, u);
1208}
1209
1210double
1212// Returns the portion of the receiver which is attached to gp.
1213{
1214 //double determinant = fabs(this->interpolation.giveTransformationJacobian(gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) );
1215 //double weight = gp->giveWeight();
1216 return ( this->computeVolume() );
1217
1218 //return ( determinant * weight );
1219}
1220
1221
1222int
1224{
1225 if ( type == IST_Velocity ) {
1226 FloatArray N, a;
1227 FloatMatrix Nmat;
1228
1229 this->computeVectorOf({ V_u, V_v, V_w }, VM_Total, tStep, a);
1231
1232 Nmat.resize(3, N.giveSize() * 3);
1233 for ( int i = 1; i <= N.giveSize(); i++ ) {
1234 Nmat.at(1, 3 * i - 2) = N.at(i);
1235 Nmat.at(2, 3 * i - 1) = N.at(i);
1236 Nmat.at(3, 3 * i - 0) = N.at(i);
1237 }
1238
1239 answer.beProductOf(Nmat, a);
1240 return 1;
1241 } else if ( type == IST_Pressure ) {
1242 FloatArray N, a;
1243
1244 this->computeVectorOf({ P_f }, VM_Total, tStep, a);
1246
1247 answer.resize(1);
1248 answer.at(1) = N.dotProduct(a);
1249 return 1;
1250 } else {
1251 MaterialMode matmode = gp->giveMaterialMode();
1252 gp->setMaterialMode(_3dFlow);
1253 int r = StructuralElement::giveIPValue(answer, gp, type, tStep);
1254 gp->setMaterialMode(matmode);
1255 return r;
1256 }
1257}
1258
1259bool
1261{
1262 // Create a transformation matrix that switch all rows/equations located in OmegaF but not on GammaInt, i.e where we do not have a no slip condition
1263
1264 Itransform.resize(64, 64);
1265 Itransform.zero();
1266
1267#if USEUNCOUPLED == 0
1268 Itransform.beUnitMatrix();
1269 return 0;
1270
1271#endif
1272
1273 int m = 1;
1274
1275 int row1, row2;
1276 IntArray row1List, row2List;
1277
1278 for ( int i = 1; i <= this->giveNumberOfDofManagers(); i++ ) {
1279 IntArray DofIDs;
1280 int firstIndex = m;
1281 this->giveDofManDofIDMask(i, DofIDs);
1282 // DofIDs.printYourself();
1283
1284 for ( int j = 1; j <= DofIDs.giveSize(); j++ ) {
1285 row1 = m;
1286 row2 = m;
1287
1288 if ( DofIDs.at(j) == V_u || DofIDs.at(j) == V_v || DofIDs.at(j) == V_w ) {
1289 bool doSwitch = !this->giveDofManager(i)->giveDofWithID(DofIDs.at(j) )->hasBc(tStep);
1290
1291 if ( doSwitch ) { // Boundary condition not set, make switch
1292 row1 = m;
1293
1294 for ( int n = 1; n <= DofIDs.giveSize(); n++ ) {
1295 if ( ( DofIDs.at(j) == V_u && DofIDs.at(n) == D_u ) ||
1296 ( DofIDs.at(j) == V_v && DofIDs.at(n) == D_v ) ||
1297 ( DofIDs.at(j) == V_w && DofIDs.at(n) == D_w ) ) {
1298 row2 = firstIndex + n - 1;
1299 }
1300 }
1301 row1List.resizeWithValues(row1List.giveSize() + 1);
1302 row1List.at(row1List.giveSize() ) = row1;
1303 row2List.resizeWithValues(row2List.giveSize() + 1);
1304 row2List.at(row2List.giveSize() ) = row2;
1305 }
1306 }
1307 m++;
1308 }
1309 }
1310
1311 // Create identity matrix
1312 Itransform.beUnitMatrix();
1313
1314 // Create tranformation matrix by switching rows
1315 for ( int i = 1; i <= row1List.giveSize(); i++ ) {
1316 Itransform.at(row1List.at(i), row1List.at(i) ) = 0;
1317 Itransform.at(row2List.at(i), row2List.at(i) ) = 0;
1318
1319 Itransform.at(row1List.at(i), row2List.at(i) ) = 1;
1320 Itransform.at(row2List.at(i), row1List.at(i) ) = 1;
1321 }
1322
1323 computeItransform = false;
1324
1325 return 0;
1326}
1327
1328// Some extension Interfaces to follow:
1329
1331{
1332 switch ( it ) {
1334 return static_cast< NodalAveragingRecoveryModelInterface * >( this );
1335
1337 return static_cast< SpatialLocalizerInterface * >( this );
1338
1340 return static_cast< EIPrimaryUnknownMapperInterface * >( this );
1341
1342 default:
1344 //return FMElement :: giveInterface(it);
1345 }
1346}
1347
1349 TimeStep *tStep, const FloatArray &lcoords, FloatArray &answer)
1350{
1351 FloatArray n, n_lin;
1352 this->interpolation.evalN(n, lcoords, FEIElementGeometryWrapper(this) );
1353 this->interpolation_lin.evalN(n_lin, lcoords, FEIElementGeometryWrapper(this) );
1354 answer.resize(4);
1355 answer.zero();
1356 for ( int i = 1; i <= n.giveSize(); i++ ) {
1357 answer(0) += n.at(i) * this->giveNode(i)->giveDofWithID(V_u)->giveUnknown(mode, tStep);
1358 answer(1) += n.at(i) * this->giveNode(i)->giveDofWithID(V_v)->giveUnknown(mode, tStep);
1359 answer(2) += n.at(i) * this->giveNode(i)->giveDofWithID(V_w)->giveUnknown(mode, tStep);
1360 }
1361
1362 for ( int i = 1; i <= n_lin.giveSize(); i++ ) {
1363 answer(3) += n_lin.at(i) * this->giveNode(i)->giveDofWithID(P_f)->giveUnknown(mode, tStep);
1364 }
1365}
1366
1367void
1369{
1370 if ( type == IST_Pressure ) {
1371 answer.resize(1);
1372 if ( node <= 4 ) {
1373 answer.at(1) = this->giveNode(node)->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep);
1374 } else {
1375 const auto &eNodes = this->interpolation.computeLocalEdgeMapping(node - 4);
1376 answer.at(1) = 0.5 * (
1377 this->giveNode(eNodes.at(1) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) +
1378 this->giveNode(eNodes.at(2) )->giveDofWithID(P_f)->giveUnknown(VM_Total, tStep) );
1379 }
1380 } else {
1381 answer.clear();
1382 }
1383}
1384
1385void
1386tet21ghostsolid::computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global)
1387{
1388 answer.clear();
1389 if ( type != ExternalForcesVector ) {
1390 return;
1391 }
1392
1393 FEInterpolation *fei = this->giveInterpolation();
1394 if ( !fei ) {
1395 OOFEM_ERROR("No interpolator available");
1396 }
1397
1398 FloatArray n_vec, f(18);
1399 FloatMatrix n, T;
1400 FloatArray force;
1401 int nsd = fei->giveNsd(this->giveGeometryType());
1402
1403 f.zero();
1404 auto iRule = fei->giveBoundaryIntegrationRule(load->giveApproxOrder(), boundary, this->giveGeometryType());
1405
1406 for ( auto &gp : * iRule ) {
1407 FloatArray lcoords = gp->giveNaturalCoordinates();
1408 if ( load->giveFormulationType() == Load::FT_Entity ) {
1409 load->computeValueAt(force, tStep, lcoords, mode);
1410 } else {
1411 FloatArray gcoords, elcoords;
1412 this->interpolation.surfaceLocal2global(gcoords, boundary, lcoords, FEIElementGeometryWrapper(this) );
1413 this->interpolation.global2local(elcoords, gcoords, FEIElementGeometryWrapper(this) );
1414 NeumannMomentLoad *thisLoad = dynamic_cast< NeumannMomentLoad * >( load );
1415 if ( thisLoad != NULL ) {
1416 FloatArray temp;
1417 thisLoad->computeValueAtBoundary(temp, tStep, gcoords, VM_Total, this, boundary);
1418
1419 FloatArray F;
1420 FloatMatrix Fm, Finv, FinvT;
1421 this->computeDeformationGradientVectorAt(F, elcoords, tStep);
1422 Fm.beMatrixForm(F);
1423 double J = Fm.giveDeterminant();
1424 Finv.beInverseOf(Fm);
1425 FinvT.beTranspositionOf(Finv);
1426 force.beTProductOf(Finv, temp);
1427 force.times(J);
1428 } else {
1429 load->computeValueAt(force, tStep, gcoords, VM_Total);
1430 }
1431 }
1432
1434 // We always want the global values in the end, so we might as well compute them here directly:
1435 // transform force
1436 if ( load->giveCoordSystMode() == Load::CST_Global ) {
1437 // then just keep it in global c.s
1438 } else {
1440 // transform from local boundary to element local c.s
1441 /*if ( this->computeLoadLSToLRotationMatrix(T, boundary, gp) ) {
1442 * force.rotatedWith(T, 'n');
1443 * }*/
1444 // then to global c.s
1445 if ( this->computeLoadGToLRotationMtrx(T) ) {
1446 force.rotatedWith(T, 't');
1447 }
1448 }
1449
1450 // Construct n-matrix
1451 fei->boundaryEvalN(n_vec, boundary, lcoords, FEIElementGeometryWrapper(this) );
1452 n.beNMatrixOf(n_vec, nsd);
1453
1455 double thickness = 1.0; // Should be the circumference for axisymm-elements.
1456 double dV = thickness * gp->giveWeight() * fei->boundaryGiveTransformationJacobian(boundary, lcoords, FEIElementGeometryWrapper(this) );
1457 f.plusProduct(n, force, dV);
1458 }
1459
1460 FloatArray temp;
1461 FloatMatrix Itrans;
1462
1463 answer.resize(39);
1464 answer.zero();
1465 answer.assemble(f, this->velocitydofsonside);
1466}
1467}
#define N(a, b)
#define E(a, b)
#define REGISTER_Element(class)
void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override
int giveApproxOrder() override=0
CoordSystType giveCoordSystMode() override
virtual int setupIntegrationPoints(IntegrationRule &irule, int npoints, Element *element)
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
virtual double giveUnknown(ValueModeType mode, TimeStep *tStep)=0
virtual bool hasBc(TimeStep *tStep)=0
Node * giveNode(int i) const
Definition element.h:629
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
int numberOfGaussPoints
Definition element.h:175
virtual int giveNumberOfDofManagers() const
Definition element.h:695
DofManager * giveDofManager(int i) const
Definition element.C:553
CrossSection * giveCrossSection()
Definition element.C:534
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual double computeVolume()
Definition element.C:1123
virtual std::unique_ptr< IntegrationRule > giveBoundaryIntegrationRule(int order, int boundary, const Element_Geometry_Type) const
Definition feinterpol.C:101
virtual double boundaryGiveTransformationJacobian(int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual int giveNsd(const Element_Geometry_Type) const =0
virtual void boundaryEvalN(FloatArray &answer, int boundary, const FloatArray &lcoords, const FEICellGeometry &cellgeo) const =0
virtual Interface * giveInterface(InterfaceType t)
Definition femcmpnn.h:181
void assemble(const FloatArray &fe, const IntArray &loc)
Definition floatarray.C:616
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
void plusProduct(const FloatMatrix &b, const FloatArray &s, double dV)
Definition floatarray.C:288
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
void beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:689
void beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray)
Definition floatarray.C:721
void beVectorForm(const FloatMatrix &aMatrix)
void add(const FloatArray &src)
Definition floatarray.C:218
void subtract(const FloatArray &src)
Definition floatarray.C:320
void beSubArrayOf(const FloatArray &src, const IntArray &indx)
Definition floatarray.C:440
void times(double s)
Definition floatarray.C:834
void printYourselfToFile(const std::string filename, const bool showDimensions=true) const
void times(double f)
void plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
static FloatMatrix fromArray(const FloatArray &vector, bool transpose=false)
void add(const FloatMatrix &a)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
int giveNumberOfColumns() const
Returns number of columns of receiver.
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void beNMatrixOf(const FloatArray &n, int nsd)
void plusDyadUnsym(const FloatArray &a, const FloatArray &b, double dV)
void setColumn(const FloatArray &src, int c)
void beTranspositionOf(const FloatMatrix &src)
void zero()
Zeroes all coefficient of receiver.
void beMatrixFormOfStress(const FloatArray &aArray)
bool beInverseOf(const FloatMatrix &src)
void beDyadicProductOf(const FloatArray &vec1, const FloatArray &vec2)
double giveDeterminant() const
void beMatrixForm(const FloatArray &aArray)
int giveNumberOfRows() const
Returns number of rows of receiver.
void assemble(const FloatMatrix &src, const IntArray &loc)
double at(std::size_t i, std::size_t j) const
void beTProductOf(const FloatMatrix &a, const FloatMatrix &b)
virtual FloatMatrixF< 6, 6 > computeTangent3D(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const =0
virtual std::pair< FloatArrayF< 6 >, double > computeDeviatoricStress3D(const FloatArrayF< 6 > &eps, double pressure, GaussPoint *gp, TimeStep *tStep) const
void setMaterialMode(MaterialMode newMode)
Sets material mode of receiver.
Definition gausspoint.h:192
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
MaterialMode giveMaterialMode()
Returns corresponding material mode of receiver.
Definition gausspoint.h:190
void resizeWithValues(int n, int allocChunk=0)
Definition intarray.C:64
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
@ FT_Entity
Definition load.h:80
virtual void computeComponentArrayAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
Definition load.C:84
@ CST_Global
Load is specified in global c.s.
Definition load.h:71
virtual FormulationType giveFormulationType()
Definition load.h:170
virtual double give(int aProperty, GaussPoint *gp) const
Definition material.C:51
NLStructuralElement(int n, Domain *d)
int nlGeometry
Flag indicating if geometrical nonlinearities apply.
void computeValueAtBoundary(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode, Element *e, int boundary)
SpatialLocalizerInterface(Element *element)
virtual FloatMatrixF< 9, 9 > giveStiffnessMatrix_dPdF_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const =0
virtual FloatArrayF< 6 > giveRealStress_3d(const FloatArrayF< 6 > &reducedStrain, GaussPoint *gp, TimeStep *tStep) const =0
virtual FloatMatrixF< 6, 6 > giveStiffnessMatrix_3d(MatResponseMode mode, GaussPoint *gp, TimeStep *tStep) const =0
StructuralCrossSection * giveStructuralCrossSection()
Helper function which returns the structural cross-section for the element.
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
std::unique_ptr< FloatArray > initialDisplacements
Initial displacement vector, describes the initial nodal displacements when element has been casted.
virtual int computeLoadGToLRotationMtrx(FloatMatrix &answer)
int giveNumber()
Returns receiver's number.
Definition timestep.h:144
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
bool isTheFirstStep()
Definition timestep.C:148
static FEI3dTetQuad interpolation
static IntArray displacementdofsonside
FEInterpolation * giveInterpolation() const override
bool giveRowTransformationMatrix(TimeStep *tStep)
void computeDeformationGradientVectorFromDispl(FloatArray &answer, GaussPoint *gp, TimeStep *tStep, FloatArray &u)
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
void EIPrimaryUnknownMI_computePrimaryUnknownVectorAtLocal(ValueModeType u, TimeStep *tStep, const FloatArray &coords, FloatArray &answer) override
void computeConstitutiveMatrixAt(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override
void computeNumericStiffnessMatrixDebug(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
static IntArray velocitydofsonside
static IntArray conservation_ordering
Ordering of conservation equations in element. Used to assemble the element stiffness.
void computeDeformationGradientVector(FloatArray &answer, GaussPoint *gp, TimeStep *tStep) override
void giveInternalForcesVectorGivenSolutionDebug(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &SolutionVector, bool ExtraLogging)
void computeConstitutiveMatrix_dPdF_At(FloatMatrix &answer, MatResponseMode rMode, GaussPoint *gp, TimeStep *tStep) override
static IntArray ghostdisplacement_ordering
Ordering of ghost displacements equations.
void computeDeformationGradientVectorAt(FloatArray &answer, FloatArray lcoord, TimeStep *tStep)
void giveInternalForcesVectorGivenSolution(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord, FloatArray &SolutionVector)
double computeVolumeAround(GaussPoint *gp) override
void giveInternalForcesVector(FloatArray &answer, TimeStep *tStep, int useUpdatedGpRecord=0) override
static FEI3dTetLin interpolation_lin
Interface * giveInterface(InterfaceType it) override
void giveUnknownData(FloatArray &u_prev, FloatArray &u, FloatArray &inc, TimeStep *tStep)
Element_Geometry_Type giveGeometryType() const override
void NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node, InternalStateType type, TimeStep *tStep) override
void computeBmatrixAt(GaussPoint *, FloatMatrix &, int=1, int=ALL_STRAINS) override
void computeGaussPoints() override
tet21ghostsolid(int n, Domain *d)
void computeBoundarySurfaceLoadVector(FloatArray &answer, BoundaryLoad *load, int boundary, CharType type, ValueModeType mode, TimeStep *tStep, bool global=true) override
static IntArray momentum_ordering
Ordering of momentum balance equations in element. Used to assemble the element stiffness.
virtual void computeNumericStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
void computeLoadVector(FloatArray &answer, BodyLoad *load, CharType type, ValueModeType mode, TimeStep *tStep) override
void giveDofManDofIDMask(int inode, IntArray &answer) const override
void computeBHmatrixAt(GaussPoint *, FloatMatrix &) override
void computeStiffnessMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep) override
void computeStressVector(FloatArray &answer, const FloatArray &strain, GaussPoint *gp, TimeStep *tStep) override
#define OOFEM_ERROR(...)
Definition error.h:79
@ SpatialLocalizerInterfaceType
@ NodalAveragingRecoveryModelInterfaceType
@ EIPrimaryUnknownMapperInterfaceType
#define VELOCITYCOEFF

This page is part of the OOFEM-3.0 documentation. Copyright Copyright (C) 1994-2025 Borek Patzak Bořek Patzák
Project e-mail: oofem@fsv.cvut.cz
Generated at for OOFEM by doxygen 1.15.0 written by Dimitri van Heesch, © 1997-2011