OOFEM 3.0
Loading...
Searching...
No Matches
tr1_2d_cbs.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 "tr1_2d_cbs.h"
36#include "fei2dtrlin.h"
37#include "cbs.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 "domain.h"
46#include "mathfem.h"
47#include "engngm.h"
49#include "fluidcrosssection.h"
50#include "load.h"
51#include "timestep.h"
52#include "boundaryload.h"
53#include "geotoolbox.h"
54#include "crosssection.h"
55#include "contextioerr.h"
56#include "dynamicinputrecord.h"
57#include "classfactory.h"
58#include "paramkey.h"
59
60#ifdef __OOFEG
61 #include "oofeggraphiccontext.h"
62 #include "connectivitytable.h"
63#endif
64
65namespace oofem {
66#define TRSUPG_ZERO_VOF 1.e-8
67
69
72
73FEI2dTrLin TR1_2D_CBS :: interp(1, 2);
74
75TR1_2D_CBS :: TR1_2D_CBS(int n, Domain *aDomain) :
76 CBSElement(n, aDomain),
79 //<RESTRICTED_SECTION>
81 //</RESTRICTED_SECTION>
82{
84}
85
86
88TR1_2D_CBS :: giveInterpolation() const { return & interp; }
89
90int
91TR1_2D_CBS :: computeNumberOfDofs()
92{
93 return 9;
94}
95
96void
97TR1_2D_CBS :: giveDofManDofIDMask(int inode, IntArray &answer) const
98{
99 answer = {V_u, V_v, P_f};
100}
101
102
103void
104TR1_2D_CBS :: initializeFrom(InputRecord &ir, int priority)
105{
106 CBSElement :: initializeFrom(ir, priority);
107 ParameterManager &ppm = this->giveDomain()->elementPPM;
108 bool flag;
109
110 PM_UPDATE_PARAMETER_AND_REPORT(vof, ppm, ir, this->number, IPK_TR1_2D_CBS_pvof, priority, flag) ;
111 if (flag && (vof > 0.0)) {
113 this->temp_vof = vof;
114 } else {
115 this->vof = 0.0;
116 PM_UPDATE_PARAMETER_AND_REPORT(vof, ppm, ir, this->number, IPK_TR1_2D_CBS_vof, priority, flag) ;
117 if (flag) {
118 this->temp_vof = this->vof;
119 }
120 }
121}
122
123
124void
125TR1_2D_CBS :: giveInputRecord(DynamicInputRecord &input)
126{
127 CBSElement :: giveInputRecord(input);
128 if ( this->permanentVofFlag ) {
129 input.setField(this->vof, IPK_TR1_2D_CBS_pvof.getNameCStr());
130 } else {
131 input.setField(this->vof, IPK_TR1_2D_CBS_vof.getNameCStr());
132 }
133}
134
135
136void
137TR1_2D_CBS :: computeGaussPoints()
138// Sets up the array containing the four Gauss points of the receiver.
139{
140 if ( integrationRulesArray.size() == 0 ) {
141 integrationRulesArray.resize(1);
142 integrationRulesArray [ 0 ] = std::make_unique<GaussIntegrationRule>(1, this, 1, 3);
143 this->giveCrossSection()->setupIntegrationPoints(* integrationRulesArray [ 0 ], 1, this);
144 }
145}
146
147void
148TR1_2D_CBS :: computeConsistentMassMtrx(FloatMatrix &answer, TimeStep *tStep)
149{
150 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
151
152 double ar6 = rho * area / 6.0;
153 double ar12 = rho * area / 12.0;
154
155 answer.resize(9, 9);
156 answer.zero();
157 answer.at(1, 1) = answer.at(2, 2) = ar6;
158 answer.at(4, 4) = answer.at(5, 5) = ar6;
159 answer.at(7, 7) = answer.at(8, 8) = ar6;
160
161 answer.at(1, 4) = answer.at(1, 7) = ar12;
162 answer.at(4, 1) = answer.at(4, 7) = ar12;
163 answer.at(7, 1) = answer.at(7, 4) = ar12;
164
165 answer.at(2, 5) = answer.at(2, 8) = ar12;
166 answer.at(5, 2) = answer.at(5, 8) = ar12;
167 answer.at(8, 2) = answer.at(8, 5) = ar12;
168}
169
170
171void
172TR1_2D_CBS :: computeDiagonalMassMtrx(FloatArray &answer, TimeStep *tStep)
173{
174 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
175 double mm = rho * this->area / 3.0;
176 answer.resize(9);
177 answer.zero();
178 for ( int i = 0; i < 3; i++ ) {
179 answer.at(i * 3 + 1) = mm;
180 answer.at(i * 3 + 2) = mm;
181 }
182}
183
184void
185TR1_2D_CBS :: computeConvectionTermsI(FloatArray &answer, TimeStep *tStep)
186{
187 // calculates advection component for (*) velocities
188
189 double ar12, ar3, dudx, dudy, dvdx, dvdy;
190 double usum, vsum;
191 double adu11, adu21, adu31, adv11, adv21, adv31;
192 double adu12, adu22, adu32, adv12, adv22, adv32;
193 double dt = tStep->giveTimeIncrement();
194 //double rho =static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
195 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
196 int nLoads;
197 FloatArray gVector;
198
199 FloatArray u;
200
201 ar12 = area / 12.;
202 ar3 = area / 3.0;
203
204 this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), u);
205
206 dudx = b [ 0 ] * u.at(1) + b [ 1 ] * u.at(3) + b [ 2 ] * u.at(5);
207 dudy = c [ 0 ] * u.at(1) + c [ 1 ] * u.at(3) + c [ 2 ] * u.at(5);
208 dvdx = b [ 0 ] * u.at(2) + b [ 1 ] * u.at(4) + b [ 2 ] * u.at(6);
209 dvdy = c [ 0 ] * u.at(2) + c [ 1 ] * u.at(4) + c [ 2 ] * u.at(6);
210
211 usum = u.at(1) + u.at(3) + u.at(5);
212 vsum = u.at(2) + u.at(4) + u.at(6);
213
214 // compute Cu*U term
215
216 adu11 = ar12 * ( dudx * ( usum + u.at(1) ) + dudy * ( vsum + u.at(2) ) );
217 adu21 = ar12 * ( dudx * ( usum + u.at(3) ) + dudy * ( vsum + u.at(4) ) );
218 adu31 = ar12 * ( dudx * ( usum + u.at(5) ) + dudy * ( vsum + u.at(6) ) );
219 adv11 = ar12 * ( dvdx * ( usum + u.at(1) ) + dvdy * ( vsum + u.at(2) ) );
220 adv21 = ar12 * ( dvdx * ( usum + u.at(3) ) + dvdy * ( vsum + u.at(4) ) );
221 adv31 = ar12 * ( dvdx * ( usum + u.at(5) ) + dvdy * ( vsum + u.at(6) ) );
222
223
224 // compute Ku*U term
225 double uu = ( usum * usum + u.at(1) * u.at(1) + u.at(3) * u.at(3) + u.at(5) * u.at(5) );
226 double uv = ( usum * vsum + u.at(1) * u.at(2) + u.at(3) * u.at(4) + u.at(5) * u.at(6) );
227 double vv = ( vsum * vsum + u.at(2) * u.at(2) + u.at(4) * u.at(4) + u.at(6) * u.at(6) );
228
229 adu12 = dt * 0.5 * ar12 * ( b [ 0 ] * dudx * uu + b [ 0 ] * dudy * uv + c [ 0 ] * dudx * uv + c [ 0 ] * dudy * vv );
230 adu22 = dt * 0.5 * ar12 * ( b [ 1 ] * dudx * uu + b [ 1 ] * dudy * uv + c [ 1 ] * dudx * uv + c [ 1 ] * dudy * vv );
231 adu32 = dt * 0.5 * ar12 * ( b [ 2 ] * dudx * uu + b [ 2 ] * dudy * uv + c [ 2 ] * dudx * uv + c [ 2 ] * dudy * vv );
232 adv12 = dt * 0.5 * ar12 * ( b [ 0 ] * dvdx * uu + b [ 0 ] * dvdy * uv + c [ 0 ] * dvdx * uv + c [ 0 ] * dvdy * vv );
233 adv22 = dt * 0.5 * ar12 * ( b [ 1 ] * dvdx * uu + b [ 1 ] * dvdy * uv + c [ 1 ] * dvdx * uv + c [ 1 ] * dvdy * vv );
234 adv32 = dt * 0.5 * ar12 * ( b [ 2 ] * dvdx * uu + b [ 2 ] * dvdy * uv + c [ 2 ] * dvdx * uv + c [ 2 ] * dvdy * vv );
235
236 answer.resize(9);
237 answer.zero();
238
239 answer.at(1) = -adu11 - adu12;
240 answer.at(2) = -adv11 - adv12;
241 answer.at(4) = -adu21 - adu22;
242 answer.at(5) = -adv21 - adv22;
243 answer.at(7) = -adu31 - adu32;
244 answer.at(8) = -adv31 - adv32;
245
246
247 // body load (gravity effects)
248 nLoads = this->giveBodyLoadArray()->giveSize();
249 for ( int i = 1; i <= nLoads; i++ ) {
250 auto load = domain->giveLoad( bodyLoadArray.at(i) );
251 auto ltype = load->giveBCGeoType();
252 if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) {
253 load->computeComponentArrayAt(gVector, tStep, VM_Total);
254 if ( gVector.giveSize() ) {
255 answer.at(1) -= dt * 0.5 * ar3 * ( b [ 0 ] * usum + c [ 0 ] * vsum ) * gVector.at(1);
256 answer.at(2) -= dt * 0.5 * ar3 * ( b [ 0 ] * usum + c [ 0 ] * vsum ) * gVector.at(2);
257 answer.at(4) -= dt * 0.5 * ar3 * ( b [ 1 ] * usum + c [ 1 ] * vsum ) * gVector.at(1);
258 answer.at(5) -= dt * 0.5 * ar3 * ( b [ 1 ] * usum + c [ 1 ] * vsum ) * gVector.at(2);
259 answer.at(7) -= dt * 0.5 * ar3 * ( b [ 2 ] * usum + c [ 2 ] * vsum ) * gVector.at(1);
260 answer.at(8) -= dt * 0.5 * ar3 * ( b [ 2 ] * usum + c [ 2 ] * vsum ) * gVector.at(2);
261 }
262 }
263 }
264
265
266 answer.times(rho);
267}
268
269void
270TR1_2D_CBS :: computeDiffusionTermsI(FloatArray &answer, TimeStep *tStep)
271{
272 FloatArray stress;
273 double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber();
274 GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0);
275 double rho = static_cast< FluidCrossSection* >(this->giveCrossSection())->giveDensity( gp );
276 FloatArray gVector;
277 double ar3 = area / 3.0;
278
280 stress.times(1. / Re);
281
282 // \int dNu/dxj \Tau_ij
283 answer.resize(9);
284 answer.zero();
285 for ( int i = 0; i < 3; i++ ) {
286 answer.at(i * 3 + 1) = -area * ( stress.at(1) * b [ i ] + stress.at(6) * c [ i ] );
287 answer.at(i * 3 + 2) = -area * ( stress.at(6) * b [ i ] + stress.at(2) * c [ i ] );
288 }
289
290 // add boundary termms
291 double coeff = ar3 * rho;
292 // body load (gravity effects)
293 int nLoads = this->giveBodyLoadArray()->giveSize();
294 for ( int i = 1; i <= nLoads; i++ ) {
295 auto load = domain->giveLoad( bodyLoadArray.at(i) );
296 bcGeomType ltype = load->giveBCGeoType();
297 if ( ltype == BodyLoadBGT && load->giveBCValType() == ForceLoadBVT ) {
298 load->computeComponentArrayAt(gVector, tStep, VM_Total);
299 if ( gVector.giveSize() ) {
300 answer.at(1) += coeff * gVector.at(1);
301 answer.at(2) += coeff * gVector.at(2);
302 answer.at(4) += coeff * gVector.at(1);
303 answer.at(5) += coeff * gVector.at(2);
304 answer.at(7) += coeff * gVector.at(1);
305 answer.at(8) += coeff * gVector.at(2);
306 }
307 }
308 }
309
310 // terms now computed even for boundary nodes that have prescribed velocities! (but they will not be localized)
311 // loop over sides
312 nLoads = boundarySides.giveSize();
313 for ( int j = 1; j <= nLoads; j++ ) {
314 int code = boundaryCodes.at(j);
315 if ( ( code & FMElement_PrescribedTractionBC ) ) {
316 //printf ("TR1_2D_CBS :: computeDiffusionTermsI tractions detected\n");
317
318 //_error("computeDiffusionTermsI: traction bc not supported");
319 FloatArray t, coords(1);
320
321 // integrate tractions
322 int n1 = boundarySides.at(j);
323 int n2 = ( n1 == 3 ? 1 : n1 + 1 );
324
325 double tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1);
326 double ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2);
327 double l = sqrt(tx * tx + ty * ty);
328 double nx = ty / l;
329 double ny = -tx / l;
330
331 // loop over boundary load array
332 int numLoads = this->giveBoundaryLoadArray()->giveSize() / 2;
333 for ( int i = 1; i <= numLoads; i++ ) {
334 int n = boundaryLoadArray.at(1 + ( i - 1 ) * 2);
335 auto load = dynamic_cast< BoundaryLoad * >( domain->giveLoad(n) );
336 if ( load ) {
337 load->computeValueAt(t, tStep, coords, VM_Total);
338
339 //printf ("TR1_2D_CBS :: computeDiffusionTermsI traction (%e,%e) detected\n", t.at(1), t.at(2));
340
341 answer.at( ( n1 - 1 ) * 3 + 1 ) += 0.5 * l * ( t.at(1) * nx );
342 answer.at( ( n1 - 1 ) * 3 + 2 ) += 0.5 * l * ( t.at(2) * ny );
343
344 answer.at( ( n2 - 1 ) * 3 + 1 ) += 0.5 * l * ( t.at(1) * nx );
345 answer.at( ( n2 - 1 ) * 3 + 2 ) += 0.5 * l * ( t.at(2) * ny );
346 }
347 }
348 } else if ( !( ( code & FMElement_PrescribedUnBC ) && ( code & FMElement_PrescribedUsBC ) ) ) {
349 /*
350 * n1 = i;
351 * n2 = (n1==3?n2=1:n2=n1+1);
352 *
353 * //if (giveNode(n1)->isBoundary() && giveNode(n2)->isBoundary()) {
354 *
355 * tx = giveNode(n2)->giveCoordinate(1)-giveNode(n1)->giveCoordinate(1);
356 * ty = giveNode(n2)->giveCoordinate(2)-giveNode(n1)->giveCoordinate(2);
357 * l = sqrt(tx*tx+ty*ty);
358 * nx = ty/l; ny = -tx/l;
359 *
360 * // normal displacement precribed
361 * answer.at((n1-1)*3+1)+=l*0.5*(stress.at(1)*nx + stress.at(6)*ny);
362 * answer.at((n1-1)*3+2)+=l*0.5*(stress.at(6)*nx + stress.at(2)*ny);
363 *
364 * answer.at((n2-1)*3+1)+=l*0.5*(stress.at(1)*nx + stress.at(6)*ny);
365 * answer.at((n2-1)*3+2)+=l*0.5*(stress.at(6)*nx + stress.at(2)*ny);
366 * //}
367 */
368 }
369 }
370}
371
372void
373TR1_2D_CBS :: computeDensityRhsVelocityTerms(FloatArray &answer, TimeStep *tStep)
374{
375 // computes velocity terms on RHS for density equation
376 double velu = 0.0, velv = 0.0; // dudx=0.0, dvdy=0.0;
377 //double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity(gp);
378 double theta1 = static_cast< CBS * >( domain->giveEngngModel() )->giveTheta1();
379 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
380 FloatArray u, ustar;
381
382 answer.resize(9);
383 answer.zero();
384
385 this->computeVectorOfVelocities(VM_Total, tStep, u);
387 // Should we really want to add this term?
388 // This will produce velocities that differs from their actual Dirichlet b.c.s;
389 // The patch05.in test has a Dirichlet V_v = 1.0 on node 2, but this will produce the value V_v 1.5 for that dof.
390 // It also requires knowing theta1, which we could otherwise do without.
391 // It is added for now to mirror the old code below.
392 this->computeVectorOfPrescribed({V_u, V_v}, VM_Incremental, tStep, ustar);
393 u.add(theta1, ustar);
394
395 //this->computeVectorOfVelocities(VM_Incremental, tStep, ustar);
396 //u.add((theta1-1, ustar);
397 /*
398 * printf("u_new = "); u.printYourself();
399 * this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), u);
400 * this->computeVectorOfAuxVelocities(VM_Incremental, tStep, ustar);
401 * u.add(theta1, ustar);
402 * printf("u_corr = "); u.printYourself();
403 */
404
405 for ( int i = 0; i < 3; i++ ) {
406 velu += u.at(i * 2 + 1);
407 velv += u.at(i * 2 + 2);
408 }
409
410 for ( int i = 0; i < 3; i++ ) {
411 answer.at( ( i + 1 ) * 3 ) = area * ( ( b [ i ] * velu + c [ i ] * velv ) ) / 3.0;
412 }
413
414 /* account for normal prescribed velocity on boundary*/
415 /* on the rest of the boundary the tractions or pressure is prescribed -> to be implemented later */
416
417 // loop over sides
418 for ( int j = 1; j <= boundarySides.giveSize(); j++ ) {
419 int code = boundaryCodes.at(j);
420 if ( ( code & FMElement_PrescribedPressureBC ) ) {
421 continue;
422 } else if ( ( code & FMElement_PrescribedUnBC ) ) {
423 this->computeVectorOfPrescribed({V_u, V_v}, VM_Total, tStep, u);
424
425 int n1 = boundarySides.at(j);
426 int n2 = ( n1 == 3 ? 1 : n1 + 1 );
427
428 //if (giveNode(n1)->isBoundary() && giveNode(n2)->isBoundary()) {
429 double tx, ty, l, nx, ny, un1, un2;
430 tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1);
431 ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2);
432 l = sqrt(tx * tx + ty * ty);
433 nx = ty / l;
434 ny = -tx / l;
435 un1 = nx * u.at( ( n1 - 1 ) * 2 + 1 ) + ny *u.at(n1 * 2);
436 un2 = nx * u.at( ( n2 - 1 ) * 2 + 1 ) + ny *u.at(n2 * 2);
437 //if ((un1 != 0.) && (un2 != 0.)) {
438 // normal displacement precribed
439 answer.at(n1 * 3) -= ( un1 * l / 3. + un2 * l / 6. );
440 answer.at(n2 * 3) -= ( un2 * l / 3. + un1 * l / 6. );
441 //}
442 //}
443 } else if ( ( code & FMElement_PrescribedTractionBC ) ) {
444 continue;
445 }
446 }
447
448 answer.times(rho);
449}
450
451
452void
453TR1_2D_CBS :: computePrescribedTractionPressure(FloatArray &answer, TimeStep *tStep)
454{
455 /*
456 * this method computes the prescribed pressure due to applied traction
457 * p = tau(i,j)*n(i)*n(j) - traction(i)*n(i)
458 * this pressure is enforced as dirichlet bc in density/pressure equation
459 */
460 FloatArray stress;
461 double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber();
462 GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0);
464 stress.times(1. / Re);
465
466 answer.resize(9);
467 answer.zero();
468
469 // loop over sides
470 for ( int j = 1; j <= boundarySides.giveSize(); j++ ) {
471 int code = boundaryCodes.at(j);
472 int sid = boundarySides.at(j);
473 if ( ( code & FMElement_PrescribedTractionBC ) ) {
474 FloatArray t, coords(1);
475 // integrate tractions
476 int n1 = sid;
477 int n2 = ( n1 == 3 ? 1 : n1 + 1 );
478
479 double tx, ty, l, nx, ny, pcoeff;
480 tx = giveNode(n2)->giveCoordinate(1) - giveNode(n1)->giveCoordinate(1);
481 ty = giveNode(n2)->giveCoordinate(2) - giveNode(n1)->giveCoordinate(2);
482 l = sqrt(tx * tx + ty * ty);
483 nx = ty / l;
484 ny = -tx / l;
485
486
487 //nodecounter.at(n1)++;
488 //nodecounter.at(n2)++;
489 pcoeff = stress.at(1) * nx * nx + stress.at(2) * ny * ny + 2.0 * stress.at(6) * nx * ny;
490 answer.at(n1 * 3) += pcoeff;
491 answer.at(n2 * 3) += pcoeff;
492
493 // if no traction bc applied but side marked as with traction load
494 // then zero traction is assumed !!!
495
496 // loop over boundary load array
497 int nLoads = this->giveBoundaryLoadArray()->giveSize() / 2;
498 for ( int i = 1; i <= nLoads; i++ ) {
499 int n = boundaryLoadArray.at(1 + ( i - 1 ) * 2);
500 int id = boundaryLoadArray.at(i * 2);
501 if ( id != sid ) {
502 continue;
503 }
504
505 BoundaryLoad *load = dynamic_cast< BoundaryLoad * >( domain->giveLoad(n) );
506 if ( load ) {
507 load->computeValueAt(t, tStep, coords, VM_Total);
508
509 answer.at(n1 * 3) -= t.at(1) * nx + t.at(2) * ny;
510 answer.at(n2 * 3) -= t.at(1) * nx + t.at(2) * ny;
511 }
512 }
513 }
514 }
515
516 //for (i=1; i<=3; i++) {
517 // if (nodecounter.at(i)) answer.at(i) /= nodecounter.at(i);
518 //}
519}
520
521
522void
523TR1_2D_CBS :: computeNumberOfNodalPrescribedTractionPressureContributions(FloatArray &answer, TimeStep *tStep)
524{
525 /*
526 * this method computes the prescribed pressure due to applied traction
527 * p = tau(i,j)*n(i)*n(j) - traction(i)*n(i)
528 * this pressure is enforced as dirichlet bc in density/pressure equation
529 */
530 answer.resize(9);
531 answer.zero();
532
533 // loop over sides
534 for ( int j = 1; j <= boundarySides.giveSize(); j++ ) {
535 int code = boundaryCodes.at(j);
536 if ( ( code & FMElement_PrescribedTractionBC ) ) {
537 int n1 = boundarySides.at(j);
538 int n2 = ( n1 == 3 ? 1 : n1 + 1 );
539 answer.at(n1 * 3)++;
540 answer.at(n2 * 3)++;
541 }
542 }
543}
544
545
546
547
548void
549TR1_2D_CBS :: computeDensityRhsPressureTerms(FloatArray &answer, TimeStep *tStep)
550{
551 // computes pressure terms on RHS for density equation
552 FloatArray pv;
553 double theta1 = static_cast< CBS * >( domain->giveEngngModel() )->giveTheta1();
554
555 this->computeVectorOfPressures(VM_Total, tStep->givePreviousStep(), pv);
556 answer.resize(9);
557 answer.zero();
558
559 double dpdx = 0.0, dpdy = 0.0;
560 for ( int i = 0; i < 3; i++ ) {
561 dpdx += b [ i ] * pv.at(i + 1);
562 dpdy += c [ i ] * pv.at(i + 1);
563 }
564
565 for ( int i = 0; i < 3; i++ ) {
566 answer.at( ( i + 1 ) * 3 ) = -theta1 *tStep->giveTimeIncrement() * area * ( b [ i ] * dpdx + c [ i ] * dpdy );
567 }
568}
569
570
571void
572TR1_2D_CBS :: computePressureLhs(FloatMatrix &answer, TimeStep *tStep)
573{
574 // calculates the pressure LHS
575
576 answer.resize(3, 3);
577
578 answer.at(1, 1) = area * ( b [ 0 ] * b [ 0 ] + c [ 0 ] * c [ 0 ] );
579 answer.at(2, 2) = area * ( b [ 1 ] * b [ 1 ] + c [ 1 ] * c [ 1 ] );
580 answer.at(3, 3) = area * ( b [ 2 ] * b [ 2 ] + c [ 2 ] * c [ 2 ] );
581
582 answer.at(1, 2) = answer.at(2, 1) = area * ( b [ 0 ] * b [ 1 ] + c [ 0 ] * c [ 1 ] );
583 answer.at(1, 3) = answer.at(3, 1) = area * ( b [ 0 ] * b [ 2 ] + c [ 0 ] * c [ 2 ] );
584 answer.at(2, 3) = answer.at(3, 2) = area * ( b [ 1 ] * b [ 2 ] + c [ 1 ] * c [ 2 ] );
585}
586
587
588void
589TR1_2D_CBS :: computeCorrectionRhs(FloatArray &answer, TimeStep *tStep)
590{
591 //Evaluates the RHS of velocity correction step
592 FloatArray pv, u;
593 double ar3;
594 double usum, vsum, coeff;
595
596
597 this->computeVectorOfPressures(VM_Total, tStep, pv);
598
599 double dpdx = 0.0, dpdy = 0.0;
600 for ( int i = 0; i < 3; i++ ) {
601 double pn1 = pv.at(i + 1);
602 dpdx += b [ i ] * pn1;
603 dpdy += c [ i ] * pn1;
604 }
605
606 answer.resize(9);
607 answer.zero();
608
609 ar3 = area / 3.0;
610 answer.at(1) = answer.at(4) = answer.at(7) = -ar3 * dpdx;
611 answer.at(2) = answer.at(5) = answer.at(8) = -ar3 * dpdy;
612
613
614 this->computeVectorOfPressures(VM_Total, tStep->givePreviousStep(), pv);
615 this->computeVectorOfVelocities(VM_Total, tStep->givePreviousStep(), u);
616 dpdx = 0.0, dpdy = 0.0;
617 for ( int i = 0; i < 3; i++ ) {
618 double pn1 = pv.at(i + 1);
619 dpdx += b [ i ] * pn1;
620 dpdy += c [ i ] * pn1;
621 }
622
623 usum = u.at(1) + u.at(3) + u.at(5);
624 vsum = u.at(2) + u.at(4) + u.at(6);
625 coeff = ar3 * tStep->giveTimeIncrement() / 2.0;
626 answer.at(1) -= coeff * dpdx * ( b [ 0 ] * usum + c [ 0 ] * vsum );
627 answer.at(4) -= coeff * dpdx * ( b [ 1 ] * usum + c [ 1 ] * vsum );
628 answer.at(7) -= coeff * dpdx * ( b [ 2 ] * usum + c [ 2 ] * vsum );
629
630 answer.at(2) -= coeff * dpdy * ( b [ 0 ] * usum + c [ 0 ] * vsum );
631 answer.at(5) -= coeff * dpdy * ( b [ 1 ] * usum + c [ 1 ] * vsum );
632 answer.at(8) -= coeff * dpdy * ( b [ 2 ] * usum + c [ 2 ] * vsum );
633}
634
635
636Interface *
637TR1_2D_CBS :: giveInterface(InterfaceType interface)
638{
639 if ( interface == ZZNodalRecoveryModelInterfaceType ) {
640 return static_cast< ZZNodalRecoveryModelInterface * >(this);
641 } else if ( interface == NodalAveragingRecoveryModelInterfaceType ) {
642 return static_cast< NodalAveragingRecoveryModelInterface * >(this);
643 } else if ( interface == SPRNodalRecoveryModelInterfaceType ) {
644 return static_cast< SPRNodalRecoveryModelInterface * >(this);
645 } else if ( interface == SpatialLocalizerInterfaceType ) {
646 return static_cast< SpatialLocalizerInterface * >(this);
647 } else if ( interface == EIPrimaryFieldInterfaceType ) {
648 return static_cast< EIPrimaryFieldInterface * >(this);
649 }
650 //<RESTRICTED_SECTION>
651 else if ( interface == LEPlicElementInterfaceType ) {
652 return static_cast< LEPlicElementInterface * >(this);
653 }
654
655 //</RESTRICTED_SECTION>
656 return nullptr;
657}
658
659
660void
661TR1_2D_CBS :: computeDeviatoricStress(FloatArray &answer, GaussPoint *gp, TimeStep *tStep)
662{
663 /* one should call material driver instead */
664 FloatArray u;
665 this->computeVectorOfVelocities(VM_Total, tStep, u);
666
667 FloatArrayF<3> eps = {
668 b [ 0 ] * u.at(1) + b [ 1 ] * u.at(3) + b [ 2 ] * u.at(5),
669 c [ 0 ] * u.at(2) + c [ 1 ] * u.at(4) + c [ 2 ] * u.at(6),
670 b [ 0 ] * u.at(2) + b [ 1 ] * u.at(4) + b [ 2 ] * u.at(6) + c [ 0 ] * u.at(1) + c [ 1 ] * u.at(3) + c [ 2 ] * u.at(5),
671 };
672 answer = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveFluidMaterial()->computeDeviatoricStress2D(eps, gp, tStep);
673}
674
675int
676TR1_2D_CBS :: checkConsistency()
677{
678 double x1, x2, x3, y1, y2, y3;
679
680 auto node1 = giveNode(1);
681 auto node2 = giveNode(2);
682 auto node3 = giveNode(3);
683
684 // init geometry data
685 x1 = node1->giveCoordinate(1);
686 x2 = node2->giveCoordinate(1);
687 x3 = node3->giveCoordinate(1);
688
689 y1 = node1->giveCoordinate(2);
690 y2 = node2->giveCoordinate(2);
691 y3 = node3->giveCoordinate(2);
692
693 this->area = 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 );
694
695 b [ 0 ] = ( y2 - y3 ) / ( 2. * area );
696 c [ 0 ] = ( x3 - x2 ) / ( 2. * area );
697 b [ 1 ] = ( y3 - y1 ) / ( 2. * area );
698 c [ 1 ] = ( x1 - x3 ) / ( 2. * area );
699 b [ 2 ] = ( y1 - y2 ) / ( 2. * area );
700 c [ 2 ] = ( x2 - x1 ) / ( 2. * area );
701
702 return CBSElement :: checkConsistency();
703}
704
705double
706TR1_2D_CBS :: computeCriticalTimeStep(TimeStep *tStep)
707{
708 FloatArray u;
709 double Re = static_cast< FluidModel * >( domain->giveEngngModel() )->giveReynoldsNumber();
710
711 this->computeVectorOfVelocities(VM_Total, tStep, u);
712
713 double vn1 = sqrt( u.at(1) * u.at(1) + u.at(2) * u.at(2) );
714 double vn2 = sqrt( u.at(3) * u.at(3) + u.at(4) * u.at(4) );
715 double vn3 = sqrt( u.at(5) * u.at(5) + u.at(6) * u.at(6) );
716 double veln = max( vn1, max(vn2, vn3) );
717
718 double l1 = 1.0 / ( sqrt(b [ 0 ] * b [ 0 ] + c [ 0 ] * c [ 0 ]) );
719 double l2 = 1.0 / ( sqrt(b [ 1 ] * b [ 1 ] + c [ 1 ] * c [ 1 ]) );
720 double l3 = 1.0 / ( sqrt(b [ 2 ] * b [ 2 ] + c [ 2 ] * c [ 2 ]) );
721
722 double ln = min( l1, min(l2, l3) );
723
724 // viscous limit
725 double dt;
726 double dt2 = 0.5 * ln * ln * Re;
727 if ( veln != 0.0 ) {
728 double dt1 = ln / veln;
729 dt = dt1 * dt2 / ( dt1 + dt2 );
730 } else {
731 dt = dt2;
732 }
733
734 return dt;
735}
736
737//<RESTRICTED_SECTION>
738double
739TR1_2D_CBS :: computeLEPLICVolumeFraction(const FloatArray &n, const double p, LEPlic *matInterface, bool updFlag)
740{
741 Polygon pg;
742 double answer, volume = computeMyVolume(matInterface, updFlag);
743 this->formVolumeInterfacePoly(pg, matInterface, n, p, updFlag);
744 answer = fabs(pg.computeVolume() / volume);
745 if ( answer > 1.000000001 ) {
746 return 1.0;
747 } else {
748 return answer;
749 }
750}
751
752void
753TR1_2D_CBS :: formMaterialVolumePoly(Polygon &matvolpoly, LEPlic *matInterface,
754 const FloatArray &normal, const double p, bool updFlag)
755{
756 Vertex v;
757
758 matvolpoly.clear();
759
760 if ( this->vof <= TRSUPG_ZERO_VOF ) {
761 return;
762 } else if ( this->vof >= ( 1 - TRSUPG_ZERO_VOF ) ) {
763 for ( int i = 1; i <= 3; i++ ) {
764 double x, y;
765 if ( updFlag ) {
766 x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() );
767 y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() );
768 } else {
769 x = this->giveNode(i)->giveCoordinate(1);
770 y = this->giveNode(i)->giveCoordinate(2);
771 }
772
773 v.setCoords(x, y);
774 matvolpoly.addVertex(v);
775 }
776
777 return;
778 }
779
780 this->formVolumeInterfacePoly(matvolpoly, matInterface, normal, p, updFlag);
781}
782
783
784void
785TR1_2D_CBS :: formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface,
786 const FloatArray &normal, const double p, bool updFlag)
787{
788 int next;
789 bool nodeIn [ 3 ];
790 double nx = normal.at(1), ny = normal.at(2), x, y;
791 double tx, ty;
792 Vertex v;
793
794 matvolpoly.clear();
795
796 for ( int i = 1; i <= 3; i++ ) {
797 if ( updFlag ) {
798 x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() );
799 y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() );
800 } else {
801 x = this->giveNode(i)->giveCoordinate(1);
802 y = this->giveNode(i)->giveCoordinate(2);
803 }
804
805 if ( ( nx * x + ny * y + p ) >= 0. ) {
806 nodeIn [ i - 1 ] = true;
807 } else {
808 nodeIn [ i - 1 ] = false;
809 }
810 }
811
812 if ( nodeIn [ 0 ] && nodeIn [ 1 ] && nodeIn [ 2 ] ) { // all nodes inside
813 for ( int i = 1; i <= 3; i++ ) {
814 if ( updFlag ) {
815 x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() );
816 y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() );
817 } else {
818 x = this->giveNode(i)->giveCoordinate(1);
819 y = this->giveNode(i)->giveCoordinate(2);
820 }
821
822 v.setCoords(x, y);
823 matvolpoly.addVertex(v);
824 }
825
826 return;
827 } else if ( !( nodeIn [ 0 ] || nodeIn [ 1 ] || nodeIn [ 2 ] ) ) { // all nodes outside
828 return;
829 } else {
830 for ( int i = 1; i <= 3; i++ ) {
831 next = i < 3 ? i + 1 : 1;
832 if ( nodeIn [ i - 1 ] ) {
833 if ( updFlag ) {
834 v.setCoords( matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() ),
835 matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() ) );
836 } else {
837 v.setCoords( this->giveNode(i)->giveCoordinate(1),
838 this->giveNode(i)->giveCoordinate(2) );
839 }
840
841 matvolpoly.addVertex(v);
842 }
843
844 if ( nodeIn [ next - 1 ] ^ nodeIn [ i - 1 ] ) {
845 // compute intersection with (i,next) edge
846 if ( updFlag ) {
847 x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() );
848 y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() );
849 tx = matInterface->giveUpdatedXCoordinate( this->giveNode(next)->giveNumber() ) - x;
850 ty = matInterface->giveUpdatedYCoordinate( this->giveNode(next)->giveNumber() ) - y;
851 } else {
852 x = this->giveNode(i)->giveCoordinate(1);
853 y = this->giveNode(i)->giveCoordinate(2);
854 tx = this->giveNode(next)->giveCoordinate(1) - x;
855 ty = this->giveNode(next)->giveCoordinate(2) - y;
856 }
857
858 double s, sd = nx * tx + ny * ty;
859 if ( fabs(sd) > 1.e-10 ) {
860 s = ( -p - ( nx * x + ny * y ) ) / sd;
861 v.setCoords(x + tx * s, y + ty * s);
862 matvolpoly.addVertex(v);
863 } else {
864 // pathological case - lines are parallel
865 if ( nodeIn [ i - 1 ] ) {
866 if ( updFlag ) {
867 v.setCoords( matInterface->giveUpdatedXCoordinate( this->giveNode(next)->giveNumber() ),
868 matInterface->giveUpdatedYCoordinate( this->giveNode(next)->giveNumber() ) );
869 } else {
870 v.setCoords( this->giveNode(next)->giveCoordinate(1), this->giveNode(next)->giveCoordinate(2) );
871 }
872
873 matvolpoly.addVertex(v);
874 } else {
875 v.setCoords(x, y);
876 matvolpoly.addVertex(v);
877 if ( updFlag ) {
878 v.setCoords( matInterface->giveUpdatedXCoordinate( this->giveNode(next)->giveNumber() ),
879 matInterface->giveUpdatedYCoordinate( this->giveNode(next)->giveNumber() ) );
880 } else {
881 v.setCoords( this->giveNode(next)->giveCoordinate(1), this->giveNode(next)->giveCoordinate(2) );
882 }
883
884 matvolpoly.addVertex(v);
885 }
886 }
887 }
888 } // end loop over elem nodes
889 }
890}
891
892
893double
894TR1_2D_CBS :: truncateMatVolume(const Polygon &matvolpoly, double &volume)
895{
896 Polygon me, clip;
897 Graph g;
898
899 this->formMyVolumePoly(me, NULL, false);
900 g.clip(clip, me, matvolpoly);
901#ifdef __OOFEG
902 EASValsSetColor( gc [ 0 ].getActiveCrackColor() );
903 clip.draw(gc [ OOFEG_DEBUG_LAYER ], true);
904 //EVFastRedraw(myview);
905#endif
906 volume = clip.computeVolume();
907 return volume / area;
908}
909
910void
911TR1_2D_CBS :: formMyVolumePoly(Polygon &me, LEPlic *matInterface, bool updFlag)
912{
913 Vertex v;
914
915 me.clear();
916
917 for ( int i = 1; i <= 3; i++ ) {
918 double x, y;
919 if ( updFlag ) {
920 x = matInterface->giveUpdatedXCoordinate( this->giveNode(i)->giveNumber() );
921 y = matInterface->giveUpdatedYCoordinate( this->giveNode(i)->giveNumber() );
922 } else {
923 x = this->giveNode(i)->giveCoordinate(1);
924 y = this->giveNode(i)->giveCoordinate(2);
925 }
926
927 v.setCoords(x, y);
928 me.addVertex(v);
929 }
930}
931
932
933double
934TR1_2D_CBS :: computeMyVolume(LEPlic *matInterface, bool updFlag)
935{
936 if ( updFlag ) {
937 double x1, x2, x3, y1, y2, y3;
938 x1 = matInterface->giveUpdatedXCoordinate( this->giveNode(1)->giveNumber() );
939 x2 = matInterface->giveUpdatedXCoordinate( this->giveNode(2)->giveNumber() );
940 x3 = matInterface->giveUpdatedXCoordinate( this->giveNode(3)->giveNumber() );
941
942 y1 = matInterface->giveUpdatedYCoordinate( this->giveNode(1)->giveNumber() );
943 y2 = matInterface->giveUpdatedYCoordinate( this->giveNode(2)->giveNumber() );
944 y3 = matInterface->giveUpdatedYCoordinate( this->giveNode(3)->giveNumber() );
945 return 0.5 * ( x2 * y3 + x1 * y2 + y1 * x3 - x2 * y1 - x3 * y2 - x1 * y3 );
946 } else {
947 return area;
948 }
949}
950
951void
952TR1_2D_CBS :: giveElementCenter(LEPlic *mat_interface, FloatArray &center, bool upd)
953{
954 FloatArray coords;
955
956 center.resize(2);
957 center.zero();
958 if ( upd ) {
959 for ( int i = 1; i <= 3; i++ ) {
960 mat_interface->giveUpdatedCoordinate( coords, giveNode(i)->giveNumber() );
961 center.add(coords);
962 }
963 } else {
964 for ( int i = 1; i <= 3; i++ ) {
965 center.at(1) += this->giveNode(i)->giveCoordinate(1);
966 center.at(2) += this->giveNode(i)->giveCoordinate(2);
967 }
968 }
969
970 center.times(1. / 3.);
971}
972
973//</RESTRICTED_SECTION>
974
975
976int
977TR1_2D_CBS :: EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf,
978 const FloatArray &coords, IntArray &dofId, ValueModeType mode,
979 TimeStep *tStep)
980{
981#if 0
983 int es = dofId.giveSize();
984 this->computeVectorOf(pf, dofId, mode, tStep, elemvector, true);
985 answer.resize( es );
986 answer.zero();
987 for ( int i = 1; i <= es; i++ ) {
988 for ( int j = 1; j <= lc.giveSize(); j++ ) {
989 answer.at(i) += lc.at(j) * elemvector.at( es * ( j - 1 ) + i );
990 }
991 }
992#endif
993 int indx, es;
994 double sum;
995 FloatArray elemvector, f, lc;
996 //FloatMatrix n;
997 IntArray elemdofs;
998 // determine element dof ids
999 this->giveElementDofIDMask(elemdofs);
1000 es = elemdofs.giveSize();
1001 // first evaluate element unknown vector
1002 this->computeVectorOf(pf, elemdofs, mode, tStep, elemvector);
1003 // determine corresponding local coordinates
1004 if ( this->computeLocalCoordinates(lc, coords) ) {
1005 // compute interpolation matrix
1006 // this->computeNmatrixAt(n, &lc);
1007 // compute answer
1008 answer.resize( dofId.giveSize() );
1009 for ( int i = 1; i <= dofId.giveSize(); i++ ) {
1010 if ( ( indx = elemdofs.findFirstIndexOf( dofId.at(i) ) ) ) {
1011 sum = 0.0;
1012 for ( int j = 1; j <= 3; j++ ) {
1013 sum += lc.at(j) * elemvector.at(es * ( j - 1 ) + indx);
1014 }
1015
1016 answer.at(i) = sum;
1017 } else {
1018 //_error("EIPrimaryFieldI_evaluateFieldVectorAt: unknown dof id encountered");
1019 answer.at(i) = 0.0;
1020 }
1021 }
1022
1023 return 0; // ok
1024 } else {
1025 OOFEM_ERROR("target point not in receiver volume");
1026 return 1; // fail
1027 }
1028}
1029
1030
1031void
1032TR1_2D_CBS :: updateYourself(TimeStep *tStep)
1033{
1034 CBSElement :: updateYourself(tStep);
1035 //<RESTRICTED_SECTION>
1036 LEPlicElementInterface :: updateYourself(tStep);
1037 //</RESTRICTED_SECTION>
1038}
1039
1040int
1041TR1_2D_CBS :: giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
1042{
1043 if ( type == IST_VOFFraction ) {
1044 answer.resize(1);
1045 answer.at(1) = this->giveTempVolumeFraction();
1046 return 1;
1047 } else {
1048 return CBSElement :: giveIPValue(answer, gp, type, tStep);
1049 }
1050}
1051
1052void
1053TR1_2D_CBS :: NodalAveragingRecoveryMI_computeNodalValue(FloatArray &answer, int node,
1054 InternalStateType type, TimeStep *tStep)
1055{
1056 GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0);
1057 this->giveIPValue(answer, gp, type, tStep);
1058}
1059
1060void
1061TR1_2D_CBS :: SPRNodalRecoveryMI_giveSPRAssemblyPoints(IntArray &pap)
1062{
1063 pap.resize(3);
1064 pap.at(1) = this->giveNode(1)->giveNumber();
1065 pap.at(2) = this->giveNode(2)->giveNumber();
1066 pap.at(3) = this->giveNode(3)->giveNumber();
1067}
1068
1069void
1070TR1_2D_CBS :: SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(IntArray &answer, int pap)
1071{
1072 answer.resize(1);
1073 if ( ( pap == this->giveNode(1)->giveNumber() ) ||
1074 ( pap == this->giveNode(2)->giveNumber() ) ||
1075 ( pap == this->giveNode(3)->giveNumber() ) ) {
1076 answer.at(1) = pap;
1077 } else {
1078 OOFEM_ERROR("node unknown");
1079 }
1080}
1081
1082int
1083TR1_2D_CBS :: SPRNodalRecoveryMI_giveNumberOfIP()
1084{ return 1; }
1085
1086
1088TR1_2D_CBS :: SPRNodalRecoveryMI_givePatchType()
1089{
1090 return SPRPatchType_2dxy;
1091}
1092
1093
1094
1095void
1096TR1_2D_CBS :: printOutputAt(FILE *file, TimeStep *tStep)
1097// Performs end-of-step operations.
1098{
1099 CBSElement :: printOutputAt(file, tStep);
1100 //<RESTRICTED_SECTION>
1101 double rho = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
1102 fprintf(file, "VOF %e, density %e\n\n", this->giveVolumeFraction(), rho);
1103 //</RESTRICTED_SECTION>
1104}
1105
1106
1107
1108void TR1_2D_CBS :: saveContext(DataStream &stream, ContextMode mode)
1109{
1110 CBSElement :: saveContext(stream, mode);
1111 //<RESTRICTED_SECTION>
1112 LEPlicElementInterface :: saveContext(stream, mode);
1113 //</RESTRICTED_SECTION>
1114}
1115
1116
1117void TR1_2D_CBS :: restoreContext(DataStream &stream, ContextMode mode)
1118{
1119 CBSElement :: restoreContext(stream, mode);
1120 //<RESTRICTED_SECTION>
1121 LEPlicElementInterface :: restoreContext(stream, mode);
1122 //</RESTRICTED_SECTION>
1123}
1124
1125
1126#ifdef __OOFEG
1127int
1128TR1_2D_CBS :: giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode,
1129 int node, TimeStep *tStep)
1130{
1131 //<RESTRICTED_SECTION>
1132 if ( type == IST_VOFFraction ) {
1133 answer.resize(1);
1134 answer.at(1) = this->giveTempVolumeFraction();
1135 return 1;
1136 } else
1137 //</RESTRICTED_SECTION>
1138 if ( type == IST_Density ) {
1139 answer.resize(1);
1140 answer.at(1) = static_cast< FluidCrossSection * >( this->giveCrossSection() )->giveDensity( integrationRulesArray [ 0 ]->getIntegrationPoint(0) );
1141 return 1;
1142 } else {
1143 return CBSElement :: giveInternalStateAtNode(answer, type, mode, node, tStep);
1144 }
1145}
1146
1147void
1148TR1_2D_CBS :: drawRawGeometry(oofegGraphicContext &gc, TimeStep *tStep)
1149{
1150 WCRec p [ 3 ];
1151 GraphicObj *go;
1152
1153 if ( !gc.testElementGraphicActivity(this) ) {
1154 return;
1155 }
1156
1157 EASValsSetLineWidth(OOFEG_RAW_GEOMETRY_WIDTH);
1158 EASValsSetColor( gc.getElementColor() );
1159 EASValsSetEdgeColor( gc.getElementEdgeColor() );
1160 EASValsSetEdgeFlag(true);
1161 EASValsSetLayer(OOFEG_RAW_GEOMETRY_LAYER);
1162 p [ 0 ].x = ( FPNum ) this->giveNode(1)->giveCoordinate(1);
1163 p [ 0 ].y = ( FPNum ) this->giveNode(1)->giveCoordinate(2);
1164 p [ 0 ].z = 0.;
1165 p [ 1 ].x = ( FPNum ) this->giveNode(2)->giveCoordinate(1);
1166 p [ 1 ].y = ( FPNum ) this->giveNode(2)->giveCoordinate(2);
1167 p [ 1 ].z = 0.;
1168 p [ 2 ].x = ( FPNum ) this->giveNode(3)->giveCoordinate(1);
1169 p [ 2 ].y = ( FPNum ) this->giveNode(3)->giveCoordinate(2);
1170 p [ 2 ].z = 0.;
1171
1172 go = CreateTriangle3D(p);
1173 EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | EDGE_COLOR_MASK | EDGE_FLAG_MASK | LAYER_MASK, go);
1174 EGAttachObject(go, ( EObjectP ) this);
1175 EMAddGraphicsToModel(ESIModel(), go);
1176}
1177
1178void TR1_2D_CBS :: drawScalar(oofegGraphicContext &gc, TimeStep *tStep)
1179{
1180 int i, indx, result = 0;
1181 WCRec p [ 3 ];
1182 GraphicObj *tr;
1183 FloatArray v1, v2, v3;
1184 double s [ 3 ];
1185
1186 if ( !gc.testElementGraphicActivity(this) ) {
1187 return;
1188 }
1189
1190 if ( gc.giveIntVarMode() == ISM_recovered ) {
1191 result += this->giveInternalStateAtNode(v1, gc.giveIntVarType(), gc.giveIntVarMode(), 1, tStep);
1192 result += this->giveInternalStateAtNode(v2, gc.giveIntVarType(), gc.giveIntVarMode(), 2, tStep);
1193 result += this->giveInternalStateAtNode(v3, gc.giveIntVarType(), gc.giveIntVarMode(), 3, tStep);
1194 } else if ( gc.giveIntVarMode() == ISM_local ) {
1195 GaussPoint *gp = integrationRulesArray [ 0 ]->getIntegrationPoint(0);
1196 result += giveIPValue(v1, gp, gc.giveIntVarType(), tStep);
1197 v2 = v1;
1198 v3 = v1;
1199 result *= 3;
1200 }
1201
1202 if ( result != 3 ) {
1203 return;
1204 }
1205
1206 indx = gc.giveIntVarIndx();
1207
1208 s [ 0 ] = v1.at(indx);
1209 s [ 1 ] = v2.at(indx);
1210 s [ 2 ] = v3.at(indx);
1211
1212 EASValsSetLayer(OOFEG_VARPLOT_PATTERN_LAYER);
1213
1214 if ( gc.getScalarAlgo() == SA_ISO_SURF ) {
1215 for ( i = 0; i < 3; i++ ) {
1216 p [ i ].x = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(1);
1217 p [ i ].y = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(2);
1218 p [ i ].z = 0.;
1219 }
1220
1221 //EASValsSetColor(gc.getYieldPlotColor(ratio));
1222 gc.updateFringeTableMinMax(s, 3);
1223 tr = CreateTriangleWD3D(p, s [ 0 ], s [ 1 ], s [ 2 ]);
1224 EGWithMaskChangeAttributes(LAYER_MASK, tr);
1225 EMAddGraphicsToModel(ESIModel(), tr);
1226 } else if ( ( gc.getScalarAlgo() == SA_ZPROFILE ) || ( gc.getScalarAlgo() == SA_COLORZPROFILE ) ) {
1227 double landScale = gc.getLandScale();
1228
1229 for ( i = 0; i < 3; i++ ) {
1230 p [ i ].x = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(1);
1231 p [ i ].y = ( FPNum ) this->giveNode(i + 1)->giveCoordinate(2);
1232 p [ i ].z = s [ i ] * landScale;
1233 }
1234
1235 if ( gc.getScalarAlgo() == SA_ZPROFILE ) {
1236 EASValsSetColor( gc.getDeformedElementColor() );
1237 EASValsSetLineWidth(OOFEG_DEFORMED_GEOMETRY_WIDTH);
1238 EASValsSetFillStyle(FILL_SOLID);
1239 tr = CreateTriangle3D(p);
1240 EGWithMaskChangeAttributes(WIDTH_MASK | COLOR_MASK | FILL_MASK | LAYER_MASK, tr);
1241 } else {
1242 gc.updateFringeTableMinMax(s, 3);
1243 EASValsSetFillStyle(FILL_SOLID);
1244 tr = CreateTriangleWD3D(p, s [ 0 ], s [ 1 ], s [ 2 ]);
1245 EGWithMaskChangeAttributes(FILL_MASK | LAYER_MASK, tr);
1246 }
1247
1248 EMAddGraphicsToModel(ESIModel(), tr);
1249 }
1250}
1251
1252
1253
1254#endif
1255} // end namespace oofem
#define REGISTER_Element(class)
void computeValueAt(FloatArray &answer, TimeStep *tStep, const FloatArray &coords, ValueModeType mode) override
IntArray boundaryCodes
Boundary sides codes.
Definition cbselement.h:57
IntArray boundarySides
Array of boundary sides.
Definition cbselement.h:55
CBSElement(int n, Domain *aDomain)
Definition cbselement.C:55
double giveTheta1()
Definition cbs.C:204
void setField(int item, InputFieldType id)
virtual void giveElementDofIDMask(IntArray &answer) const
Definition element.h:510
Node * giveNode(int i) const
Definition element.h:629
IntArray boundaryLoadArray
Definition element.h:147
void computeVectorOfPrescribed(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:212
IntArray * giveBodyLoadArray()
Returns array containing load numbers of loads acting on element.
Definition element.C:411
int numberOfDofMans
Number of dofmanagers.
Definition element.h:136
void computeVectorOf(ValueModeType u, TimeStep *tStep, FloatArray &answer)
Definition element.C:103
IntArray * giveBoundaryLoadArray()
Returns array containing load numbers of boundary loads acting on element.
Definition element.C:420
std::vector< std ::unique_ptr< IntegrationRule > > integrationRulesArray
Definition element.h:157
CrossSection * giveCrossSection()
Definition element.C:534
virtual bool computeLocalCoordinates(FloatArray &answer, const FloatArray &gcoords)
Definition element.C:1240
IntArray bodyLoadArray
Definition element.h:147
Domain * giveDomain() const
Definition femcmpnn.h:97
Domain * domain
Link to domain object, useful for communicating with other FEM components.
Definition femcmpnn.h:79
int number
Component number.
Definition femcmpnn.h:77
int giveNumber() const
Definition femcmpnn.h:104
void computeVectorOfPressures(ValueModeType mode, TimeStep *tStep, FloatArray &pressures)
Definition fmelement.C:51
void computeVectorOfVelocities(ValueModeType mode, TimeStep *tStep, FloatArray &velocities)
Definition fmelement.C:44
void resize(Index s)
Definition floatarray.C:94
double & at(Index i)
Definition floatarray.h:202
Index giveSize() const
Returns the size of receiver.
Definition floatarray.h:261
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void add(const FloatArray &src)
Definition floatarray.C:218
void times(double s)
Definition floatarray.C:834
void resize(Index rows, Index cols)
Definition floatmatrix.C:79
void zero()
Zeroes all coefficient of receiver.
double at(std::size_t i, std::size_t j) const
const FloatArrayF< 6 > & giveDeviatoricStressVector() const
virtual double giveReynoldsNumber()=0
IntegrationPointStatus * giveMaterialStatus(IntegrationPointStatusIDType key=IPSID_Default)
Definition gausspoint.h:204
void clip(Polygon &result, const Polygon &a, const Polygon &b)
Definition geotoolbox.C:575
void resize(int n)
Definition intarray.C:73
int findFirstIndexOf(int value) const
Definition intarray.C:280
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
FloatArray normal
Interface segment normal.
Definition leplic.h:67
void setPermanentVolumeFraction(double v)
Definition leplic.h:106
double p
Line constant of line segment representing interface.
Definition leplic.h:65
double vof
Volume fraction of reference fluid in element.
Definition leplic.h:63
double giveUpdatedXCoordinate(int num)
Definition leplic.h:185
void giveUpdatedCoordinate(FloatArray &answer, int num)
Definition leplic.h:179
double giveUpdatedYCoordinate(int num)
Definition leplic.h:186
void addVertex(Vertex v)
Definition geotoolbox.h:96
GraphicObj * draw(oofegGraphicContext &, bool filled, int layer=OOFEG_DEBUG_LAYER)
Definition geotoolbox.C:152
double computeVolume() const
Definition geotoolbox.C:72
SpatialLocalizerInterface(Element *element)
static FEI2dTrLin interp
Definition tr1_2d_cbs.h:74
int giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode, int node, TimeStep *tStep) override
void formMyVolumePoly(Polygon &myPoly, LEPlic *mat_interface, bool updFlag) override
Assembles receiver volume.
Definition tr1_2d_cbs.C:911
static ParamKey IPK_TR1_2D_CBS_vof
Definition tr1_2d_cbs.h:80
double computeMyVolume(LEPlic *matInterface, bool updFlag) override
Computes the volume of receiver.
Definition tr1_2d_cbs.C:934
int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep) override
void formVolumeInterfacePoly(Polygon &matvolpoly, LEPlic *matInterface, const FloatArray &normal, const double p, bool updFlag) override
Assembles receiver material polygon based solely on given interface line.
Definition tr1_2d_cbs.C:785
static ParamKey IPK_TR1_2D_CBS_pvof
Definition tr1_2d_cbs.h:81
double giveTimeIncrement()
Returns solution step associated time increment.
Definition timestep.h:168
TimeStep * givePreviousStep()
Returns pointer to previous solution step.
Definition timestep.C:132
void setCoords(double x, double y)
Definition geotoolbox.h:77
ZZNodalRecoveryModelInterface(Element *element)
Constructor.
#define OOFEM_ERROR(...)
Definition error.h:79
#define FMElement_PrescribedUnBC
Definition fmelement.h:45
#define FMElement_PrescribedTractionBC
Definition fmelement.h:44
#define FMElement_PrescribedPressureBC
Definition fmelement.h:47
#define FMElement_PrescribedUsBC
Definition fmelement.h:46
long ContextMode
Definition contextmode.h:43
FloatArrayF< N > min(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
bcGeomType
Type representing the geometric character of loading.
Definition bcgeomtype.h:40
@ BodyLoadBGT
Distributed body load.
Definition bcgeomtype.h:43
FloatArrayF< N > max(const FloatArrayF< N > &a, const FloatArrayF< N > &b)
InternalStateMode
Determines the mode of internal variable.
double sum(const FloatArray &x)
@ ForceLoadBVT
Definition bcvaltype.h:43
@ SPRNodalRecoveryModelInterfaceType
@ ZZNodalRecoveryModelInterfaceType
@ EIPrimaryFieldInterfaceType
@ LEPlicElementInterfaceType
@ SpatialLocalizerInterfaceType
@ NodalAveragingRecoveryModelInterfaceType
oofem::oofegGraphicContext gc[OOFEG_LAST_LAYER]
#define OOFEG_DEBUG_LAYER
#define OOFEG_VARPLOT_PATTERN_LAYER
#define OOFEG_DEFORMED_GEOMETRY_WIDTH
#define OOFEG_RAW_GEOMETRY_WIDTH
#define OOFEG_RAW_GEOMETRY_LAYER
#define PM_UPDATE_PARAMETER_AND_REPORT(_val, _pm, _ir, _componentnum, _paramkey, _prio, _flag)
#define TRSUPG_ZERO_VOF
Definition tr1_2d_cbs.C:66

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