VTKEdgeDoFWriter.cpp 8.73 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*
 * Copyright (c) 2017-2021 Dominik Thoennes, Marcus Mohr, Nils Kohl.
 *
 * This file is part of HyTeG
 * (see https://i10git.cs.fau.de/hyteg/hyteg).
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include "hyteg/dataexport/VTKEdgeDoFWriter.hpp"

#include "core/DataTypes.h"

#include "hyteg/dataexport/VTKHelpers.hpp"
#include "hyteg/dataexport/VTKOutput.hpp"
#include "hyteg/edgedofspace/EdgeDoFMacroCell.hpp"

28
29
30
// from walberla
#include "vtk/UtilityFunctions.h"

31
32
namespace hyteg {

33
34
using walberla::vtk::typeToString;

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
void VTKEdgeDoFWriter::write( const VTKOutput& mgr, std::ostream& output, uint_t level, const vtk::DoFType& dofType )
{
   WALBERLA_ASSERT( dofType == vtk::DoFType::EDGE_X || dofType == vtk::DoFType::EDGE_Y || dofType == vtk::DoFType::EDGE_Z ||
                    dofType == vtk::DoFType::EDGE_XY || dofType == vtk::DoFType::EDGE_XZ || dofType == vtk::DoFType::EDGE_YZ ||
                    dofType == vtk::DoFType::EDGE_XYZ );

   if ( mgr.edgeDoFFunctions_.size() == 0 )
   {
      return;
   }

   auto storage = mgr.storage_;

   const uint_t numberOfPoints2D = storage->getNumberOfLocalFaces() * levelinfo::num_microedges_per_face( level ) / 3;
   const uint_t faceWidth        = levelinfo::num_microedges_per_edge( level );
   const uint_t numberOfCells2D  = storage->getNumberOfLocalFaces() * ( ( ( ( faceWidth - 1 ) * faceWidth ) / 2 ) +
                                                                       ( ( ( faceWidth - 2 ) * ( faceWidth - 1 ) ) / 2 ) );

   const uint_t numberOfPoints3D = storage->getNumberOfLocalCells() * [dofType, level]() {
      if ( dofType == vtk::DoFType::EDGE_XYZ )
         return levelinfo::num_microvertices_per_cell_from_width( levelinfo::num_microedges_per_edge( level ) - 1 );
      else
         return levelinfo::num_microvertices_per_cell_from_width( levelinfo::num_microedges_per_edge( level ) );
   }();
   const uint_t numberOfCells3D = storage->getNumberOfLocalCells() * [dofType, level]() {
      if ( dofType == vtk::DoFType::EDGE_XYZ )
         return levelinfo::num_microcells_per_cell_from_width( levelinfo::num_microedges_per_edge( level ) - 1 );
      else
         return levelinfo::num_microcells_per_cell_from_width( levelinfo::num_microedges_per_edge( level ) );
   }();

   if ( mgr.write2D_ )
   {
      vtk::writePieceHeader( output, numberOfPoints2D, numberOfCells2D );
   }
   else
   {
      vtk::writePieceHeader( output, numberOfPoints3D, numberOfCells3D );
   }
   output << "<Points>\n";
75
   vtk::openDataElement( output, typeToString< real_t >(), "", 3, mgr.vtkDataFormat_ );
76
77
78
79
80
81
82
83

   VTKMeshWriter::writePointsForMicroEdges( mgr, output, storage, level, dofType );

   output << "\n</DataArray>\n";
   output << "</Points>\n";

   output << "<PointData>\n";

84
85
86
87
88
89
90
91
92
   for ( const auto& function : mgr.edgeDoFFunctions_.getFunctions< double >() )
   {
      writeScalarFunction( mgr, output, function, storage, level, dofType );
   }
   for ( const auto& function : mgr.edgeDoFFunctions_.getFunctions< int32_t >() )
   {
      writeScalarFunction( mgr, output, function, storage, level, dofType );
   }
   for ( const auto& function : mgr.edgeDoFFunctions_.getFunctions< int64_t >() )
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
   {
      writeScalarFunction( mgr, output, function, storage, level, dofType );
   }

   output << "</PointData>\n";

   if ( mgr.write2D_ )
   {
      VTKMeshWriter::writeCells2D( mgr, output, storage, levelinfo::num_microedges_per_edge( level ) );
   }
   else
   {
      if ( dofType == vtk::DoFType::EDGE_XYZ )
         VTKMeshWriter::writeCells3D( mgr, output, storage, levelinfo::num_microedges_per_edge( level ) - 1 );
      else
         VTKMeshWriter::writeCells3D( mgr, output, storage, levelinfo::num_microedges_per_edge( level ) );
   }

   vtk::writePieceFooter( output );
}

114
template < typename value_t >
115
116
void VTKEdgeDoFWriter::writeScalarFunction( const VTKOutput&                           mgr,
                                            std::ostream&                              output,
117
                                            const EdgeDoFFunction< value_t >&          function,
118
119
120
121
                                            const std::shared_ptr< PrimitiveStorage >& storage,
                                            uint_t                                     level,
                                            const vtk::DoFType&                        dofType )
{
122
123
124
   WALBERLA_ASSERT_EQUAL( storage, function.getStorage() );

   vtk::openDataElement( output, typeToString< value_t >(), function.getFunctionName(), 1, mgr.vtkDataFormat_ );
125
126
127
128
129

   WALBERLA_ASSERT( dofType == vtk::DoFType::EDGE_X || dofType == vtk::DoFType::EDGE_Y || dofType == vtk::DoFType::EDGE_Z ||
                    dofType == vtk::DoFType::EDGE_XY || dofType == vtk::DoFType::EDGE_XZ || dofType == vtk::DoFType::EDGE_YZ ||
                    dofType == vtk::DoFType::EDGE_XYZ );

130
   VTKOutput::VTKStreamWriter< value_t > streamWriter( mgr.vtkDataFormat_ );
131
132
133
134
135
136
137
138
139

   if ( mgr.write2D_ )
   {
      for ( const auto& it : storage->getFaces() )
      {
         const Face& face = *it.second;

         switch ( dofType )
         {
140
         case vtk::DoFType::EDGE_X: {
141
142
143
144
145
146
147
            for ( const auto& itIdx : edgedof::macroface::Iterator( level ) )
            {
               streamWriter << face.getData( function.getFaceDataID() )
                                   ->getPointer( level )[edgedof::macroface::horizontalIndex( level, itIdx.col(), itIdx.row() )];
            }
            break;
         }
148
         case vtk::DoFType::EDGE_Y: {
149
150
151
152
153
154
155
            for ( const auto& itIdx : edgedof::macroface::Iterator( level ) )
            {
               streamWriter << face.getData( function.getFaceDataID() )
                                   ->getPointer( level )[edgedof::macroface::verticalIndex( level, itIdx.col(), itIdx.row() )];
            }
            break;
         }
156
         case vtk::DoFType::EDGE_XY: {
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
            for ( const auto& itIdx : edgedof::macroface::Iterator( level ) )
            {
               streamWriter << face.getData( function.getFaceDataID() )
                                   ->getPointer( level )[edgedof::macroface::diagonalIndex( level, itIdx.col(), itIdx.row() )];
            }
            break;
         }
         default:
            WALBERLA_ABORT( "Bad DoF type in VTK output for edge DoFs" );
            break;
         }
      }
   }
   else
   {
      for ( const auto& it : storage->getCells() )
      {
         const Cell& cell     = *it.second;
         const auto  cellData = cell.getData( function.getCellDataID() )->getPointer( level );

         if ( dofType == vtk::DoFType::EDGE_XYZ )
         {
            for ( const auto& itIdx : edgedof::macrocell::IteratorXYZ( level ) )
            {
               streamWriter << cellData[edgedof::macrocell::xyzIndex( level, itIdx.x(), itIdx.y(), itIdx.z() )];
            }
         }
         else
         {
            for ( const auto& itIdx : edgedof::macrocell::Iterator( level ) )
            {
               uint_t idx;
               switch ( dofType )
               {
               case vtk::DoFType::EDGE_X:
                  idx = edgedof::macrocell::xIndex( level, itIdx.x(), itIdx.y(), itIdx.z() );
                  break;
               case vtk::DoFType::EDGE_Y:
                  idx = edgedof::macrocell::yIndex( level, itIdx.x(), itIdx.y(), itIdx.z() );
                  break;
               case vtk::DoFType::EDGE_Z:
                  idx = edgedof::macrocell::zIndex( level, itIdx.x(), itIdx.y(), itIdx.z() );
                  break;
               case vtk::DoFType::EDGE_XY:
                  idx = edgedof::macrocell::xyIndex( level, itIdx.x(), itIdx.y(), itIdx.z() );
                  break;
               case vtk::DoFType::EDGE_XZ:
                  idx = edgedof::macrocell::xzIndex( level, itIdx.x(), itIdx.y(), itIdx.z() );
                  break;
               case vtk::DoFType::EDGE_YZ:
                  idx = edgedof::macrocell::yzIndex( level, itIdx.x(), itIdx.y(), itIdx.z() );
                  break;
               default:
                  WALBERLA_ABORT( "[VTK] Invalid DoFType" );
                  break;
               }
               streamWriter << cellData[idx];
            }
         }
      }
   }

   streamWriter.toStream( output );
220
221

   output << "\n</DataArray>\n";
222
223
224
}

} // namespace hyteg