OOFEM 3.0
Loading...
Searching...
No Matches
tr21_2d_supg.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
35#include "tr21_2d_supg.h"
36#include "fei2dtrquad.h"
37#include "fei2dtrlin.h"
38#include "node.h"
39#include "material.h"
40#include "gausspoint.h"
42#include "floatmatrix.h"
43#include "floatarray.h"
44#include "intarray.h"
45#include "mathfem.h"
47#include "fluidcrosssection.h"
48#include "timestep.h"
49#include "contextioerr.h"
50#include "crosssection.h"
51#include "classfactory.h"
52#include "engngm.h"
53
54#ifdef __OOFEG
55 #include "oofeggraphiccontext.h"
56 #include "connectivitytable.h"
57#endif
58
59namespace oofem {
61
62FEI2dTrQuad TR21_2D_SUPG :: velocityInterpolation(1, 2);
63FEI2dTrLin TR21_2D_SUPG :: pressureInterpolation(1, 2);
64
65
66TR21_2D_SUPG :: TR21_2D_SUPG(int n, Domain *aDomain) :
68{
70}
71
73TR21_2D_SUPG :: giveInterpolation() const
74{
75 return & this->velocityInterpolation;
76}
77
79TR21_2D_SUPG :: giveInterpolation(DofIDItem id) const
80{
81 if ( id == P_f ) {
82 return & this->pressureInterpolation;
83 } else {
84 return & this->velocityInterpolation;
85 }
86}
87
88int
89TR21_2D_SUPG :: computeNumberOfDofs()
90{
91 return 15;
92}
93
94void
95TR21_2D_SUPG :: giveDofManDofIDMask(int inode, IntArray &answer) const
96{
97 if ( inode < 4 ) {
98 answer = {V_u, V_v, P_f};
99 } else {
100 answer = {V_u, V_v};
101 }
102}
103
104void
105TR21_2D_SUPG :: computeGaussPoints()
106// Sets up the array containing the four Gauss points of the receiver.
107{
108 if ( integrationRulesArray.size() == 0 ) {
109 integrationRulesArray.resize(3);
110
111 integrationRulesArray [ 0 ] = std::make_unique<GaussIntegrationRule>(1, this, 1, 3);
112 this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 3, this);
113
114 //seven point Gauss integration
115 integrationRulesArray [ 1 ] = std::make_unique<GaussIntegrationRule>(2, this, 1, 3);
116 this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 1 ], 7, this);
117
118 integrationRulesArray [ 2 ] = std::make_unique<GaussIntegrationRule>(3, this, 1, 3);
119 this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 2 ], 13, this);
120
121
122 //integrationRulesArray [ 3 ] = std::make_unique<GaussIntegrationRule>(4, this, 1, 3);
123 //this->giveCrossSection()->setupIntegrationPoints( *integrationRulesArray[3], 27, this );
124 }
125}
126
127
128void
129TR21_2D_SUPG :: computeDeviatoricStress(FloatArray &answer, const FloatArray &eps, GaussPoint *gp, TimeStep *tStep)
130{
131 answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D(eps, gp, tStep);
132}
133
134
135void
136TR21_2D_SUPG :: computeTangent(FloatMatrix &answer, MatResponseMode mode, GaussPoint *gp, TimeStep *tStep)
137{
138 answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D(mode, gp, tStep);
139}
140
141
142void
143TR21_2D_SUPG :: computeNuMatrix(FloatMatrix &answer, GaussPoint *gp)
144{
145 FloatArray n;
146
148
149 answer.beNMatrixOf(n, 2);
150}
151
152void
153TR21_2D_SUPG :: computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep)
154{
155 FloatMatrix n, dn;
156 FloatArray u, un;
158 this->computeNuMatrix(n, gp);
159 this->computeVectorOfVelocities(VM_Total, tStep, un);
160
161 u.beProductOf(n, un);
162
163 answer.resize(2, 12);
164 answer.zero();
165 for ( int i = 1; i <= 6; i++ ) {
166 answer.at(1, 2 * i - 1) = dn.at(i, 1) * u.at(1) + dn.at(i, 2) * u.at(2);
167 answer.at(2, 2 * i) = dn.at(i, 1) * u.at(1) + dn.at(i, 2) * u.at(2);
168 }
169}
170
171void
172TR21_2D_SUPG :: computeBMatrix(FloatMatrix &answer, GaussPoint *gp)
173{
174 FloatMatrix dn;
176
177 answer.resize(3, 12);
178 answer.zero();
179
180 for ( int i = 1; i <= 6; i++ ) {
181 answer.at(1, 2 * i - 1) = dn.at(i, 1);
182 answer.at(2, 2 * i) = dn.at(i, 2);
183 answer.at(3, 2 * i - 1) = dn.at(i, 2);
184 answer.at(3, 2 * i) = dn.at(i, 1);
185 }
186}
187
188void
189TR21_2D_SUPG :: computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp)
190{
191 FloatMatrix dn;
193
194 answer.resize(1, 12);
195 answer.zero();
196
197 for ( int i = 1; i <= 6; i++ ) {
198 answer.at(1, 2 * i - 1) = dn.at(i, 1);
199 answer.at(1, 2 * i) = dn.at(i, 2);
200 }
201}
202
203void
204TR21_2D_SUPG :: computeNpMatrix(FloatMatrix &answer, GaussPoint *gp)
205{
206 FloatArray n;
208
209 answer.resize(1, 3);
210 answer.zero();
211
212 answer.at(1, 1) = n.at(1);
213 answer.at(1, 2) = n.at(2);
214 answer.at(1, 3) = n.at(3);
215}
216
217
218void
219TR21_2D_SUPG :: computeGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep)
220{
221 FloatArray u;
222 FloatMatrix dn, um(2, 6);
223 this->computeVectorOfVelocities(VM_Total, tStep, u);
224
226 for ( int i = 1; i <= 6; i++ ) {
227 um.at(1, i) = u.at(2 * i - 1);
228 um.at(2, i) = u.at(2 * i);
229 }
230
231 answer.beProductOf(um, dn);
232}
233
234void
235TR21_2D_SUPG :: computeGradPMatrix(FloatMatrix &answer, GaussPoint *gp)
236{
237 FloatMatrix dn;
239
240 answer.beTranspositionOf(dn);
241}
242
243
244
245void
246TR21_2D_SUPG :: computeDivTauMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep)
247{
248 FloatMatrix d2n;
249
250 this->velocityInterpolation.evald2Ndx2( d2n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
251
252 auto D = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeTangent2D(TangentStiffness, integrationRulesArray [ 0 ]->getIntegrationPoint(0), tStep);
253
254 answer.resize(2, 12);
255 answer.zero();
256 for ( int i = 1; i <= 6; i++ ) {
257 answer.at(1, 2 * i - 1) = D.at(1, 1) * d2n.at(i, 1) + D.at(1, 3) * d2n.at(i, 3) + D.at(3, 1) * d2n.at(i, 3) + D.at(3, 3) * d2n.at(i, 2);
258 answer.at(1, 2 * i) = D.at(1, 2) * d2n.at(i, 3) + D.at(1, 3) * d2n.at(i, 1) + D.at(3, 2) * d2n.at(i, 2) + D.at(3, 3) * d2n.at(i, 3);
259 answer.at(2, 2 * i - 1) = D.at(2, 1) * d2n.at(i, 3) + D.at(2, 3) * d2n.at(i, 2) + D.at(3, 1) * d2n.at(i, 1) + D.at(3, 3) * d2n.at(i, 3);
260 answer.at(2, 2 * i) = D.at(2, 2) * d2n.at(i, 2) + D.at(2, 3) * d2n.at(i, 3) + D.at(3, 2) * d2n.at(i, 3) + D.at(3, 3) * d2n.at(i, 1);
261 }
262}
263
264
265void
266TR21_2D_SUPG :: updateStabilizationCoeffs(TimeStep *tStep)
267{
268 double mu_min, norm_N, norm_N_d, norm_M_d, norm_LSIC;
269 FloatMatrix N, N_d, M_d, LSIC;
270 FloatArray u;
271 mu_min = 1;
272 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
273 double mu = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->giveEffectiveViscosity(gp, tStep);
274 if ( mu_min > mu ) {
275 mu_min = mu;
276 }
277 }
278
279 //this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), un);
280 this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), u);
281
282 this->computeAdvectionTerm(N, tStep);
283 this->computeAdvectionDeltaTerm(N_d, tStep);
284 this->computeMassDeltaTerm(M_d, tStep);
285 this->computeLSICTerm(LSIC, tStep);
286
287 norm_N = N.computeFrobeniusNorm();
288 norm_N_d = N_d.computeFrobeniusNorm();
289 norm_M_d = M_d.computeFrobeniusNorm();
290 norm_LSIC = LSIC.computeFrobeniusNorm();
291
292 if ( ( norm_N == 0 ) || ( norm_N_d == 0 ) || ( norm_M_d == 0 ) ) {
293 t_supg = 0;
294 } else {
295 //t_supg = 1. / sqrt( 1. / ( t_s1 * t_s1 ) + 1. / ( t_s2 * t_s2 ) + 1. / ( t_s3 * t_s3 ) );
296 t_supg = 0;
297 }
298
299 if ( norm_LSIC == 0 ) {
300 t_lsic = 0;
301 } else {
302 //t_lsic = norm_N / norm_LSIC;
303
304 t_lsic = 0;
305 }
306
307 t_pspg = 0;
308}
309
310
311
312void
313TR21_2D_SUPG :: computeAdvectionTerm(FloatMatrix &answer, TimeStep *tStep)
314{
315 FloatMatrix n, b;
316
317 answer.clear();
318
319 /* consistent part + supg stabilization term */
320 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
321 this->computeNuMatrix(n, gp);
322 this->computeUDotGradUMatrix(b, gp, tStep);
323 double dV = this->computeVolumeAround(gp);
324 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
325 answer.plusProductUnsym(n, b, rho * dV);
326 }
327}
328
329
330void
331TR21_2D_SUPG :: computeAdvectionDeltaTerm(FloatMatrix &answer, TimeStep *tStep)
332{
333 FloatMatrix n, b;
334
335 answer.clear();
336
337 /* consistent part + supg stabilization term */
338 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
339 this->computeNuMatrix(n, gp);
340 this->computeUDotGradUMatrix(b, gp, tStep);
341 double dV = this->computeVolumeAround(gp);
342 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
343
344 answer.plusProductUnsym(b, b, rho * dV);
345 }
346}
347
348
349
350void
351TR21_2D_SUPG :: computeMassDeltaTerm(FloatMatrix &answer, TimeStep *tStep)
352{
353 FloatMatrix n, b;
354
355 answer.clear();
356
357 /* mtrx for computing t_supg, norm of this mtrx is computed */
358 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
359 this->computeNuMatrix(n, gp);
360 this->computeUDotGradUMatrix(b, gp, tStep);
361 double dV = this->computeVolumeAround(gp);
362 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
363
364 answer.plusProductUnsym(b, n, rho * dV);
365 }
366}
367
368void
369TR21_2D_SUPG :: computeLSICTerm(FloatMatrix &answer, TimeStep *tStep)
370{
371 FloatMatrix b;
372
373 answer.clear();
374
375 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
376 double dV = this->computeVolumeAround(gp);
377 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
378 this->computeDivUMatrix(b, gp);
379
380 answer.plusProductSymmUpper(b, b, dV * rho);
381 }
382
383 answer.symmetrized();
384}
385
386
387int
388TR21_2D_SUPG :: giveNumberOfSpatialDimensions()
389{
390 return 2;
391}
392
393
394double
395TR21_2D_SUPG :: computeCriticalTimeStep(TimeStep *tStep)
396{
397 return 1.e6;
398}
399
400
401double
402TR21_2D_SUPG :: LS_PCS_computeF(LevelSetPCS *ls, TimeStep *tStep)
403{
404 double answer = 0.0, vol = 0.0;
405 FloatMatrix n, dn;
406 FloatArray fi(6), u, un, gfi;
407
408 this->computeVectorOfVelocities(VM_Total, tStep, un);
409
410 for ( int i = 1; i <= 6; i++ ) {
411 fi.at(i) = ls->giveLevelSetDofManValue( dofManArray.at(i) );
412 }
413
414 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
415 double dV = this->computeVolumeAround(gp);
416 velocityInterpolation.evaldNdx( dn, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
417 this->computeNuMatrix(n, gp);
418 u.beProductOf(n, un);
419 gfi.beTProductOf(dn, fi);
420
421 vol += dV;
422 answer += dV * u.dotProduct(gfi) / gfi.computeNorm();
423 }
424
425 return answer / vol;
426}
427
428void
429TR21_2D_SUPG :: LS_PCS_computedN(FloatMatrix &answer)
430{
431 FloatMatrix dn;
432
433 answer.clear();
434
435 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
436
437 velocityInterpolation.evaldNdx( dn, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
438
439 answer.add(dn);
440 }
441}
442
443void
444TR21_2D_SUPG :: LS_PCS_computeVolume(double &answer, const FloatArray **coordinates)
445{
446 //double answer = 0.0;
447 answer = 0.0;
448
449 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
450 //answer += this->computeVolumeAround(gp);
451
452 double determinant, weight, volume;
453
454 determinant = fabs( this->velocityInterpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) );
455
456 weight = gp->giveWeight();
457 volume = determinant * weight;
458
459 answer += volume;
460 }
461}
462
463
464double
465TR21_2D_SUPG :: LS_PCS_computeVolume()
466{
467 double answer = 0.0;
468
469 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
470 answer += this->computeVolumeAround(gp);
471 }
472
473 return answer;
474}
475
476double
477TR21_2D_SUPG :: LS_PCS_computeS(LevelSetPCS *ls, TimeStep *tStep)
478{
479 FloatArray fi(6), un, n;
480
481 double vol = 0.0, eps = 0.0, _fi, S = 0.0;
482
483 for ( int i = 1; i <= 6; i++ ) {
484 fi.at(i) = ls->giveLevelSetDofManValue( dofManArray.at(i) );
485 }
486
487 for ( GaussPoint *gp: *integrationRulesArray [ 1 ] ) {
488 double dV = this->computeVolumeAround(gp);
489 velocityInterpolation.evalN( n, gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) );
490 vol += dV;
491 _fi = n.dotProduct(fi);
492 S += _fi / ( _fi * _fi + eps * eps ) * dV;
493 }
494
495 return S / vol;
496}
497
498
499
500void
501TR21_2D_SUPG :: LS_PCS_computeVOFFractions(FloatArray &answer, FloatArray &fi)
502{
503 int neg = 0, pos = 0, zero = 0, si = 0, sqi = 0;
504
505
506 answer.resize(2);
507
508 for ( double ifi: fi ) { //comparing values of fi in vertices
509 if ( ifi > 0. ) {
510 pos++;
511 } else if ( ifi < 0.0 ) {
512 neg++;
513 } else {
514 zero++;
515 }
516 }
517
518 //control !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
519 int first_control = 0;
520 first_control = this->giveNumber();
521 OOFEM_LOG_INFO("TR21_2D_SUPG :: LS_PCS_computeVOFFractions - First control, sign(fi) in vertices, element no. %d", first_control);
522
523
524
525 if ( neg == 0 ) { // all level set values positive
526 answer.at(1) = 1.0;
527 answer.at(2) = 0.0;
528 } else if ( pos == 0 ) { // all level set values negative
529 answer.at(1) = 0.0;
530 answer.at(2) = 1.0;
531 } else if ( zero == 3 ) {
532 // ???????
533 answer.at(1) = 1.0;
534 answer.at(2) = 0.0;
535 } else {
536 // zero level set inside
537 // three main cases of crossing the triangle are possible
538
539 int inter_case, negq = 0, posq = 0, zeroq = 0; //inter_case is variable that differs type of which fi crosses the triangle
540
541 for ( double ifi: fi ) { //loop over edge nodes
542 if ( ifi > 0. ) {
543 posq++;
544 } else if ( ifi < 0.0 ) {
545 negq++;
546 } else {
547 zeroq++;
548 }
549 }
550
551 for ( int i = 1; i <= 3; i++ ) { //loop over vertex nodes, searching for which vertex has different value of fi
552 if ( ( pos > neg ) && ( fi.at(i) < 0.0 ) ) {
553 si = i;
554 break;
555 }
556
557 if ( ( pos < neg ) && ( fi.at(i) >= 0.0 ) ) {
558 si = i;
559 break;
560 }
561 }
562
563
564
565 for ( int i = 4; i <= 6; i++ ) { //loop over edge nodes, searching for which edge node has different value of fi
566 if ( ( posq > negq ) && ( fi.at(i) < 0.0 ) ) {
567 sqi = i;
568 break;
569 }
570
571 if ( ( posq < negq ) && ( fi.at(i) >= 0.0 ) ) {
572 sqi = i;
573 break;
574 }
575 }
576
577 if ( negq == 0 ) {
578 inter_case = 11; //only one node has different level set value from other five
579 } else if ( posq == 0 ) {
580 inter_case = 12; //only one node has different level set value from other five
581 } else { // level set devides element 2:4 or 3:3 nodes
582 if ( fi.at(si) * fi.at(sqi) > 0 ) {
583 inter_case = 2;
584 } else {
585 inter_case = 3;
586 }
587 }
588
589
590 int edge1 = 0, edge2 = 0;
591 FloatArray helplcoords(3);
592
593
594 if ( inter_case > 3 ) { //only one node (vertex in this case) of triangle has diffenert level set value, than others
595 FloatArray inter1(2), inter2(2);
596
597 //kontrola!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
598 int second_control1;
599 second_control1 = this->giveNumber();
600 OOFEM_LOG_INFO("TR21_2D_SUPG :: LS_PCS_computeVOFFractions - case 1 - first type of element deviation by LS, element no. %d", second_control1);
601
602
603
604
605 if ( si == 1 ) { // computing intersection points in order to vertex with different sign of level set funct
606 this->computeIntersection(1, inter1, fi);
607
608
609 this->computeIntersection(3, inter2, fi);
610
611 edge1 = 1;
612 edge2 = 3;
613 } else if ( si == 2 ) {
614 this->computeIntersection(2, inter1, fi);
615
616
617 this->computeIntersection(1, inter2, fi);
618
619 edge1 = 2;
620 edge2 = 1;
621 } else if ( si == 3 ) {
622 this->computeIntersection(3, inter1, fi);
623
624
625 this->computeIntersection(2, inter2, fi);
626
627 edge1 = 3;
628 edge2 = 2;
629 }
630
631
632
633
634 OOFEM_LOG_INFO("case 1 - after intersections of LS and edges, element no. %d", second_control1);
635
636
637
638 //computing point on zero level set curve: [xM, yM]
639 // this point lies on line from the "si" vertex, the condition is fi([xM, yM]) = 0, M = [xM, yM]
640
641 FloatArray _l(4), M(2), X_si(2), _Mid(2), line(6), _X1(2), Mid1(2), Mid2(2), Coeff(3), loc_Mid(3), loc_X1(3), N_Mid, N_X1;
642 double x1, xsi, y1, ysi, t, fi_X1, fi_Mid, r1, r11, r12;
643
644 _l.at(1) = inter1.at(1);
645 _l.at(2) = inter1.at(2);
646 _l.at(3) = inter2.at(1);
647 _l.at(4) = inter2.at(2);
648
649 this->computeCenterOf(_Mid, _l, 1);
650
651 xsi = this->giveNode(si)->giveCoordinate(1);
652 ysi = this->giveNode(si)->giveCoordinate(2);
653
654 X_si.at(1) = xsi;
655 X_si.at(2) = ysi;
656
657 x1 = xsi + 2 * ( _Mid.at(1) - xsi );
658 y1 = ysi + 2 * ( _Mid.at(2) - ysi );
659
660 _X1.at(1) = x1;
661
662 _X1.at(2) = y1;
663
664 this->velocityInterpolation.global2local( loc_Mid, _Mid, FEIElementGeometryWrapper(this) );
665 this->velocityInterpolation.global2local( loc_X1, _X1, FEIElementGeometryWrapper(this) );
666
667 this->velocityInterpolation.evalN( N_Mid, loc_Mid, FEIElementGeometryWrapper(this) );
668 this->velocityInterpolation.evalN( N_X1, loc_X1, FEIElementGeometryWrapper(this) );
669
670 fi_Mid = N_Mid.dotProduct(fi);
671 fi_X1 = N_X1.dotProduct(fi);
672
673 line.at(1) = 0;
674 line.at(2) = fi.at(si);
675 line.at(3) = sqrt( ( _Mid.at(1) - xsi ) * ( _Mid.at(1) - xsi ) + ( _Mid.at(2) - ysi ) * ( _Mid.at(2) - ysi ) );
676 line.at(4) = fi_Mid;
677 line.at(5) = sqrt( ( _Mid.at(1) - _X1.at(1) ) * ( _Mid.at(1) - _X1.at(1) ) + ( _Mid.at(2) - _X1.at(2) ) * ( _Mid.at(2) - _X1.at(2) ) );
678 line.at(6) = fi_X1;
679
680 this->computeQuadraticFunct(Coeff, line);
681
682 this->computeQuadraticRoots(Coeff, r11, r12);
683
684 if ( r11 > line.at(6) || r11 < line.at(1) ) {
685 r1 = r12;
686 } else {
687 r1 = r11;
688 }
689
690 t = r1 / sqrt( ( _Mid.at(1) - xsi ) * ( _Mid.at(1) - xsi ) + ( _Mid.at(2) - ysi ) * ( _Mid.at(2) - ysi ) );
691
692 M.at(1) = xsi + t * ( _Mid.at(1) - xsi );
693 M.at(2) = ysi + t * ( _Mid.at(2) - ysi );
694
695
696 OOFEM_LOG_INFO("case 1 - after computing third point on zero level set curve inside element, element no. %d", second_control1);
697
698
699
700 //computing middle points to get six-point triangle
701 FloatArray borderpoints(4);
702
703 borderpoints.at(1) = xsi;
704 borderpoints.at(2) = ysi;
705 borderpoints.at(3) = inter1.at(1);
706 borderpoints.at(4) = inter1.at(2);
707
708 this->computeMiddlePointOnParabolicArc(Mid1, edge1, borderpoints);
709
710 borderpoints.at(1) = xsi;
711 borderpoints.at(2) = ysi;
712 borderpoints.at(3) = inter2.at(1);
713 borderpoints.at(4) = inter2.at(2);
714
715
716 this->computeMiddlePointOnParabolicArc(Mid2, edge2, borderpoints);
717
718
719 const FloatArray *c1 [ 6 ];
720
721
722
723
724 double vol_1, vol;
725
726 c1 [ 0 ] = & X_si;
727 c1 [ 1 ] = & inter1;
728 c1 [ 2 ] = & inter2;
729 c1 [ 3 ] = & Mid1;
730 c1 [ 4 ] = & M;
731 c1 [ 5 ] = & Mid2;
732
733
734 //volume of small triangle
735 this->LS_PCS_computeVolume(vol_1, c1);
736 //volume of whole triangle
737 vol = LS_PCS_computeVolume();
738
739
740
741
742 if ( inter_case == 11 ) {
743 answer.at(2) = vol_1 / vol;
744 answer.at(1) = 1.0 - answer.at(2);
745 } else {
746 answer.at(1) = vol_1 / vol;
747 answer.at(2) = 1.0 - answer.at(1);
748 }
749 } //end case inter_case > 3
750 else if ( inter_case == 2 ) {
751 //kontrola!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
752 int second_control2 = 0;
753 second_control2 = this->giveNumber();
754 OOFEM_LOG_INFO("case 2 - second type of element deviation by LS, element no. %d", second_control2);
755
756
757 FloatArray inter1(2), inter2(2), crosssect(4);
758 crosssect.zero();
759
760 if ( si == 1 ) { // computing intersection points in order to vertex with different sign of level set funct
761 this->computeIntersection(1, inter1, fi);
762
763 this->computeIntersection(3, inter2, fi);
764
765 edge1 = 1;
766 edge2 = 3;
767 } else if ( si == 2 ) {
768 this->computeIntersection(2, inter1, fi);
769
770 this->computeIntersection(1, inter2, fi);
771
772 edge1 = 2;
773 edge2 = 1;
774 } else if ( si == 3 ) {
775 this->computeIntersection(3, inter1, fi);
776
777 this->computeIntersection(2, inter2, fi);
778
779 edge1 = 3;
780 edge2 = 2;
781 }
782
783 //computing point on zero level set curve: [xM, yM]
784 // this point lies on line from the "si" vertex, the condition is fi([xM, yM]) = 0
785 FloatArray X_qsi(2), X_si(2), _Mid(2), line(6), _X1(2), Mid1(2), Coeff(3), loc_Mid, loc_X1, N_Mid, N_X1, M(2);
786 double x1, xsi, y1, ysi, t, fi_X1, fi_Mid, r1, r11, r12;
787 this->computeCenterOf(_Mid, crosssect, 1);
788
789 xsi = this->giveNode(si)->giveCoordinate(1);
790 ysi = this->giveNode(si)->giveCoordinate(2);
791
792 X_si.at(1) = xsi;
793 X_si.at(2) = ysi;
794
795 X_qsi.at(1) = this->giveNode(sqi)->giveCoordinate(1);
796 X_qsi.at(2) = this->giveNode(sqi)->giveCoordinate(2);
797
798
799 x1 = xsi + 1.3 * ( _Mid.at(1) - xsi );
800 y1 = ysi + 1.3 * ( _Mid.at(2) - ysi );
801
802 _X1.at(1) = x1;
803 _X1.at(2) = y1;
804
805 this->velocityInterpolation.global2local( loc_Mid, _Mid, FEIElementGeometryWrapper(this) );
806 this->velocityInterpolation.global2local( loc_X1, _X1, FEIElementGeometryWrapper(this) );
807
808 this->velocityInterpolation.evalN( N_Mid, loc_Mid, FEIElementGeometryWrapper(this) );
809 this->velocityInterpolation.evalN( N_X1, loc_X1, FEIElementGeometryWrapper(this) );
810
811 fi_Mid = N_Mid.dotProduct(fi);
812 fi_X1 = N_X1.dotProduct(fi);
813
814 line.at(1) = 0;
815 line.at(2) = fi.at(si);
816 line.at(3) = sqrt( ( _Mid.at(1) - xsi ) * ( _Mid.at(1) - xsi ) + ( _Mid.at(2) - ysi ) * ( _Mid.at(2) - ysi ) );
817 line.at(4) = fi_Mid;
818 line.at(5) = sqrt( ( _Mid.at(1) - _X1.at(1) ) * ( _Mid.at(1) - _X1.at(1) ) + ( _Mid.at(2) - _X1.at(2) ) * ( _Mid.at(2) - _X1.at(2) ) );
819 line.at(6) = fi_X1;
820
821 this->computeQuadraticFunct(Coeff, line);
822
823 this->computeQuadraticRoots(Coeff, r11, r12);
824
825 if ( r11 > line.at(6) || r11 < line.at(1) ) {
826 r1 = r12;
827 } else {
828 r1 = r11;
829 }
830
831 t = r1 / sqrt( ( _Mid.at(1) - xsi ) * ( _Mid.at(1) - xsi ) + ( _Mid.at(2) - ysi ) * ( _Mid.at(2) - ysi ) );
832
833 M.at(1) = xsi + t * ( _Mid.at(1) - xsi );
834 M.at(2) = ysi + t * ( _Mid.at(2) - ysi );
835
836 //computing middle points to get six-point triangle
837 FloatArray borderpoints(4);
838 int sub_case = 0;
839 if ( ( si == 1 ) && ( sqi == 4 ) ) {
840 borderpoints.at(1) = xsi;
841 borderpoints.at(2) = ysi;
842 borderpoints.at(3) = inter2.at(1);
843 borderpoints.at(4) = inter2.at(2);
844 sub_case = 2;
845
846 this->computeMiddlePointOnParabolicArc(Mid1, edge2, borderpoints);
847 }
848
849 if ( ( si == 1 ) && ( sqi == 6 ) ) {
850 borderpoints.at(1) = xsi;
851 borderpoints.at(2) = ysi;
852 borderpoints.at(3) = inter1.at(1);
853 borderpoints.at(4) = inter1.at(2);
854 sub_case = 1;
855 this->computeMiddlePointOnParabolicArc(Mid1, edge1, borderpoints);
856 }
857
858 if ( ( si == 2 ) && ( sqi == 4 ) ) {
859 borderpoints.at(1) = xsi;
860 borderpoints.at(2) = ysi;
861 borderpoints.at(3) = inter1.at(1);
862 borderpoints.at(4) = inter1.at(2);
863 sub_case = 1;
864 this->computeMiddlePointOnParabolicArc(Mid1, edge1, borderpoints);
865 }
866
867 if ( ( si == 2 ) && ( sqi == 5 ) ) {
868 borderpoints.at(1) = xsi;
869 borderpoints.at(2) = ysi;
870 borderpoints.at(3) = inter2.at(1);
871 borderpoints.at(4) = inter2.at(2);
872 sub_case = 2;
873 this->computeMiddlePointOnParabolicArc(Mid1, edge2, borderpoints);
874 }
875
876 if ( ( si == 3 ) && ( sqi == 6 ) ) {
877 borderpoints.at(1) = xsi;
878 borderpoints.at(2) = ysi;
879 borderpoints.at(3) = inter2.at(1);
880 borderpoints.at(4) = inter2.at(2);
881 sub_case = 2;
882 this->computeMiddlePointOnParabolicArc(Mid1, edge2, borderpoints);
883 }
884
885 if ( ( si == 3 ) && ( sqi == 5 ) ) {
886 borderpoints.at(1) = xsi;
887 borderpoints.at(2) = ysi;
888 borderpoints.at(3) = inter1.at(1);
889 borderpoints.at(4) = inter1.at(2);
890 sub_case = 1;
891 this->computeMiddlePointOnParabolicArc(Mid1, edge1, borderpoints);
892 }
893
894 const FloatArray *c1 [ 6 ];
895
896
897
898 double vol_1, vol;
899
900
901
902 if ( sub_case == 1 ) {
903 c1 [ 0 ] = & X_si;
904 c1 [ 1 ] = & inter1;
905 c1 [ 2 ] = & inter2;
906 c1 [ 3 ] = & Mid1;
907 c1 [ 4 ] = & M;
908 c1 [ 5 ] = & X_qsi;
909 } else {
910 c1 [ 0 ] = & X_si;
911 c1 [ 1 ] = & inter1;
912 c1 [ 2 ] = & inter2;
913 c1 [ 3 ] = & X_qsi;
914 c1 [ 4 ] = & M;
915 c1 [ 5 ] = & Mid1;
916
917
918
919 //volume of small triangle
920 this->LS_PCS_computeVolume(vol_1, c1);
921 //volume of whole triangle
922 vol = LS_PCS_computeVolume();
923
924
925
926 if ( fi(si) < 0 ) {
927 answer.at(2) = vol_1 / vol;
928 answer.at(1) = 1.0 - answer.at(2);
929 } else {
930 answer.at(1) = vol_1 / vol;
931 answer.at(2) = 1.0 - answer.at(1);
932 }
933 } //end case inter_case == 2
934 } else { //inter_case == 3
935 //kontrola!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
936 int second_control3 = 0;
937 second_control3 = this->giveNumber();
938 OOFEM_LOG_INFO("case 3 - third type of element deviation by LS, element no. %d", second_control3);
939
940
941 FloatArray inter1(2), inter2(2), crosssect(4);
942 crosssect.zero();
943
944 if ( si == 1 ) { // computing intersection points in order to vertex with different sign of level set funct
945 this->computeIntersection(1, inter1, fi);
946
947 this->computeIntersection(3, inter2, fi);
948
949 //edge1 = 1;
950 //edge2 = 3;
951 } else if ( si == 2 ) {
952 this->computeIntersection(2, inter1, fi);
953
954
955 this->computeIntersection(1, inter2, fi);
956
957 //edge1 = 2;
958 //edge2 = 1;
959 } else if ( si == 3 ) {
960 this->computeIntersection(3, inter1, fi);
961
962
963 this->computeIntersection(2, inter2, fi);
964
965 //edge1 = 3;
966 //edge2 = 2;
967 }
968
969 //computing point on zero level set curve: [xM, yM]
970 // this point lies on line from the "si" vertex, the condition is fi([xM, yM]) = 0
971 FloatArray X_si(2), M(2), _Mid(2), line(6), _X1(2), Mid1(2), Coeff(3), loc_Mid, loc_X1, N_Mid, N_X1;
972 double x1, xsi, y1, ysi, t, fi_X1, fi_Mid, r1, r11, r12;
973 this->computeCenterOf(_Mid, crosssect, 1);
974
975 xsi = this->giveNode(si)->giveCoordinate(1);
976 ysi = this->giveNode(si)->giveCoordinate(2);
977
978 X_si.at(1) = xsi;
979 X_si.at(2) = ysi;
980
981 x1 = xsi + 0.5 * ( _Mid.at(1) - xsi );
982 y1 = ysi + 0.5 * ( _Mid.at(2) - ysi );
983
984 _X1.at(1) = x1;
985 _X1.at(2) = y1;
986
987 this->velocityInterpolation.global2local( loc_Mid, _Mid, FEIElementGeometryWrapper(this) );
988 this->velocityInterpolation.global2local( loc_X1, _X1, FEIElementGeometryWrapper(this) );
989
990 this->velocityInterpolation.evalN( N_Mid, loc_Mid, FEIElementGeometryWrapper(this) );
991 this->velocityInterpolation.evalN( N_X1, loc_X1, FEIElementGeometryWrapper(this) );
992
993 fi_Mid = N_Mid.dotProduct(fi);
994 fi_X1 = N_X1.dotProduct(fi);
995
996 line.at(1) = 0;
997 line.at(2) = fi.at(si);
998 line.at(3) = sqrt( ( _Mid.at(1) - xsi ) * ( _Mid.at(1) - xsi ) + ( _Mid.at(2) - ysi ) * ( _Mid.at(2) - ysi ) );
999 line.at(4) = fi_Mid;
1000 line.at(5) = sqrt( ( _Mid.at(1) - _X1.at(1) ) * ( _Mid.at(1) - _X1.at(1) ) + ( _Mid.at(2) - _X1.at(2) ) * ( _Mid.at(2) - _X1.at(2) ) );
1001 line.at(6) = fi_X1;
1002
1003 this->computeQuadraticFunct(Coeff, line);
1004
1005 this->computeQuadraticRoots(Coeff, r11, r12);
1006
1007 if ( r11 > line.at(6) || r11 < line.at(1) ) {
1008 r1 = r12;
1009 } else {
1010 r1 = r11;
1011 }
1012
1013 t = r1 / sqrt( ( _Mid.at(1) - xsi ) * ( _Mid.at(1) - xsi ) + ( _Mid.at(2) - ysi ) * ( _Mid.at(2) - ysi ) );
1014
1015 M.at(1) = xsi + t * ( _Mid.at(1) - xsi );
1016 M.at(2) = ysi + t * ( _Mid.at(2) - ysi );
1017
1018
1019 FloatArray X_e1(2), X_e2(2); //points on edges close to the vertex si, "quadratic" nodes
1020 double vol_1, vol;
1021
1022 X_e1.at(1) = this->giveNode(si + 3)->giveCoordinate(1);
1023 X_e1.at(2) = this->giveNode(si + 3)->giveCoordinate(2);
1024
1025 X_e2.at(1) = this->giveNode( ( ( si + 4 ) % 3 ) + 4 )->giveCoordinate(1);
1026 X_e2.at(2) = this->giveNode( ( ( si + 4 ) % 3 ) + 4 )->giveCoordinate(2);
1027
1028
1029
1030
1031 const FloatArray *c1 [ 6 ];
1032
1033
1034 c1 [ 0 ] = & X_si;
1035 c1 [ 1 ] = & inter1;
1036 c1 [ 2 ] = & inter2;
1037 c1 [ 3 ] = & X_e1;
1038 c1 [ 4 ] = & M;
1039 c1 [ 5 ] = & X_e2;
1040
1041
1042 //volume of small triangle
1043 this->LS_PCS_computeVolume(vol_1, c1);
1044 //volume of whole triangle
1045 vol = LS_PCS_computeVolume();
1046
1047
1048
1049
1050 if ( fi(si) < 0 ) {
1051 answer.at(2) = vol_1 / vol;
1052 answer.at(1) = 1.0 - answer.at(2);
1053 } else {
1054 answer.at(1) = vol_1 / vol;
1055 answer.at(2) = 1.0 - answer.at(1);
1056 }
1057 }
1058 }
1059}
1060
1061void
1062TR21_2D_SUPG :: computeIntersection(int iedge, FloatArray &intcoords, FloatArray &fi)
1063{
1064 FloatArray Coeff(3), helplcoords(3);
1065 double fi1, fi2, fi3, r1, r11, r12;
1066 intcoords.resize(2);
1067 intcoords.zero();
1068
1069 const auto &edge = this->velocityInterpolation.computeLocalEdgeMapping(iedge);
1070 fi1 = fi.at( edge.at(1) );
1071 fi2 = fi.at( edge.at(2) );
1072 fi3 = fi.at( edge.at(3) );
1073
1074 Coeff.at(1) = fi1 + fi2 - 2 * fi3;
1075 Coeff.at(2) = fi2 - fi1;
1076 Coeff.at(3) = 2 * fi3;
1077
1078 this->computeQuadraticRoots(Coeff, r11, r12);
1079
1080 if ( r11 > 1.0 || r11 < -1.0 ) {
1081 r1 = r12;
1082 } else {
1083 r1 = r11;
1084 }
1085
1086 helplcoords.zero();
1087 helplcoords.at(1) = r1;
1088
1089 this->velocityInterpolation.edgeLocal2global( intcoords, 3, helplcoords, FEIElementGeometryWrapper(this) );
1090
1091 //this->velocityInterpolation.evaldNdx(dn, this->giveDomain(), dofManArray, gp->giveNaturalCoordinates(),tStep->giveTime());
1092}
1093
1094
1095#if 0
1096void
1097TR21_2D_SUPG :: computeIntersection(int iedge, FloatArray &intcoords, FloatArray &fi)
1098{
1099 FloatArray Coeff(3), helplcoords(3);
1100 double fi1, fi2, fi3, r1, r11, r12;
1101
1102 intcoords.resize(2);
1103 intcoords.zero();
1104
1105 this->velocityInterpolation.computeLocalEdgeMapping(edge, iedge);
1106 fi1 = fi.at( edge.at(1) );
1107 fi2 = fi.at( edge.at(2) );
1108 fi3 = fi.at( edge.at(3) );
1109
1110 Coeff.at(1) = fi1 + fi2 - 2 * fi3;
1111 Coeff.at(2) = fi2 - fi1;
1112 Coeff.at(3) = 2 * fi3;
1113
1114 this->computeQuadraticRoots(Coeff, r11, r12);
1115
1116 if ( r11 > 1.0 || r11 < -1.0 ) {
1117 r1 = r12;
1118 } else {
1119 r1 = r11;
1120 }
1121
1122 helplcoords.zero();
1123 helplcoords.at(1) = r1;
1124
1125 this->velocityInterpolation.edgeLocal2global( intcoords, iedge, this->giveDomain(), dofManArray, helplcoords, tStep->giveTime() );
1126
1127 //this->velocityInterpolation.evaldNdx(dn, this->giveDomain(), dofManArray, gp->giveNaturalCoordinates(),tStep->giveTime());
1128}
1129#endif
1130
1131void
1132TR21_2D_SUPG :: computeMiddlePointOnParabolicArc(FloatArray &answer, int iedge, FloatArray borderpoints)
1133{
1134 double a, b, c;
1135 FloatArray Coeff, C(2);
1136
1137
1138
1139
1140 this->computeQuadraticFunct(Coeff, iedge);
1141
1142
1143 this->computeCenterOf(C, borderpoints, 1);
1144
1145 a = Coeff.at(1);
1146 b = Coeff.at(2);
1147 c = Coeff.at(3);
1148
1149 answer.at(1) = C.at(1);
1150 answer.at(2) = a * C.at(1) * C.at(1) + b *C.at(1) + c;
1151}
1152
1153
1154
1155
1156void
1157TR21_2D_SUPG :: computeCenterOf(FloatArray &C, FloatArray c, int dim)
1158{
1159 switch ( dim ) {
1160 case 1:
1161
1162 C.at(1) = ( c.at(1) + c.at(3) ) / 2;
1163 C.at(2) = ( c.at(2) + c.at(4) ) / 2;
1164
1165 break;
1166
1167 case 2:
1168
1169 C.at(1) = ( c.at(1) + c.at(3) + c.at(5) ) / 3;
1170 C.at(2) = ( c.at(2) + c.at(4) + c.at(6) ) / 3;
1171
1172 break;
1173 }
1174}
1175
1176
1177void
1178TR21_2D_SUPG :: computeQuadraticRoots(FloatArray Coeff, double &r1, double &r2)
1179{
1180 double a, b, c;
1181
1182 a = Coeff.at(1);
1183 b = Coeff.at(2);
1184 c = Coeff.at(3);
1185
1186 r1 = ( -b + sqrt(b * b - 4 * a * c) ) / ( 2 * a );
1187 r2 = ( -b - sqrt(b * b - 4 * a * c) ) / ( 2 * a );
1188}
1189
1190
1191
1192void
1193TR21_2D_SUPG :: computeCoordsOfEdge(FloatArray &answer, int iedge)
1194
1195{
1196 const auto &edge = velocityInterpolation.computeLocalEdgeMapping(iedge);
1197
1198 answer.at(1) = this->giveNode( edge.at(1) )->giveCoordinate(1);
1199 answer.at(2) = this->giveNode( edge.at(1) )->giveCoordinate(2);
1200
1201 answer.at(3) = this->giveNode( edge.at(2) )->giveCoordinate(1);
1202 answer.at(4) = this->giveNode( edge.at(2) )->giveCoordinate(2);
1203
1204 answer.at(5) = this->giveNode( edge.at(3) )->giveCoordinate(1);
1205 answer.at(6) = this->giveNode( edge.at(3) )->giveCoordinate(2);
1206}
1207
1208
1209
1210//this function computes coefficients of quadratic function a,b,c in y = a*x^2 + b*x + c
1211//iedge is number of i-th edge of quadratic triangle
1212void
1213TR21_2D_SUPG :: computeQuadraticFunct(FloatArray &answer, int iedge)
1214{
1215 double x1, y1, x2, y2, x3, y3, detA, detA1;
1216 FloatMatrix A(3, 3), A1(3, 3);
1217 FloatArray edge, crds(6);
1218
1219
1220 answer.resize(3);
1221
1222
1223
1224 this->computeCoordsOfEdge(crds, iedge);
1225
1226
1227 x1 = crds.at(1);
1228 y1 = crds.at(2);
1229 x2 = crds.at(5);
1230 y2 = crds.at(6);
1231 x3 = crds.at(3);
1232 y3 = crds.at(4);
1233
1234 A.at(1, 1) = x1 * x1;
1235 A.at(2, 1) = x2 * x2;
1236 A.at(3, 1) = x3 * x3;
1237 A.at(1, 2) = x1;
1238 A.at(2, 2) = x2;
1239 A.at(3, 2) = x3;
1240 A.at(1, 3) = 1.0;
1241 A.at(2, 3) = 1.0;
1242 A.at(3, 3) = 1.0;
1243
1244 FloatArray b(3);
1245
1246 detA = A.giveDeterminant();
1247
1248 b.at(1) = y1;
1249 b.at(2) = y2;
1250 b.at(3) = y3;
1251
1252 for ( int k = 1; k <= 3; k++ ) {
1253 for ( int i = 1; i <= 3; i++ ) {
1254 for ( int j = 1; j <= 3; j++ ) {
1255 A1.at(i, j) = A.at(i, j);
1256 }
1257
1258 A1.at(i, k) = b.at(i);
1259 }
1260
1261 detA1 = A1.giveDeterminant();
1262 answer.at(k) = detA1 / detA;
1263 }
1264}
1265
1266void
1267TR21_2D_SUPG :: computeQuadraticFunct(FloatArray &answer, FloatArray line)
1268{
1269 double x1, y1, x2, y2, x3, y3, detA, detA1;
1270 FloatMatrix A(3, 3), A1(3, 3);
1271 FloatArray edge;
1272
1273
1274 answer.resize(3);
1275
1276
1277 x1 = line.at(1);
1278 y1 = line.at(2);
1279 x2 = line.at(3);
1280 y2 = line.at(4);
1281 x3 = line.at(5);
1282 y3 = line.at(6);
1283
1284 A.at(1, 1) = x1 * x1;
1285 A.at(2, 1) = x2 * x2;
1286 A.at(3, 1) = x3 * x3;
1287 A.at(1, 2) = x1;
1288 A.at(2, 2) = x2;
1289 A.at(3, 2) = x3;
1290 A.at(1, 3) = 1.0;
1291 A.at(2, 3) = 1.0;
1292 A.at(3, 3) = 1.0;
1293
1294 FloatArray b(3);
1295
1296 detA = A.giveDeterminant();
1297
1298 b.at(1) = y1;
1299 b.at(2) = y2;
1300 b.at(3) = y3;
1301
1302 for ( int k = 1; k <= 3; k++ ) {
1303 for ( int i = 1; i <= 3; i++ ) {
1304 for ( int j = 1; j <= 3; j++ ) {
1305 A1.at(i, j) = A.at(i, j);
1306 }
1307
1308 A1.at(i, k) = b.at(i);
1309 }
1310
1311 detA1 = A1.giveDeterminant();
1312 answer.at(k) = detA1 / detA;
1313 }
1314}
1315
1316
1317void
1318TR21_2D_SUPG :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node,
1319 InternalStateType type, TimeStep *tStep)
1320{
1321 GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0);
1322 this->giveIPValue(answer, gp, type, tStep);
1323}
1324
1325
1326void
1327TR21_2D_SUPG :: initGeometry()
1328{ }
1329
1330
1331int
1332TR21_2D_SUPG :: checkConsistency()
1333{
1334 return SUPGElement :: checkConsistency();
1335}
1336
1337
1338void
1339TR21_2D_SUPG :: updateYourself(TimeStep *tStep)
1340{
1341 SUPGElement :: updateYourself(tStep);
1342}
1343
1344int
1345TR21_2D_SUPG :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
1346{
1347 return SUPGElement2 :: giveIPValue(answer, gp, type, tStep);
1348}
1349
1350void TR21_2D_SUPG :: saveContext(DataStream &stream, ContextMode mode)
1351{
1352 SUPGElement :: saveContext(stream, mode);
1353}
1354
1355void TR21_2D_SUPG :: restoreContext(DataStream &stream, ContextMode mode)
1356{
1357 SUPGElement :: restoreContext(stream, mode);
1358}
1359
1360
1361double
1362TR21_2D_SUPG :: computeVolumeAround(GaussPoint *gp)
1363// Returns the portion of the receiver which is attached to gp.
1364{
1365 double determinant, weight, volume;
1366
1367 determinant = fabs( this->velocityInterpolation.giveTransformationJacobian( gp->giveNaturalCoordinates(), FEIElementGeometryWrapper(this) ) );
1368
1369
1370 weight = gp->giveWeight();
1371 volume = determinant * weight;
1372
1373 return volume;
1374}
1375
1376
1377Interface *
1378TR21_2D_SUPG :: giveInterface(InterfaceType interface)
1379{
1380 if ( interface == LevelSetPCSElementInterfaceType ) {
1381 return static_cast< LevelSetPCSElementInterface * >(this);
1382 } else if ( interface == ZZNodalRecoveryModelInterfaceType ) {
1383 return static_cast< ZZNodalRecoveryModelInterface * >(this);
1384 } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) {
1385 return static_cast< NodalAveragingRecoveryModelInterface * >(this);
1386 }
1387
1388 return NULL;
1389}
1390
1391
1392void
1393TR21_2D_SUPG :: giveLocalVelocityDofMap(IntArray &map)
1394{
1395 map = {1, 2, 4, 5, 7, 8, 10, 11, 12, 13, 14, 15};
1396}
1397
1398void
1399TR21_2D_SUPG :: giveLocalPressureDofMap(IntArray &map)
1400{
1401 map = {3, 6, 9};
1402}
1403
1404
1405
1406
1407
1408#ifdef __OOFEG
1409int
1410TR21_2D_SUPG :: giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode,
1411 int node, TimeStep *tStep)
1412{
1413 return SUPGElement :: giveInternalStateAtNode(answer, type, mode, node, tStep);
1414}
1415
1416
1417
1418void
1419TR21_2D_SUPG :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep)
1420{
1421 WCRec p [ 3 ];
1422 GraphicObj *go;
1423
1424 if ( !gc.testElementGraphicActivity(this) ) {
1425 return;
1426 }
1427
1428 EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH);
1429 EASValsSetColor( gc.getElementColor() );
1430 EASValsSetEdgeColor( gc.getElementEdgeColor() );
1431 EASValsSetEdgeFlag(true);
1432 EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER);
1433 p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1);
1434 p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2);
1435 p [ 0 ].z = 0.;
1436 p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1);
1437 p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2);
1438 p [ 1 ].z = 0.;
1439 p [ 2 ].x = ( FPNum ) this->giveNode(3)->giveCoordinate(1);
1440 p [ 2 ].y = ( FPNum ) this->giveNode(3)->giveCoordinate(2);
1441 p [ 2 ].z = 0.;
1442
1443 go = CreateTriangle3D(p);
1444 EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go);
1445 EGAttachObject(go, ( EObjectP ) this);
1446 EMAddGraphicsToModel(ESIModel(), go);
1447}
1448
1449void TR21_2D_SUPG :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep)
1450{
1451 int i, indx, result = 0;
1452 WCRec p [ 3 ];
1453 GraphicObj *tr;
1454 FloatArray v1, v2, v3;
1455 double s [ 3 ];
1456
1457 if ( !gc.testElementGraphicActivity(this) ) {
1458 return;
1459 }
1460
1461 EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER);
1462
1463 // if ((gc.giveIntVarMode() == ISM_local) && (gc.giveIntVarType() == IST_VOFFraction)) {
1464 if ( ( gc.giveIntVarType() == IST_VOFFraction ) && ( gc.giveIntVarMode() == ISM_local ) ) {
1465 Polygon matvolpoly;
1466 //this->formMaterialVolumePoly(matvolpoly, NULL, temp_normal, temp_p, false);
1467 EASValsSetColor( gc.getStandardSparseProfileColor() );
1468 //GraphicObj *go = matvolpoly.draw(gc,true,OOFEG_VARPLOT_PATTERN_LAYER);
1469 matvolpoly.draw(gc, true, OOFEG_VARPLOT_PATTERN_LAYER);
1470 return;
1471 }
1472
1473 if ( gc.giveIntVarMode() == ISM_recovered ) {
1474 result += this->giveInternalStateAtNode(v1, gc.giveIntVarType(), gc.giveIntVarMode(), 1, tStep);
1475 result += this->giveInternalStateAtNode(v2, gc.giveIntVarType(), gc.giveIntVarMode(), 2, tStep);
1476 result += this->giveInternalStateAtNode(v3, gc.giveIntVarType(), gc.giveIntVarMode(), 3, tStep);
1477 } else if ( gc.giveIntVarMode() == ISM_local ) {
1478 GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0);
1479 result += giveIPValue(v1, gp, gc.giveIntVarType(), tStep);
1480 v2 = v1;
1481 v3 = v1;
1482 result *= 3;
1483 }
1484
1485 if ( result != 3 ) {
1486 return;
1487 }
1488
1489 indx = gc.giveIntVarIndx();
1490
1491 s [ 0 ] = v1.at(indx);
1492 s [ 1 ] = v2.at(indx);
1493 s [ 2 ] = v3.at(indx);
1494
1495 EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER);
1496
1497 if ( gc.getScalarAlgo() == SA_ISO_SURF ) {
1498 for ( i = 0; i < 3; i++ ) {
1499 p [ i ].x = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(1);
1500 p [ i ].y = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(2);
1501 p [ i ].z = 0.;
1502 }
1503
1504 //EASValsSetColor(gc.getYieldPlotColor(ratio));
1505 gc.updateFringeTableMinMax(s, 3);
1506 tr = CreateTriangleWD3D(p, s [ 0 ], s [ 1 ], s [ 2 ]);
1507 EGWithMaskChangeAttributes(LAYER_MASK, tr);
1508 EMAddGraphicsToModel(ESIModel(), tr);
1509 } else if ( ( gc.getScalarAlgo() == SA_ZPROFILE ) || ( gc.getScalarAlgo() == SA_COLORZPROFILE ) ) {
1510 double landScale = gc.getLandScale();
1511
1512 for ( i = 0; i < 3; i++ ) {
1513 p [ i ].x = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(1);
1514 p [ i ].y = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(2);
1515 p [ i ].z = s [ i ] * landScale;
1516 }
1517
1518 if ( gc.getScalarAlgo() == SA_ZPROFILE ) {
1519 EASValsSetColor( gc.getDeformedElementColor() );
1520 EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH);
1521 EASValsSetFillStyle(FILL_SOLID);
1522 tr = CreateTriangle3D(p);
1523 EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | FILL_MASK | LAYER_MASK, tr);
1524 } else {
1525 gc.updateFringeTableMinMax(s, 3);
1526 EASValsSetFillStyle(FILL_SOLID);
1527 tr = CreateTriangleWD3D(p, s [ 0 ], s [ 1 ], s [ 2 ]);
1528 EGWithMaskChangeAttributes(FILL_MASK | LAYER_MASK, tr);
1529 }
1530
1531 EMAddGraphicsToModel(ESIModel(), tr);
1532 }
1533}
1534
1535
1536
1537#endif
1538} // end namespace oofem
#define N(a, b)
#define REGISTER_Element(class)
Node * giveNode(int i) const
Definition element.h:629
IntArray dofManArray
Array containing dofmanager numbers.
Definition element.h:138
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
CrossSection * giveCrossSection()
Definition element.C:534
int giveNumber() const
Definition femcmpnn.h:104
void computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep, FloatArray &velocities)
Definition fmelement.C:44
double computeNorm() const
Definition floatarray.C:861
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
double dotProduct(const FloatArray &x) const
Definition floatarray.C:524
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
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 plusProductSymmUpper(const FloatMatrix &a, const FloatMatrix &b, double dV)
void add(const FloatMatrix &a)
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
*Sets size of receiver to be an empty matrix It will have zero rows and zero columns size void clear()
void plusProductUnsym(const FloatMatrix &a, const FloatMatrix &b, double dV)
void beProductOf(const FloatMatrix &a, const FloatMatrix &b)
void beNMatrixOf(const FloatArray &n, int nsd)
void beTranspositionOf(const FloatMatrix &src)
void zero()
Zeroes all coefficient of receiver.
double giveDeterminant() const
double computeFrobeniusNorm() const
double at(std::size_t i, std::size_t j) const
const FloatArray & giveNaturalCoordinates() const
Returns coordinate array of receiver.
Definition gausspoint.h:138
double giveWeight()
Returns integration weight of receiver.
Definition gausspoint.h:180
double giveLevelSetDofManValue(int i)
Returns level set value in specific node.
GraphicObj * draw(oofegGraphicContext &, bool filled, int layer=OOFEG_DEBUG_LAYER)
Definition geotoolbox.C:152
SUPGElement2(int n, Domain *aDomain)
void computeDivUMatrix(FloatMatrix &answer, GaussPoint *gp) override
void computeCenterOf(FloatArray &C, FloatArray c, int dim)
void computeNuMatrix(FloatMatrix &answer, GaussPoint *gp) override
void computeIntersection(int iedge, FloatArray &intcoords, FloatArray &fi)
void computeAdvectionDeltaTerm(FloatMatrix &answer, TimeStep *tStep)
void computeQuadraticRoots(FloatArray Coeff, double &r1, double &r2)
void computeUDotGradUMatrix(FloatMatrix &answer, GaussPoint *gp, TimeStep *tStep) override
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, int node, TimeStep *tStep) override
static FEI2dTrLin pressureInterpolation
void computeMassDeltaTerm(FloatMatrix &answer, TimeStep *tStep)
void computeLSICTerm(FloatMatrix &answer, TimeStep *tStep)
void computeCoordsOfEdge(FloatArray &answer, int iedge)
void computeQuadraticFunct(FloatArray &answer, int iedge)
double computeVolumeAround(GaussPoint *gp) override
static FEI2dTrQuad velocityInterpolation
double LS_PCS_computeVolume() override
Returns receiver's volume.
void computeMiddlePointOnParabolicArc(FloatArray &answer, int iedge, FloatArray borderpoints)
void computeAdvectionTerm(FloatMatrix &answer, TimeStep *tStep)
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
ZZNodalRecoveryModelInterface(Element *element)
Constructor.
#define OOFEM_LOG_INFO(...)
Definition logger.h:143
#define S(p)
Definition mdm.C:469
long ContextMode
Definition contextmode.h:43
InternalStateMode
Determines the mode of internal variable.
FloatMatrixF< N, M > zero()
Constructs a zero matrix (this is the default behavior when constructing a matrix,...
@ ZZNodalRecoveryModelInterfaceType
@ LevelSetPCSElementInterfaceType
@ NodalAveragingRecoveryModelInterfaceType
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]
#define OOFEG_VARPLOT_PATTERN_LAYER
#define OOFEG_DEFORMED_GEOMETRY_WIDTH
#define OOFEG_RAW_GEOMETRY_WIDTH
#define OOFEG_RAW_GEOMETRY_LAYER

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