OOFEM 3.0
Loading...
Searching...
No Matches
vtkbaseexportmodule.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 "vtkbaseexportmodule.h"
36#include "element.h"
37#include "gausspoint.h"
38#include "timestep.h"
39#include "engngm.h"
40#include "node.h"
41#include "dof.h"
42#include "materialinterface.h"
43#include "mathfem.h"
44#include "cltypes.h"
45#include "material.h"
46#include "classfactory.h"
47#include "crosssection.h"
49
50#include <string>
51#include <sstream>
52#include <ctime>
53
54namespace oofem {
55
56
57// Beginning of VTKBaseExportModule
58
60 1, 5, 9, 8, 7, 4, 6, 3, 2
61}; //position of xx, yy, zz, yz, xz, xy in tensor
62
65
68
69void
74
75void
78
79void
81{
82 answer.resize(9);
83 answer.zero();
84
85 for ( int i = 1; i <= reducedForm.giveSize(); i++ ) {
86 answer.at(redToFull.at(i) ) = reducedForm.at(i);
87 }
88
89 if ( vtype == ISVT_TENSOR_S3E ) {
90 answer.at(4) *= 0.5;
91 answer.at(7) *= 0.5;
92 answer.at(8) *= 0.5;
93 }
94
95 // Symmetrize if needed
96 if ( vtype != ISVT_TENSOR_G ) {
97 answer.at(2) = answer.at(4);
98 answer.at(3) = answer.at(7);
99 answer.at(6) = answer.at(8);
100 }
101}
102
103int
105{
107 int vtkCellType = 0;
108
109 if ( elemGT == EGT_point ) {
110 vtkCellType = 1;
111 } else if ( elemGT == EGT_line_1 ) {
112 vtkCellType = 3;
113 } else if ( elemGT == EGT_line_2 ) {
114 vtkCellType = 21;
115 } else if ( elemGT == EGT_triangle_1 ) {
116 vtkCellType = 5;
117 } else if ( elemGT == EGT_triangle_2 ) {
118 vtkCellType = 22;
119 } else if ( elemGT == EGT_tetra_1 ) {
120 vtkCellType = 10;
121 } else if ( elemGT == EGT_tetra_2 ) {
122 vtkCellType = 24;
123 } else if ( elemGT == EGT_quad_1) {
124 vtkCellType = 9;
125 } else if ( elemGT == EGT_quad_21_interface ) {
126 vtkCellType = 30;
127 } else if ( elemGT == EGT_quad_2 ) {
128 vtkCellType = 23;
129 } else if ( elemGT == EGT_quad9_2 ) {
130 vtkCellType = 23;
131 } else if ( elemGT == EGT_hexa_1 || elemGT == EGT_quad_1_interface ) {
132 vtkCellType = 12;
133 } else if ( elemGT == EGT_hexa_2 ) {
134 vtkCellType = 25;
135 } else if ( elemGT == EGT_hexa_27 ) {
136 vtkCellType = 29;
137 } else if ( elemGT == EGT_wedge_1 ) {
138 vtkCellType = 13;
139 } else if ( elemGT == EGT_wedge_2 ) {
140 vtkCellType = 26;
141 } else {
142 OOFEM_ERROR("unsupported element geometry type on element %d", elem->giveNumber() );
143 }
144
145 return vtkCellType;
146}
147
149 return giveCellType(this->emodel->giveDomain(1)->giveElement(num));
150}
151
152
153int
155{
156 switch ( cellType ) {
157 case 1:
158 return 1;
159
160 case 3:
161 return 2;
162
163 case 5:
164 case 21:
165 return 3;
166
167 case 9:
168 case 10:
169 return 4;
170
171 case 14:
172 return 5;
173
174 case 13:
175 case 22:
176 case 30:
177 return 6;
178
179 case 12:
180 case 23:
181 return 8;
182
183 case 24:
184 return 10;
185
186 case 25:
187 return 20;
188
189 case 29:
190 return 27;
191
192 default:
193 OOFEM_ERROR("unsupported cell type ID");
194 }
195
196 // return 0; // to make compiler happy
197}
198
199
200void
202{
203 // Gives the node mapping from the order used in OOFEM to that used in VTK
204
206 IntArray nodeMapping(0);
207 if ( ( elemGT == EGT_point ) ||
208 ( elemGT == EGT_line_1 ) || ( elemGT == EGT_line_2 ) ||
209 ( elemGT == EGT_triangle_1 ) || ( elemGT == EGT_triangle_2 ) ||
210 ( elemGT == EGT_tetra_1 ) || ( elemGT == EGT_tetra_2 ) ||
211 ( elemGT == EGT_quad_1 ) || ( elemGT == EGT_quad_2 ) ||
212 ( elemGT == EGT_hexa_1 ) || ( elemGT == EGT_quad9_2 ) ||
213 ( elemGT == EGT_wedge_1 ) )
214 {} else if ( elemGT == EGT_hexa_27 ) {
215 nodeMapping = {
216 5, 8, 7, 6, 1, 4, 3, 2, 16, 15, 14, 13, 12, 11, 10, 9, 17, 20, 19, 18, 23, 25, 26, 24, 22, 21, 27
217 };
218 } else if ( elemGT == EGT_hexa_2 ) {
219 nodeMapping = {
220 5, 8, 7, 6, 1, 4, 3, 2, 16, 15, 14, 13, 12, 11, 10, 9, 17, 20, 19, 18
221 };
222 } else if ( elemGT == EGT_wedge_2 ) {
223 nodeMapping = {
224 4, 6, 5, 1, 3, 2, 12, 11, 10, 9, 8, 7, 13, 15, 14
225 };
226 } else if ( elemGT == EGT_quad_1_interface ) {
227 nodeMapping = {
228 1, 2, 4, 3, 5, 6, 8, 7
229 };
230 } else if ( elemGT == EGT_quad_21_interface ) {
231 nodeMapping = {
232 1, 2, 5, 4, 3, 6
233 };
234 } else {
235 OOFEM_ERROR("VTKXMLExportModule: unsupported element geometry type");
236 }
237
238 int nelemNodes = giveNumberOfNodesPerCell(this->giveCellType(elem)); // elem->giveNumberOfNodes();
239 answer.resize(nelemNodes);
240 if ( nodeMapping.giveSize() > 0 ) {
241 for ( int i = 1; i <= nelemNodes; i++ ) {
242 answer.at(i) = elem->giveNode(nodeMapping.at(i) )->giveNumber();
243 }
244 } else {
245 for ( int i = 1; i <= nelemNodes; i++ ) {
246 answer.at(i) = elem->giveNode(i)->giveNumber();
247 }
248 }
249}
250
251
252bool
254{
255 return ( elem->giveGeometryType() == EGT_Composite );
256}
257
258void
260{
261 Domain *d = emodel->giveDomain(1);
262 Element *elem;
263
264 // output nodes Region By Region
265
266
267 // Assemble local->global and global->local region map and get number of
268 // single cells to process, the composite cells exported individually.
269 this->initRegionNodeNumbering(vtkPiece, d, tStep, region);
270 const IntArray& mapG2L = vtkPiece.getMapG2L();
271 const IntArray& mapL2G = vtkPiece.getMapL2G();
272 const int numNodes = vtkPiece.giveNumberOfNodes();
273 const int numRegionEl = vtkPiece.giveNumberOfCells();
274 if ( numNodes > 0 && numRegionEl > 0 ) {
275 // Export nodes as vtk vertices
276 vtkPiece.setNumberOfNodes(numNodes);
277 for ( int inode = 1; inode <= numNodes; inode++ ) {
278 const auto &coords = d->giveNode(mapL2G.at(inode) )->giveCoordinates();
279 vtkPiece.setNodeCoords(inode, coords);
280 }
281
282
283 //-------------------------------------------
284 // Export all the cell data for the piece
285 //-------------------------------------------
286 IntArray cellNodes;
287 vtkPiece.setNumberOfCells(numRegionEl);
288
289 int offset = 0;
290 int cellNum = 0;
291 IntArray elems = region.giveElementList();
292 for ( int ei = 1; ei <= elems.giveSize(); ei++ ) {
293 int elNum = elems.at(ei);
294 elem = d->giveElement(elNum);
295
296 // Skip elements that:
297 // are inactivated or of composite type ( these are exported individually later)
298 if ( this->isElementComposite(elem) || !elem->isActivated(tStep) ) {
299 continue;
300 }
301
302 //skip materials with casting time > current time
303 if ( !elem->isCast(tStep) ) {
304 continue;
305 }
306
307 if ( elem->giveParallelMode() != Element_local ) {
308 continue;
309 }
310
311 vtkPiece.getRegionCells().followedBy(elNum);
312
313 cellNum++;
314
315 // Set the connectivity
316 this->giveElementCell(cellNodes, elem); // node numbering of the cell according to the VTK format
317
318 // Map from global to local node numbers for the current piece
319 int numElNodes = cellNodes.giveSize();
320 IntArray connectivity(numElNodes);
321 for ( int i = 1; i <= numElNodes; i++ ) {
322 connectivity.at(i) = mapG2L.at(cellNodes.at(i) );
323 }
324
325 vtkPiece.setConnectivity(cellNum, connectivity);
326
327 vtkPiece.setCellType(cellNum, this->giveCellType(elem) ); // VTK cell type
328
329 offset += numElNodes;
330 vtkPiece.setOffset(cellNum, offset);
331 }
332
333
334
335/*
336#ifdef _PYBIND_BINDINGS
337 if ( pythonExport ) {
338 //Export nodes
339 py::list vals;
340 for ( int inode = 1; inode <= numNodes; inode++ ) {
341 py::list node;
342 const int numberG = d->giveNode(mapL2G.at(inode))->giveGlobalNumber();
343 const int number = d->giveNode(mapL2G.at(inode))->giveNumber();
344 const auto &coords = d->giveNode(mapL2G.at(inode))->giveCoordinates();
345 node.append(inode);
346 node.append(number);
347 node.append(numberG);
348 node.append(coords);
349 vals.append(node);
350 }
351 std::string s = std::to_string(region.giveNumber());
352 this->Py_Nodes[s.c_str()] = vals;//keys as region number (VTKPiece)
353
354 //Export elements
355 py::list elemVals;
356 for ( int ei = 1; ei <= vtkPiece.giveNumberOfCells(); ei++ ) {
357 py::list element;
358 IntArray &conn = vtkPiece.giveCellConnectivity(ei);
359 element.append(ei);
360 element.append(conn);
361 elemVals.append(element);
362 }
363 this->Py_Elements[s.c_str()] = elemVals;//keys as region number (VTKPiece)
364 }
365#endif
366*/
367
368 } // end of default piece for simple geometry elements
369}
370
371//----------------------------------------------------
372// Primary variables - readily available in the nodes
373//----------------------------------------------------
374void
375VTKBaseExportModule::exportPrimaryVars(ExportRegion &vtkPiece, Set &region, IntArray& primaryVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep)
376{
377 Domain *d = emodel->giveDomain(1);
378 FloatArray valueArray;
379 smoother.clear(); // Makes sure primary smoother is up-to-date with potentially new mesh.
380
381 //const IntArray& mapG2L = vtkPiece.getMapG2L();
382 const IntArray& mapL2G = vtkPiece.getMapL2G();
383
384 vtkPiece.setNumberOfPrimaryVarsToExport(primaryVarsToExport, mapL2G.giveSize() );
385 for ( int i = 1, n = primaryVarsToExport.giveSize(); i <= n; i++ ) {
386 UnknownType type = ( UnknownType ) primaryVarsToExport.at(i);
387
388 for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) {
389 DofManager *dman = d->giveNode(mapL2G.at(inode) );
390
391 this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region, smoother);
392 vtkPiece.setPrimaryVarInNode(type, inode, std::move(valueArray) );
393 }
394 }
395}
396
397
398void
400{
401 // This code is not perfect. It should be rewritten to handle all cases more gracefully.
404
405 IntArray dofIDMask(3);
406 int size;
407 const FloatArray *recoveredVal;
408
409 InternalStateType iState = IST_DisplacementVector; // Shouldn't be necessary
410
411 dofIDMask.clear();
412
413 if ( (type == DisplacementVector) || (type == ResidualForce) ) {
414 dofIDMask = {
415 ( int ) Undef, ( int ) Undef, ( int ) Undef
416 };
417 for ( Dof *dof : * dman ) {
418 DofIDItem id = dof->giveDofID();
419 if ( id == D_u ) {
420 dofIDMask.at(1) = id;
421 } else if ( id == D_v ) {
422 dofIDMask.at(2) = id;
423 } else if ( id == D_w ) {
424 dofIDMask.at(3) = id;
425 }
426 }
427
428 answer.resize(3);
429 } else if ( type == VelocityVector ) {
430 dofIDMask = {
431 ( int ) Undef, ( int ) Undef, ( int ) Undef
432 };
433 for ( Dof *dof : * dman ) {
434 DofIDItem id = dof->giveDofID();
435 if ( id == V_u ) {
436 dofIDMask.at(1) = id;
437 } else if ( id == V_v ) {
438 dofIDMask.at(2) = id;
439 } else if ( id == V_w ) {
440 dofIDMask.at(3) = id;
441 }
442 }
443
444 answer.resize(3);
445 } else if ( type == EigenVector ) {
446 dofIDMask = {
447 ( int ) Undef, ( int ) Undef, ( int ) Undef
448 };
449 for ( Dof *dof : * dman ) {
450 DofIDItem id = dof->giveDofID();
451 if ( ( id == V_u ) || ( id == D_u ) ) {
452 dofIDMask.at(1) = id;
453 } else if ( ( id == V_v ) || ( id == D_v ) ) {
454 dofIDMask.at(2) = id;
455 } else if ( ( id == V_w ) || ( id == D_w ) ) {
456 dofIDMask.at(3) = id;
457 }
458 }
459
460 answer.resize(3);
461 } else if ( type == FluxVector || type == Humidity ) {
462 dofIDMask.followedBy(C_1);
463 iState = IST_MassConcentration_1;
464 answer.resize(1);
465 } else if ( type == DeplanationFunction ) {
466 dofIDMask.followedBy(Warp_PsiTheta);
467 iState = IST_Temperature;
468 answer.resize(1);
469 } else if ( type == Temperature ) {
470 dofIDMask.followedBy(T_f);
471 iState = IST_Temperature;
472 answer.resize(1);
473 } else if ( type == PressureVector ) {
474 dofIDMask.followedBy(P_f);
475 iState = IST_Pressure;
476 answer.resize(1);
477 } else if ( type == DirectorField ) {
478 for ( Dof *dof : * dman ) {
479 DofIDItem id = dof->giveDofID();
480 if ( ( id == W_u ) || ( id == W_v ) || ( id == W_w ) ) {
481 dofIDMask.followedBy(id);
482 }
483
484 answer.resize(3);
485 }
486
487 iState = IST_DirectorField;
488 } else if ( type == MacroSlipVector ) {
489 for ( Dof *dof : * dman ) {
490 DofIDItem id = dof->giveDofID();
491 if ( ( id == S_u ) || ( id == S_v ) || ( id == S_w ) ) {
492 dofIDMask.followedBy(id);
493 }
494 answer.resize(3);
495 }
496 iState = IST_MacroSlipVector;
497 } else if ( type == Concentration) {
498 dofIDMask.followedBy(C_1);
499 answer.resize(1);
500 } else {
501 OOFEM_ERROR("unsupported unknownType %s", __UnknownTypeToString(type) );
502 }
503
504 size = dofIDMask.giveSize();
505 answer.zero();
506
507 for ( int j = 1; j <= size; j++ ) {
508 DofIDItem id = ( DofIDItem ) dofIDMask.at(j);
509 if ( id == Undef ) {
510 answer.at(j) = 0.;
511 } else if ( iState == IST_DirectorField ) {
512 answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Total, tStep);
513 // recover values if not done before
514 smoother.recoverValues(region, iState, tStep);
515 smoother.giveNodalVector(recoveredVal, dman->giveNumber() );
516 if ( size == recoveredVal->giveSize() ) {
517 answer.at(j) = recoveredVal->at(j);
518 } else {
519 OOFEM_WARNING("Recovered variable size mismatch for %d for id %d", type, id);
520 answer.at(j) = 0.0;
521 }
522 } else if (type == ResidualForce) {
523 answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Residual, tStep);
524 } else if ( dman->hasDofID(id) ) {
525 // primary variable available directly in DOF-manager
526 answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Total, tStep);
527 //mj - if incremental value needed: answer.at(j) = dman->giveDofWithID(id)->giveUnknown(VM_Incremental, tStep);
528 } else if ( iState != IST_Undefined ) {
529 // primary variable not directly available
530 // but equivalent InternalStateType provided
531 // in this case use smoother to recover nodal value
532
533 // This can't deal with ValueModeType, and would recover over and over for some vectorial quantities like velocity
534 // recover values if not done before.
535 smoother.recoverValues(region, iState, tStep);
536 smoother.giveNodalVector(recoveredVal, dman->giveNumber() );
537 // here we have a lack of information about how to convert recovered values to response
538 // if the size is compatible we accept it, otherwise give a warning and zero value.
539 if ( size == recoveredVal->giveSize() ) {
540 answer.at(j) = recoveredVal->at(j);
541 } else {
542 OOFEM_WARNING("Recovered variable size mismatch for \"%s\" for dof id %d. Size is %d, should be %d", __UnknownTypeToString(type), id, (int)recoveredVal->giveSize(), (int)size);
543 answer.at(j) = 0.0;
544 }
545 }
546 }
547
548
549
551 //rotate back from nodal CS to global CS if applies
552 if ( valType == ISVT_VECTOR ) {
553 Node *node = dynamic_cast< Node * >( dman );
554 if ( node && node->hasLocalCS() ) {
555 answer.rotatedWith(* node->giveLocalCoordinateTriplet(), 't');
556 }
557 }
558}
559
560
561//----------------------------------------------------
562// Internal variables and XFEM realted fields (keyword "vars" in OOFEM input file)
563//----------------------------------------------------
564void
565VTKBaseExportModule::exportIntVars(ExportRegion &vtkPiece, Set& region, IntArray& internalVarsToExport, NodalRecoveryModel& smoother, TimeStep *tStep)
566{
567 Domain *d = emodel->giveDomain(1);
568 InternalStateType isType;
569 FloatArray answer;
570 //IntArray& mapG2L = vtkPiece.getMapG2L();
571 IntArray& mapL2G = vtkPiece.getMapL2G();
572
573 smoother.clear(); // Makes sure smoother is up-to-date with potentially new mesh.
574
575 // Export of Internal State Type fields
576 vtkPiece.setNumberOfInternalVarsToExport(internalVarsToExport, mapL2G.giveSize() );
577 for ( int field = 1; field <= internalVarsToExport.giveSize(); field++ ) {
578 isType = ( InternalStateType ) internalVarsToExport.at(field);
579
580 for ( int nodeNum = 1; nodeNum <= mapL2G.giveSize(); nodeNum++ ) {
581 Node *node = d->giveNode(mapL2G.at(nodeNum) );
582 this->getNodalVariableFromIS(answer, node, tStep, isType, region, smoother);
583 vtkPiece.setInternalVarInNode(isType, nodeNum, answer);
584 }
585 }
586
587 /*
588 // Export of XFEM related quantities
589 if ( d->hasXfemManager() ) {
590 XfemManager *xFemMan = d->giveXfemManager();
591 int nEnrIt = xFemMan->giveNumberOfEnrichmentItems();
592
593 vtkPiece.setNumberOfInternalXFEMVarsToExport(xFemMan->vtkExportFields.giveSize(), nEnrIt, mapL2G.giveSize() );
594 for ( int field = 1; field <= xFemMan->vtkExportFields.giveSize(); field++ ) {
595 XFEMStateType xfemstype = ( XFEMStateType ) xFemMan->vtkExportFields [ field - 1 ];
596
597 for ( int enrItIndex = 1; enrItIndex <= nEnrIt; enrItIndex++ ) {
598 for ( int nodeIndx = 1; nodeIndx <= mapL2G.giveSize(); nodeIndx++ ) {
599 Node *node = d->giveNode(mapL2G.at(nodeIndx) );
600 getNodalVariableFromXFEMST(answer, node, tStep, xfemstype, region, xFemMan->giveEnrichmentItem(enrItIndex) );
601 vtkPiece.setInternalXFEMVarInNode(field, enrItIndex, nodeIndx, answer);
602 }
603 }
604 }
605 }
606 */
607}
608
609
610void
612{
613 // Recovers nodal values from Internal States defined in the integration points.
614 // Should return an array with proper size supported by VTK (1, 3 or 9)
615 // Domain *d = emodel->giveDomain(1);
616 IntArray redIndx;
617
618 if ( !( type == IST_DisplacementVector || type == IST_MaterialInterfaceVal ) ) {
619 smoother.recoverValues(region, type, tStep);
620 }
621
622
623 const FloatArray *val = NULL;
624 FloatArray valueArray;
626
627 if ( type == IST_DisplacementVector ) {
629 valueArray.resize(3);
630 val = & valueArray;
631 for ( int i = 1; i <= 3; i++ ) {
632 valueArray.at(i) = node->giveUpdatedCoordinate(i, tStep, 1.0) - node->giveCoordinate(i);
633 }
634 } else if ( type == IST_MaterialInterfaceVal ) {
635 MaterialInterface *mi = emodel->giveMaterialInterface(1);
636 if ( mi ) {
637 valueArray.resize(1);
638 val = & valueArray;
639 valueArray.at(1) = mi->giveNodalScalarRepresentation(node->giveNumber() );
640 }
641 } else {
642 int found = smoother.giveNodalVector(val, node->giveNumber() );
643 if ( !found ) {
644 valueArray.resize(redIndx.giveSize() );
645 val = & valueArray;
646 }
647 }
648
649 int ncomponents = giveInternalStateTypeSize(valType);
650 answer.resize(ncomponents);
651 int valSize = val->giveSize(); // size of recovered quantity
652
653 // check if valSize corresponds to the expected size otherwise pad with zeros
654 if ( valType == ISVT_SCALAR ) {
655 answer.at(1) = valSize ? val->at(1) : 0.0;
656 } else if ( valType == ISVT_VECTOR ) {
657 answer = * val;
658 // bp: hack for BeamForceMomentTensor, which should be splitted into force and momentum vectors
659 if ( type == IST_BeamForceMomentTensor ) {
660 answer.resizeWithValues(6);
661 } else {
662 answer.resizeWithValues(3);
663 }
664 } else if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) {
665 this->makeFullTensorForm(answer, * val, valType);
666 } else {
667 OOFEM_ERROR("ISVT_UNDEFINED encountered")
668 }
669}
670
671
672
673//----------------------------------------------------
674// Cell vars
675//----------------------------------------------------
676
677void
678VTKBaseExportModule::exportCellVars(ExportRegion &vtkPiece, Set& region, IntArray& cellVarsToExport, TimeStep *tStep)
679{
680 Domain *d = emodel->giveDomain(1);
681 FloatArray valueArray;
682 const IntArray &elems = region.giveElementList();
683
684 vtkPiece.setNumberOfCellVarsToExport(cellVarsToExport, elems.giveSize() );
685 for ( int field = 1; field <= cellVarsToExport.giveSize(); field++ ) {
686 InternalStateType type = ( InternalStateType ) cellVarsToExport.at(field);
687
688 for ( int subIndex = 1; subIndex <= elems.giveSize(); ++subIndex ) {
689 Element *el = d->giveElement(elems.at(subIndex) );
690 if ( el->giveParallelMode() != Element_local ) {
691 continue;
692 }
693
694 this->getCellVariableFromIS(valueArray, el, type, tStep);
695 vtkPiece.setCellVar(type, subIndex, valueArray);
696 }
697 }
698}
699
700
701void
703{
705 int ncomponents = giveInternalStateTypeSize(valType);
706
707 answer.resize(ncomponents);
708
709 switch ( type ) {
710 // Special scalars
711 case IST_MaterialNumber:
712 // commented by bp: do what user wants
713 //OOFEM_WARNING1("Material numbers are deprecated, outputing cross section number instead...");
714 answer.at(1) = ( double ) el->giveMaterial()->giveNumber();
715 break;
716 case IST_CrossSectionNumber:
717 answer.at(1) = ( double ) el->giveCrossSection()->giveNumber();
718 break;
719 case IST_ElementNumber:
720 answer.at(1) = ( double ) el->giveNumber();
721 break;
722 case IST_Pressure:
723 if ( el->giveNumberOfInternalDofManagers() == 1 ) {
724 //IntArray pmask(1); pmask.at(1) = P_f;
725 //el->giveInternalDofManager(1)->giveUnknownVector (answer, pmask, VM_Total, tStep);
726 //answer.at(1) = answer.at(1);
727 }
728
729 break;
730 case IST_AbaqusStateVector:
731 {
732 // compute cell average from ip values
734 computeIPAverage(answer, iRule, el, type, tStep); // if element has more than one iRule?? /JB
735 }
736 break;
737
738 // Special vectors
739 case IST_MaterialOrientation_x:
740 case IST_MaterialOrientation_y:
741 case IST_MaterialOrientation_z:
742 {
743 FloatMatrix rotMat;
744 int col = 0;
745 if ( type == IST_MaterialOrientation_x ) {
746 col = 1;
747 } else if ( type == IST_MaterialOrientation_y ) {
748 col = 2;
749 } else if ( type == IST_MaterialOrientation_z ) {
750 col = 3;
751 }
752
753 if ( !el->giveLocalCoordinateSystem(rotMat) ) {
754 rotMat.resize(3, 3);
755 rotMat.beUnitMatrix();
756 }
757
758 answer.beColumnOf(rotMat, col);
759 break;
760 }
761 case IST_VOFFraction:
762 case IST_VolumeFraction:
763 {
764 if (this->emodel->giveField(FieldType::FT_VOF, tStep)) {
765 this->emodel->giveField(FieldType::FT_VOF, tStep)->evaluateAt(answer, el, VM_Total, tStep);
766 } else {
767 answer.at(1) = 0.0;
768 }
769 break;
770 }
771
772 // Export cell data as average from ip's as default
773 default:
774
775 // compute cell average from ip values
777 computeIPAverage(answer, iRule, el, type, tStep); // if element has more than one iRule?? /JB
778 // Reshape the Voigt vectors to include all components (duplicated if necessary, VTK insists on 9 components for tensors.)
781 if ( valType == ISVT_TENSOR_S3 || valType == ISVT_TENSOR_S3E || valType == ISVT_TENSOR_G ) {
782 FloatArray temp = answer;
783 this->makeFullTensorForm(answer, temp, valType);
784 } else if ( valType == ISVT_VECTOR && answer.giveSize() < 3 ) {
785 answer.resizeWithValues(3);
786 } else if ( ncomponents != answer.giveSize() ) { // Trying to gracefully handle bad cases, just output zeros.
787 answer.resizeWithValues(ncomponents);
788 }
789 }
790}
791
792
793int
795 Domain *domain, TimeStep *tStep, Set& region)
796{
797 // regionG2LNodalNumbers is array with mapping from global numbering to local region numbering.
798 // The i-th value contains the corresponding local region number (or zero, if global number is not in region).
799
800 // regionL2GNodalNumbers is array with mapping from local to global numbering.
801 // The i-th value contains the corresponding global node number.
802
803
804 int nnodes = domain->giveNumberOfDofManagers();
805 int elemNodes;
806 int elementNode, node;
807 int currOffset = 1;
808 Element *element;
809
810 IntArray &regionG2LNodalNumbers = piece.getMapG2L();
811 IntArray &regionL2GNodalNumbers = piece.getMapL2G();
812
813 regionG2LNodalNumbers.resize(nnodes);
814 regionG2LNodalNumbers.zero();
815 int regionDofMans = 0;
816 int regionSingleCells = 0;
817
818 const IntArray& elements = region.giveElementList();
819 for ( int ie = 1; ie <= elements.giveSize(); ie++ ) {
820 int ielem = elements.at(ie);
821 element = domain->giveElement(ielem);
822
823 if ( this->isElementComposite(element) ) {
824 continue; // composite cells exported individually
825 }
826
827 if ( !element->isActivated(tStep) ) { //skip inactivated elements
828 continue;
829 }
830
831 //skip materials with casting time > current time
832 if ( !element->isCast(tStep) ) {
833 continue;
834 }
835
836 if ( element->giveParallelMode() != Element_local ) {
837 continue;
838 }
839
840 regionSingleCells++;
841 elemNodes = element->giveNumberOfNodes();
842 // elemSides = element->giveNumberOfSides();
843
844 // determine local region node numbering
845 for ( elementNode = 1; elementNode <= elemNodes; elementNode++ ) {
846 node = element->giveNode(elementNode)->giveNumber();
847 if ( regionG2LNodalNumbers.at(node) == 0 ) { // assign new number
848 /* mark for assignment. This is done later, as it allows to preserve
849 * natural node numbering.
850 */
851 regionG2LNodalNumbers.at(node) = 1;
852 regionDofMans++;
853 }
854 }
855 }
856
857 regionL2GNodalNumbers.resize(regionDofMans);
858
859 for ( int i = 1; i <= nnodes; i++ ) {
860 if ( regionG2LNodalNumbers.at(i) ) {
861 regionG2LNodalNumbers.at(i) = currOffset++;
862 regionL2GNodalNumbers.at(regionG2LNodalNumbers.at(i) ) = i;
863 }
864 }
865
866 piece.setNumberOfCells(regionSingleCells);
867 piece.setNumberOfNodes(regionDofMans);
868
869 return 1;
870}
871
872void
874{
875 // Computes the volume average (over an element) for the quantity defined by isType
876 double gptot = 0.0;
877 answer.clear();
878 FloatArray temp;
879 if ( iRule ) {
880 for ( IntegrationPoint *ip : * iRule ) {
881 elem->giveIPValue(temp, ip, isType, tStep);
882 gptot += ip->giveWeight();
883 answer.add(ip->giveWeight(), temp);
884 }
885
886 answer.times(1. / gptot);
887 }
888}
889
890//----------------------------------------------------
891// Load vectors
892//----------------------------------------------------
893void
894VTKBaseExportModule::exportExternalForces(ExportRegion &vtkPiece, Set& region, IntArray& externalForcesToExport, TimeStep *tStep)
895{
896 Domain *d = emodel->giveDomain(1);
897 //this->givePrimVarSmoother()->clear(); // Makes sure primary smoother is up-to-date with potentially new mesh.
898 //IntArray& mapG2L = vtkPiece.getMapG2L();
899 IntArray& mapL2G = vtkPiece.getMapL2G();
900
901 if ( externalForcesToExport.giveSize() == 0 ) {
902 return;
903 }
904
907 int neq = emodel->giveNumberOfDomainEquations(1, EModelDefaultEquationNumbering() );
908 int npeq = emodel->giveNumberOfDomainEquations(1, EModelDefaultPrescribedEquationNumbering() );
909 FloatArray extForces(neq), extForcesP(npeq);
910 emodel->assembleVector(extForces, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultEquationNumbering(), d);
911 emodel->assembleVector(extForcesP, tStep, ExternalForceAssembler(), VM_Total, EModelDefaultPrescribedEquationNumbering(), d);
912
913 vtkPiece.setNumberOfLoadsToExport(externalForcesToExport.giveSize(), mapL2G.giveSize() );
914 for ( int i = 1; i <= externalForcesToExport.giveSize(); i++ ) {
915 UnknownType type = ( UnknownType ) externalForcesToExport.at(i);
917 IntArray dofids;
918 if ( type == VelocityVector ) {
919 dofids = {
920 V_u, V_v, V_w
921 };
922 } else if ( type == DisplacementVector ) {
923 dofids = {
924 D_u, D_v, D_w
925 };
926 } else if ( type == PressureVector ) {
927 dofids = {
928 P_f
929 };
930 } else {
931 OOFEM_WARNING("Unrecognized UnknownType (%d), no external forces exported", type);
932 }
933
934 for ( int inode = 1; inode <= mapL2G.giveSize(); inode++ ) {
935 DofManager *dman = d->giveNode(mapL2G.at(inode) );
936
937 FloatArray valueArray(dofids.giveSize() );
938 for ( int k = 1; k <= dofids.giveSize(); ++k ) {
939 Dof *dof = dman->giveDofWithID(dofids.at(k) );
941 int eq;
942 if ( ( eq = dof->giveEquationNumber(EModelDefaultEquationNumbering() ) ) > 0 ) {
943 valueArray.at(k) = extForces.at(eq);
944 } else if ( ( eq = dof->giveEquationNumber(EModelDefaultPrescribedEquationNumbering() ) ) > 0 ) {
945 valueArray.at(k) = extForcesP.at(eq);
946 }
947 }
948 //this->getNodalVariableFromPrimaryField(valueArray, dman, tStep, type, region);
949 vtkPiece.setLoadInNode(i, inode, std::move(valueArray) );
950 }
951 }
952}
953
954void
956{
957 Domain *d = emodel->giveDomain(1);
958 FloatArray valueArray;
959 int nsets = d->giveNumberOfSets();
960 const IntArray &elems = region.giveElementList();
961 const IntArray &nodes = region.giveNodeList();
962 IntArray &regionG2LNodalNumbers = vtkPiece.getMapG2L();
963 vtkPiece.setNumberOfSetMembershipsToExport(nsets, nodes.giveSize(), elems.giveSize() );
964 const IntArray& regionElements = region.giveElementList();
965
966 for ( int iset = 1; iset <= nsets; iset++ ) {
967 Set *set = d->giveSet(iset);
968
969 const IntArray &setNodes = set->giveSpecifiedNodeList();
970 //const IntArray &setElems = set->giveElementList();
971
972 for (int node : setNodes) {
973 int regionNode = regionG2LNodalNumbers.at(node);
974 if (regionNode == 0) {
975 continue; // node not in region
976 }
977 vtkPiece.setVertexSetMembership(iset, regionNode);
978 }
979
980 for (int ic=1; ic<=regionElements.giveSize(); ic++) {
981 int regionCell = regionElements.at(ic);
982 // now test if region cell is in the set
983 if (set->hasElement(regionCell) ) {
984 vtkPiece.setCellSetMembership(iset, ic);
985 }
986 }
987 }
988}
989
990
991
992
993// End of VTKBaseExportModule implementation
994
995
996
997} // end namespace oofem
bool hasDofID(DofIDItem id) const
Definition dofmanager.C:174
double giveCoordinate(int i) const
Definition dofmanager.h:383
const FloatArray & giveCoordinates() const
Definition dofmanager.h:390
Dof * giveDofWithID(int dofID) const
Definition dofmanager.C:127
int giveEquationNumber(const UnknownNumberingScheme &s)
Definition dof.C:56
virtual double giveUnknown(ValueModeType mode, TimeStep *tStep)=0
Set * giveSet(int n)
Definition domain.C:366
int giveNumberOfSets() const
Returns number of sets.
Definition domain.h:479
int giveNumberOfDofManagers() const
Returns number of dof managers in domain.
Definition domain.h:461
Element * giveElement(int n)
Definition domain.C:165
Node * giveNode(int n)
Definition domain.h:398
Node * giveNode(int i) const
Definition element.h:629
virtual bool isActivated(TimeStep *tStep)
Definition element.C:838
virtual int giveNumberOfNodes() const
Definition element.h:703
virtual int giveNumberOfInternalDofManagers() const
Definition element.h:243
virtual Material * giveMaterial()
Definition element.C:523
virtual int giveLocalCoordinateSystem(FloatMatrix &answer)
Definition element.C:1252
elementParallelMode giveParallelMode() const
Definition element.h:1139
CrossSection * giveCrossSection()
Definition element.C:534
virtual IntegrationRule * giveDefaultIntegrationRulePtr()
Definition element.h:886
virtual bool isCast(TimeStep *tStep)
Definition element.C:853
virtual int giveIPValue(FloatArray &answer, GaussPoint *gp, InternalStateType type, TimeStep *tStep)
Definition element.C:1298
virtual Element_Geometry_Type giveGeometryType() const =0
virtual void initialize()
ExportModule(int n, EngngModel *e)
Constructor. Creates empty Output Manager with number n.
EngngModel * emodel
Problem pointer.
Stores all neccessary data (of a region) in a VTKPiece so it can be exported later.
IntArray & getMapL2G()
void setCellVar(InternalStateType type, int cellNum, FloatArray valueArray)
void setInternalVarInNode(InternalStateType type, int nodeNum, FloatArray valueArray)
void setNumberOfLoadsToExport(int numVars, int numNodes)
void setCellType(int cellNum, int type)
void setNumberOfCellVarsToExport(const IntArray &cellVars, int numCells)
void setNumberOfInternalVarsToExport(const IntArray &ists, int numNodes)
void setLoadInNode(int varNum, int nodeNum, FloatArray valueArray)
void setNumberOfPrimaryVarsToExport(const IntArray &primVars, int numNodes)
IntArray & getRegionCells()
void setConnectivity(int cellNum, IntArray &nodes)
void setVertexSetMembership(int set, int nodeNum)
void setPrimaryVarInNode(UnknownType type, int nodeNum, FloatArray valueArray)
IntArray & getMapG2L()
void setNumberOfSetMembershipsToExport(int numSets, int numNodes, int numCells)
void setOffset(int cellNum, int offset)
void setNumberOfCells(int numCells)
void setNodeCoords(int nodeNum, const FloatArray &coords)
void setCellSetMembership(int set, int cellNum)
void setNumberOfNodes(int numNodes)
int giveNumber() const
Definition femcmpnn.h:104
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 resizeWithValues(Index s, std::size_t allocChunk=0)
Definition floatarray.C:103
void beColumnOf(const FloatMatrix &mat, int col)
void zero()
Zeroes all coefficients of receiver.
Definition floatarray.C:683
void rotatedWith(FloatMatrix &r, char mode)
Definition floatarray.C:814
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 beUnitMatrix()
Sets receiver to unity matrix.
void followedBy(const IntArray &b, int allocChunk=0)
Definition intarray.C:94
void resize(int n)
Definition intarray.C:73
void zero()
Sets all component to zero.
Definition intarray.C:52
int & at(std::size_t i)
Definition intarray.h:104
int giveSize() const
Definition intarray.h:211
virtual double giveNodalScalarRepresentation(int)=0
virtual int recoverValues(Set elementSet, InternalStateType type, TimeStep *tStep)=0
int giveNodalVector(const FloatArray *&ptr, int node)
FloatMatrix * giveLocalCoordinateTriplet()
Definition node.h:149
bool hasLocalCS()
Returns nonzero if node has prescribed local coordinate system.
Definition node.h:141
virtual double giveUpdatedCoordinate(int ic, TimeStep *tStep, double scale=1.)
Definition node.C:234
const IntArray & giveSpecifiedNodeList()
Definition set.C:229
bool hasElement(int elem) const
Return True if given element is contained.
Definition set.C:245
const IntArray & giveElementList()
Definition set.C:158
const IntArray & giveNodeList()
Definition set.C:168
void exportSetMembership(ExportRegion &piece, Set &region, TimeStep *tStep)
static IntArray redToFull
Map from Voigt to full tensor.
int giveNumberOfNodesPerCell(int cellType)
virtual ~VTKBaseExportModule()
Destructor.
bool isElementComposite(Element *elem)
void exportCellVars(ExportRegion &piece, Set &region, IntArray &cellVarsToExport, TimeStep *tStep)
Exports cell variables (typically internal variables).
void giveElementCell(IntArray &answer, Element *elem)
static void makeFullTensorForm(FloatArray &answer, const FloatArray &reducedForm, InternalStateValueType vtype)
Gives the full form of given symmetrically stored tensors, missing components are filled with zeros.
void getNodalVariableFromIS(FloatArray &answer, Node *node, TimeStep *tStep, InternalStateType type, Set &region, NodalRecoveryModel &smoother)
int giveCellType(Element *element)
virtual int initRegionNodeNumbering(ExportRegion &vtkPiece, Domain *domain, TimeStep *tStep, Set &region)
VTKBaseExportModule(int n, EngngModel *e)
Constructor. Creates empty Output Manager. By default all components are selected.
virtual void exportIntVars(ExportRegion &piece, Set &region, IntArray &internalVarsToExport, NodalRecoveryModel &smoother, TimeStep *tStep)
void exportExternalForces(ExportRegion &piece, int region, TimeStep *tStep)
static void computeIPAverage(FloatArray &answer, IntegrationRule *iRule, Element *elem, InternalStateType isType, TimeStep *tStep)
void getCellVariableFromIS(FloatArray &answer, Element *el, InternalStateType type, TimeStep *tStep)
void getNodalVariableFromPrimaryField(FloatArray &answer, DofManager *dman, TimeStep *tStep, UnknownType type, Set &region, NodalRecoveryModel &smoother)
virtual void setupVTKPiece(ExportRegion &vtkPiece, TimeStep *tStep, Set &region)
virtual void exportPrimaryVars(ExportRegion &piece, Set &region, IntArray &primaryVarsToExport, NodalRecoveryModel &smoother, TimeStep *tStep)
#define OOFEM_WARNING(...)
Definition error.h:80
#define OOFEM_ERROR(...)
Definition error.h:79
@ Element_local
Element is local, there are no contributions from other domains to this element.
Definition element.h:88
GaussPoint IntegrationPoint
Definition gausspoint.h:272
int giveInternalStateTypeSize(InternalStateValueType valType)
Definition cltypes.C:229
InternalStateValueType
Determines the type of internal variable.
@ ISVT_TENSOR_S3E
symmetric 3x3 tensor, packed with off diagonal components multiplied by 2 (engineering strain vector,...
@ ISVT_SCALAR
Scalar.
@ ISVT_TENSOR_S3
Symmetric 3x3 tensor.
@ ISVT_VECTOR
Vector.
@ ISVT_TENSOR_G
General tensor.
const char * __UnknownTypeToString(UnknownType _value)
Definition cltypes.C:313
InternalStateValueType giveInternalStateValueType(InternalStateType type)
Definition cltypes.C:75

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