void VTKXMLExportModule :: doOutput(TimeStep *tStep) { if ( !testTimeStepOutput(tStep) ) { return; } #ifdef __VTK_MODULE vtkSmartPointer<vtkUnstructuredGrid> stream = vtkSmartPointer<vtkUnstructuredGrid>::New(); vtkSmartPointer<vtkPoints> nodes = vtkSmartPointer<vtkPoints>::New(); vtkSmartPointer<vtkIdList> elemNodeArray = vtkSmartPointer<vtkIdList>::New(); #else FILE *stream = this->giveOutputStream(tStep); struct tm *current; time_t now; time(&now); current = localtime(&now); fprintf(stream, "<!-- TimeStep %e Computed %d-%02d-%02d at %02d:%02d:%02d -->\n", tStep->giveIntrinsicTime(), current->tm_year+1900, current->tm_mon+1, current->tm_mday, current->tm_hour, current->tm_min, current->tm_sec); fprintf(stream, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n"); fprintf(stream, "<UnstructuredGrid>\n"); #endif Domain *d = emodel->giveDomain(1); Element *elem; FloatArray *coords; int nelem = d->giveNumberOfElements(); this->giveSmoother(); // make sure smoother is created // output nodes Region By Region int nregions = this->smoother->giveNumberOfVirtualRegions(); int regionDofMans, totalcells; IntArray mapG2L, mapL2G; /* loop over regions */ for ( int ireg = 1; ireg <= nregions; ireg++ ) { if ( ( ireg > 0 ) && ( this->regionsToSkip.contains(ireg) ) ) { continue; } // assemble local->global and global->local region map // and get number of single cells to process // the composite cells exported individually this->initRegionNodeNumbering(mapG2L, mapL2G, regionDofMans, totalcells, d, ireg); /* start default piece containing all single cell elements * the elements with composite geometry are assumed to be exported in individual pieces * after the default one */ #ifndef __PARALLEL_MODE if ( regionDofMans && totalcells ) { #else if ( 1 ) { #endif #ifdef __VTK_MODULE for ( int inode = 1; inode <= regionDofMans; inode++ ) { coords = d->giveNode(mapL2G.at(inode))->giveCoordinates(); int dims = coords->giveSize(); nodes->InsertNextPoint(coords->at(1), dims >= 2 ? coords->at(2) : 0.0, dims >= 3 ? coords->at(3) : 0.0); } stream->SetPoints(nodes); #else fprintf(stream, "<Piece NumberOfPoints=\"%d\" NumberOfCells=\"%d\">\n", regionDofMans, totalcells); // export nodes in region as vtk vertices fprintf(stream, "<Points>\n <DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\"> "); for ( int inode = 1; inode <= regionDofMans; inode++ ) { coords = d->giveNode( mapL2G.at(inode) )->giveCoordinates(); for ( int i = 1; i <= coords->giveSize(); i++ ) { fprintf( stream, "%e ", coords->at(i) ); } for ( int i = coords->giveSize() + 1; i <= 3; i++ ) { fprintf(stream, "%e ", 0.0); } } fprintf(stream, "</DataArray>\n</Points>\n"); #endif // output all cells of the piece int nelemNodes; IntArray cellNodes; #ifdef __VTK_MODULE stream->Allocate(nelem); #else fprintf(stream, "<Cells>\n"); // output the connectivity data fprintf(stream, " <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\"> "); #endif for ( int ielem = 1; ielem <= nelem; ielem++ ) { elem = d->giveElement(ielem); if ( ( ireg > 0 ) && ( this->smoother->giveElementVirtualRegionNumber(ielem) != ireg ) ) { continue; } if ( this->isElementComposite(elem) ) { continue; // composite cells exported individually } if ( !elem-> isActivated(tStep) ) { //skip inactivated elements continue; } #ifdef __PARALLEL_MODE if ( elem->giveParallelMode() != Element_local ) { continue; } #endif nelemNodes = elem->giveNumberOfNodes(); this->giveElementCell(cellNodes, elem, 0); #ifdef __VTK_MODULE elemNodeArray->Reset(); elemNodeArray->SetNumberOfIds(nelemNodes); #endif for ( int i = 1; i <= nelemNodes; i++ ) { #ifdef __VTK_MODULE elemNodeArray->SetId(i-1, mapG2L.at( cellNodes.at(i) ) - 1); #else fprintf(stream, "%d ", mapG2L.at( cellNodes.at(i) ) - 1); #endif } #ifdef __VTK_MODULE stream->InsertNextCell(this->giveCellType(elem), elemNodeArray); #else fprintf(stream, " "); #endif } #ifndef __VTK_MODULE int vtkCellType; fprintf(stream, "</DataArray>\n"); // output the offsets (index of individual element data in connectivity array) fprintf(stream, " <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\"> "); int offset = 0; for ( int ielem = 1; ielem <= nelem; ielem++ ) { elem = d->giveElement(ielem); if ( ( ireg > 0 ) && ( this->smoother->giveElementVirtualRegionNumber(ielem) != ireg ) ) { continue; } #ifdef __PARALLEL_MODE if ( elem->giveParallelMode() != Element_local ) { continue; } #endif offset += elem->giveNumberOfNodes(); fprintf(stream, "%d ", offset); } fprintf(stream, "</DataArray>\n"); // output cell (element) types fprintf(stream, " <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\"> "); for ( int ielem = 1; ielem <= nelem; ielem++ ) { elem = d->giveElement(ielem); if ( ( ireg > 0 ) && ( this->smoother->giveElementVirtualRegionNumber(ielem) != ireg ) ) { continue; } if ( this->isElementComposite(elem) ) { continue; // composite cells exported individually } #ifdef __PARALLEL_MODE if ( elem->giveParallelMode() != Element_local ) { continue; } #endif vtkCellType = this->giveCellType(elem); fprintf(stream, "%d ", vtkCellType); } fprintf(stream, "</DataArray>\n"); fprintf(stream, "</Cells>\n"); #endif // export primary and internal variables #ifndef __VTK_MODULE this->exportPointDataHeader(stream, tStep); #endif this->exportPrimaryVars(stream, mapG2L, mapL2G, regionDofMans, ireg, tStep); this->exportIntVars(stream, mapG2L, mapL2G, regionDofMans, ireg, tStep); #ifndef __VTK_MODULE fprintf(stream, "</PointData>\n"); #endif //export cell data this->exportCellVars(stream, ireg, tStep); #ifndef __VTK_MODULE // end of piece record fprintf(stream, "</Piece>\n"); #endif } // end of default piece for simple geometry elements #if 1 // loop over region elements with multi-cell geometry for ( int ielem = 1; ielem <= nelem; ielem++ ) { elem = d->giveElement(ielem); if ( this->regionsToSkip.contains( this->smoother->giveElementVirtualRegionNumber(ielem) ) ) { continue; } #ifdef __PARALLEL_MODE if ( elem->giveParallelMode() != Element_local ) { continue; } #endif if ( this->isElementComposite(elem) ) { #ifndef __VTK_MODULE ///@todo Not sure how to deal with this. // multi cell (composite) elements should support vtkxmlexportmoduleinterface // and are exported as individual pieces (see VTKXMLExportModuleElementInterface) VTKXMLExportModuleElementInterface *interface = ( VTKXMLExportModuleElementInterface * ) elem->giveInterface(VTKXMLExportModuleElementInterfaceType); if ( interface ) { // passing this to access general piece related methods like exportPointDataHeader, etc. interface->_export(stream, this, primaryVarsToExport, internalVarsToExport, tStep); } #endif } } // end loop over multi-cell elements #endif } // end loop over regions std::string fname = giveOutputFileName(tStep); #ifdef __VTK_MODULE #if 0 // Doesn't as well as I would want it to, interface to VTK is to limited to control this. // * The PVTU-file is written by every process (seems to be impossible to avoid). // * Part files are renamed and time step and everything else is cut off => name collisions vtkSmartPointer<vtkXMLPUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLPUnstructuredGridWriter>::New(); writer->SetTimeStep(tStep->giveNumber()-1); writer->SetNumberOfPieces( this->emodel->giveNumberOfProcesses() ); writer->SetStartPiece( this->emodel->giveRank() ); writer->SetEndPiece( this->emodel->giveRank() ); #else vtkSmartPointer<vtkXMLUnstructuredGridWriter> writer = vtkSmartPointer<vtkXMLUnstructuredGridWriter>::New(); #endif writer->SetFileName(fname.c_str()); writer->SetInput(stream); // Optional - set the mode. The default is binary. //writer->SetDataModeToBinary(); //writer->SetDataModeToAscii(); writer->Write(); #else // finish unstructured grid data and vtk file fprintf(stream, "</UnstructuredGrid>\n</VTKFile>"); fclose(stream); #endif // Writing the *.pvd-file. Only time step information for now. It's named "timestep" but is actually the total time. // First we check to see that there are more than 1 time steps, otherwise it is redundant; #ifdef __PARALLEL_MODE if ( emodel->isParallel() && emodel->giveRank() == 0 ) { ///@todo Should use probably use PVTU-files instead. It is starting to get messy. // For this to work, all processes must have an identical output file name. for (int i = 0; i < this->emodel->giveNumberOfProcesses(); ++i) { std::ostringstream pvdEntry; char fext[100]; if (this->emodel->giveNumberOfProcesses() > 1) { sprintf( fext, "_%03d.m%d.%d", i, this->number, tStep->giveNumber() ); } else { sprintf( fext, "m%d.%d", this->number, tStep->giveNumber() ); } pvdEntry << "<DataSet timestep=\"" << tStep->giveIntrinsicTime() << "\" group=\"\" part=\"" << i << "\" file=\"" << this->emodel->giveOutputBaseFileName() << fext << ".vtu\"/>"; this->pvdBuffer.push_back(pvdEntry.str()); } this->writeVTKCollection(); } else #endif if ( !emodel->isParallel() && tStep->giveNumber() >= 1 ) { // For non-parallel enabled OOFEM, then we only check for multiple steps. std::ostringstream pvdEntry; pvdEntry << "<DataSet timestep=\"" << tStep->giveIntrinsicTime() << "\" group=\"\" part=\"\" file=\"" << fname << "\"/>"; this->pvdBuffer.push_back(pvdEntry.str()); this->writeVTKCollection(); } } #ifndef __VTK_MODULE void VTKXMLExportModule :: exportPointDataHeader(FILE *stream, TimeStep *tStep) { int n; std :: string scalars, vectors, tensors; n = primaryVarsToExport.giveSize(); UnknownType type; for ( int i = 1; i <= n; i++ ) { type = ( UnknownType ) primaryVarsToExport.at(i); if ( ( type == DisplacementVector ) || ( type == EigenVector ) || ( type == VelocityVector ) ) { vectors += __UnknownTypeToString(type); vectors.append(" "); } else if ( ( type == FluxVector ) || ( type == PressureVector ) || ( type == Temperature ) ) { scalars += __UnknownTypeToString(type); scalars.append(" "); } else { OOFEM_ERROR2( "VTKXMLExportModule::exportPrimVarAs: unsupported UnknownType %s", __UnknownTypeToString(type) ); } } InternalStateType isttype; InternalStateValueType vtype; n = internalVarsToExport.giveSize(); // prepare header for ( int i = 1; i <= n; i++ ) { isttype = ( InternalStateType ) internalVarsToExport.at(i); vtype = giveInternalStateValueType(isttype); if ( vtype == ISVT_SCALAR ) { scalars += __InternalStateTypeToString(isttype); scalars.append(" "); } else if ( vtype == ISVT_VECTOR ) { vectors += __InternalStateTypeToString(isttype); vectors.append(" "); } else if ( ( vtype == ISVT_TENSOR_S3 ) || ( vtype == ISVT_TENSOR_S3E ) ) { tensors += __InternalStateTypeToString(isttype); tensors.append(" "); } else if ( vtype == ISVT_TENSOR_G ) { vectors += __InternalStateTypeToString(isttype); vectors.append(" "); } else { fprintf( stderr, "VTKXMLExportModule::exportIntVars: unsupported variable type %s\n", __InternalStateTypeToString(isttype) ); } } // print header fprintf( stream, "<PointData Scalars=\"%s\" Vectors=\"%s\" Tensors=\"%s\" >\n", scalars.c_str(), vectors.c_str(), tensors.c_str() ); }