13#ifndef AMIRAMESHREADER_HH
14#define AMIRAMESHREADER_HH
27#include <boost/timer/timer.hpp>
28#include <boost/lexical_cast.hpp>
30#include <dune/common/fvector.hh>
32#include <amiramesh/AmiraMesh.h>
39template <>
class std::complex<float>;
52 namespace AmiraMeshReader
54 namespace ImplementationDetails
56 std::string
exceptionMessage(std::string
const& function, std::string
const& gridfile,
int line)
58 return std::string(
"In AmiraMeshReader::") + function +
", line " + boost::lexical_cast<std::string>(line) +
": Error reading " + gridfile +
"\n";
63 return std::string(
"In AmiraMeshReader::") + function +
", line " + boost::lexical_cast<std::string>(line) + std::string(
": Error reading ") +
component +
" of " + location +
"\n";
67 template <
class Source,
class value_type,
int components>
74 std::cout << n <<
" entries...\n";
81 for (
size_t i=0; i<n; ++i)
82 for (
int j=0; j<components; ++j)
83 data[i][j] =
static_cast<value_type
>(source[i*components+j]);
86 template <
class value_type,
int components>
87 bool readData(AmiraMesh& am,
char const* location,
char const* name,
92 std::cout <<
"Looking for " << name <<
" at " << location <<
" with " << components <<
" components\n";
95 for (
int i=0; i<am.dataList.size(); ++i)
97 auto const& data = *am.dataList[i];
98 if ( components==data.dim()
99 && std::strcmp(name, data.name())==0
100 && std::strcmp(location,data.location()->name())==0 )
103 size_t const n = data.location()->nNodes();
107 if (data.primType()==MC_FLOAT)
108 extractData(n,
static_cast<float const*
>(data.dataPtr()),out);
109 else if (data.primType()==MC_DOUBLE)
110 extractData(n,
static_cast<double const*
>(data.dataPtr()),out);
111 else if (data.primType()==MC_UINT8)
112 extractData(n,
static_cast<std::uint8_t const*
>(data.dataPtr()),out);
113 else if (data.primType()==MC_INT16)
114 extractData(n,
static_cast<std::int16_t const*
>(data.dataPtr()),out);
115 else if (data.primType()==MC_UINT16)
116 extractData(n,
static_cast<std::uint16_t const*
>(data.dataPtr()),out);
117 else if (data.primType()==MC_INT32)
118 extractData(n,
static_cast<std::int32_t const*
>(data.dataPtr()),out);
128 std::cout <<
"Did not find specified data.\n";
129 for (
int i=0; i<am.dataList.size(); ++i)
131 auto const& data = *am.dataList[i];
133 std::cout <<
"data " << data.name() <<
" at " << data.location()->name()
134 <<
" with " << data.dim() <<
" components of type " << (int)data.primType() <<
"\n";
145 ifstream infile(gridFile);
147 while(getline(infile, line)) {
148 istringstream iss(line);
150 if((iss >> firstWord) && (firstWord ==
"BoundaryTriangleData")) {
151 string bracket, type;
152 if(iss >> bracket >> type) {
153 if(type ==
"byte")
return true;
154 if(type ==
"int")
return false;
156 throw Kaskade::LookupException(
"Wrong data type for BoundaryTriangleData. Has to be either byte or int.",__FILE__,__LINE__);
162 template <
class Scalar,
class Gr
id,
class ScalarEd>
165 int const dim = Grid::dimension;
166 std::vector<Dune::FieldVector<unsigned int, 2>> edges;
167 std::vector<Dune::FieldVector<Scalar, dim>> edgePos;
180 edgeDisplacement.resize(edges.size());
182 std::vector<std::pair<std::array<unsigned int, 2>,
184 for (
int i=0; i<edges.size(); ++i)
186 edgeTable[i].first[0] = edges[i][0]-1;
187 edgeTable[i].first[1] = edges[i][1]-1;
188 if(edgeTable[i].first[0] > edgeTable[i].first[1]) std::swap(edgeTable[i].first[0], edgeTable[i].first[1]);
190 edgeTable[i].second = edgePos[i];
192 std::sort(edgeTable.begin(), edgeTable.end(), [](
auto const& a,
auto const& b) {return a.first < b.first;});
194 std::vector<bool> edgeRead(grid.size(dim-1),
false);
196 for (
auto const& element : elements(grid.leafGridView()))
198 auto const& refElement = Dune::ReferenceElements<double, dim>::general(element.type());
199 for (
int j=0; j<refElement.size(dim-1); j++)
201 size_t edgeIndex = grid.leafGridView().indexSet().subIndex(element,j,dim-1);
202 if (!edgeRead[edgeIndex])
204 auto c0 = element.template subEntity<dim>(refElement.subEntity(j, dim-1, 0, dim));
205 auto c1 = element.template subEntity<dim>(refElement.subEntity(j, dim-1, 1, dim));
207 std::array<unsigned int, 2> wantedEdge { factory.insertionIndex(c0),
208 factory.insertionIndex(c1) };
209 if(wantedEdge[0] > wantedEdge[1])
210 std::swap(wantedEdge[0], wantedEdge[1]);
212 auto edge = std::lower_bound(edgeTable.begin(), edgeTable.end(), wantedEdge,
213 [] (
auto const& a,
auto const& b) { return a.first < b;});
215 if (edge == edgeTable.end() || edge->first != wantedEdge)
220 auto edgePosition = c0.geometry().corner(0);
221 edgePosition += c1.geometry().corner(0);
224 edgeDisplacement[edgeIndex] = edge->second;
225 edgeDisplacement[edgeIndex] -= edgePosition;
227 edgeRead[edgeIndex] =
true;
260 template<
class Gr
id,
class Scalar,
class ScalarEd = Scalar>
261 std::unique_ptr<Grid>
readGrid(std::string
const& gridfile,
int initialGridSize = 0,
262 std::vector<int>* boundaryIds =
nullptr,
268 auto identity = [] (
auto x) {
return x;};
269 return readGrid<Grid,Scalar>(gridfile,identity,initialGridSize,boundaryIds,edgeDisplacement,scale);
295 template<
class Gr
id,
class Scalar,
class ScalarEd = Scalar,
class Deformation>
296 std::unique_ptr<Grid>
readGrid(std::string
const& gridfile,
297 Deformation
const& deformation,
298 int initialGridSize = 0,
299 std::vector<int>* boundaryIds =
nullptr,
303 int const dim = Grid::dimension;
304 std::vector<Dune::FieldVector<Scalar,dim>> vertices;
305 std::vector<Dune::FieldVector<int,dim+1>> cells;
306 std::vector<Dune::FieldVector<int,dim>> boundary;
309 std::cout <<
"Opening " << gridfile <<
" ...\n";
310 std::unique_ptr<AmiraMesh> am(AmiraMesh::read(gridfile.c_str()));
319 std::string cellName;
320 if(dim == 2) cellName =
"Triangles";
321 if(dim == 3) cellName =
"Tetrahedra";
322 if(dim != 2 && dim != 3)
323 throw std::runtime_error(
"Sorry!\nOnly 2D and 3D grids are supported.");
330 if (boundaryIds && !boundaryExists)
333 std::vector<Dune::FieldVector<int,1>> boundaryID;
338 std::vector<Dune::FieldVector<unsigned char,1>> boundaryIDchar;
342 std::transform(begin(boundaryIDchar),end(boundaryIDchar),back_inserter(boundaryID),
350 throw Kaskade::LookupException(
"No boundary triangle ids found in AmiraMesh file [neither of type char nor int].",__FILE__,__LINE__);
354 if (
auto* unitLength = am->parameters.find(
"UnitLength"))
356 scale = unitLength->getReal();
357 std::cout <<
"Found unit length of " << scale <<
"m.\n";
364 for (
size_t i=0; i<cells.size(); ++i)
366 for (
int j=0; j<dim+1; ++j)
369 if (cells[i][j]>=vertices.size())
371 std::string message = std::string(
"In ") + __FILE__ +
" line " + boost::lexical_cast<std::string>(__LINE__) +
": cell node " + boost::lexical_cast<std::string>(i) +
"[" + boost::lexical_cast<std::string>(j) +
"]=" + boost::lexical_cast<std::string>(cells[i][j]) +
" exceeds vertex numbers!\n";
372 throw std::runtime_error(message);
379 for (
size_t i=0; i<boundary.size(); ++i)
380 for (
int j=0; j<dim; ++j)
386 Dune::GridFactory<Grid> factory = IOTools::FactoryGenerator<Grid>::createFactory(initialGridSize);
387 std::cout <<
"inserting vertices...";
388 for (
size_t i=0; i<vertices.size(); ++i)
391 for(
int j=0; j<dim; ++j)
392 pos[j] = scale*(
double)vertices[i][j];
393 factory.insertVertex(deformation(pos));
395 std::cout <<
"done. ";
397 if (boundaryExists && boundaryIds)
399 std::cout <<
"inserting boundary segments...";
400 for(
size_t i=0; i<boundary.size(); ++i){
401 std::vector<unsigned int> tmp(dim);
402 for(
size_t j=0; j<dim; ++j){
403 assert(boundary[i][j]>=0 && boundary[i][j]<vertices.size());
404 tmp[j] = boundary[i][j];
406 factory.insertBoundarySegment(tmp);
408 std::cout <<
"done. ";
411 std::cout <<
"inserting elements...";
412 for (
size_t i=0; i<cells.size(); ++i) {
413 std::vector<unsigned int> tmp(dim+1);
414 for (
int j=0; j<dim+1; ++j) {
415 assert(cells[i][j]>=0 && cells[i][j]<vertices.size());
416 tmp[j] = cells[i][j];
418 factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex,dim),tmp);
420 std::cout <<
"done. " << std::endl;
422 boost::timer::cpu_timer timer;
423 std::unique_ptr<Grid> grid(factory.createGrid());
424 std::cout <<
"grid creation finished in " << boost::timer::format(timer.elapsed()) << std::endl;
428 std::cout <<
"sorting boundary ids...";
429 IOTools::BoundarySegmentIndexWrapper<Grid>::readBoundarySegmentIndices(*grid, factory, vertices, boundary, boundaryID, *boundaryIds);
430 std::cout <<
"done." << std::endl;
433 if (edgeDisplacement)
434 ImplementationDetails::readEdgePositions<Scalar>(*grid, factory, *am, *edgeDisplacement);
466 template<
class Gr
id,
class Scalar,
class ScalarEd = Scalar>
467 std::unique_ptr<Grid>
mergeGrids(std::string
const& gridfile1, std::string
const& gridfile2,
468 int initialGridSize = 0,
469 std::vector<int>* boundaryIds =
nullptr,
471 double scale1 = 1.0,
double scale2 = 1.0)
473 int const dim = Grid::dimension;
474 std::vector<Dune::FieldVector<Scalar,dim>> vertices1, vertices2;
475 std::vector<Dune::FieldVector<int,dim+1>> cells1, cells2;
476 std::vector<Dune::FieldVector<int,dim>> boundary1, boundary2;
479 std::cout <<
"Reading first amira mesh\n";
480 std::cout <<
"opening " << gridfile1 <<
'\n';
481 std::unique_ptr<AmiraMesh> am1(AmiraMesh::read(gridfile1.c_str()));
484 std::cout <<
"Reading second amira mesh\n";
485 std::cout <<
"opening " << gridfile2 <<
'\n';
486 std::unique_ptr<AmiraMesh> am2(AmiraMesh::read(gridfile2.c_str()));
499 std::string cellName;
500 if(dim == 2) cellName =
"Triangles";
501 if(dim == 3) cellName =
"Tetrahedra";
502 if(dim != 2 && dim != 3)
503 throw std::runtime_error(
"Sorry!\nOnly 2D and 3D grids are supported.");
513 if(boundaryIds && !boundaryExists1)
516 if(boundaryIds && !boundaryExists2)
540 if (
auto* unitLength = am1->parameters.find(
"UnitLength"))
542 scale1 = unitLength->getReal();
543 std::cout <<
"Found unit length of " << scale1 <<
"m in first Amira file.\n";
547 if (
auto* unitLength = am2->parameters.find(
"UnitLength"))
549 scale2 = unitLength->getReal();
550 std::cout <<
"Found unit length of " << scale2 <<
"m in second Amira file.\n";
557 for (
size_t i=0; i<cells1.size(); ++i)
559 for (
int j=0; j<dim+1; ++j)
562 if (cells1[i][j]>=vertices1.size())
564 std::string message = std::string(
"In ") + __FILE__ +
" line " + boost::lexical_cast<std::string>(__LINE__) +
": cell node " + boost::lexical_cast<std::string>(i) +
"[" + boost::lexical_cast<std::string>(j) +
"]=" + boost::lexical_cast<std::string>(cells1[i][j]) +
" exceeds vertex numbers!\n";
565 throw std::runtime_error(message);
569 for (
size_t i=0; i<cells2.size(); ++i)
571 for (
int j=0; j<dim+1; ++j)
574 if (cells2[i][j]>=vertices2.size())
576 std::string message = std::string(
"In ") + __FILE__ +
" line " + boost::lexical_cast<std::string>(__LINE__) +
": cell node " + boost::lexical_cast<std::string>(i) +
"[" + boost::lexical_cast<std::string>(j) +
"]=" + boost::lexical_cast<std::string>(cells2[i][j]) +
" exceeds vertex numbers!\n";
577 throw std::runtime_error(message);
591 std::cout << std::endl;
592 std::cout <<
"preparing grid creation\n";
594 Dune::GridFactory<Grid> factory = IOTools::FactoryGenerator<Grid>::createFactory(initialGridSize);
595 std::cout <<
"inserting vertices of first mesh...";
596 for (
size_t i=0; i<vertices1.size(); ++i)
599 for(
int j=0; j<dim; ++j)
600 pos[j] = scale1*(
double)vertices1[i][j];
601 factory.insertVertex(pos);
603 std::cout <<
"done.\n";
604 std::cout <<
"inserting vertices of second mesh...";
605 for (
size_t i=0; i<vertices2.size(); ++i)
608 for(
int j=0; j<dim; ++j)
609 pos[j] = scale2*(
double)vertices2[i][j];
610 factory.insertVertex(pos);
612 std::cout <<
"done." << std::endl;
628 std::cout <<
"inserting elements of first mesh...";
629 for (
size_t i=0; i<cells1.size(); ++i) {
630 std::vector<unsigned int> tmp(dim+1);
631 for (
int j=0; j<dim+1; ++j) {
632 assert(cells1[i][j]>=0 && cells1[i][j]<vertices1.size());
633 tmp[j] = cells1[i][j];
635 factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex,dim),tmp);
637 std::cout <<
"done.\n";
638 std::cout <<
"inserting elements of second mesh...";
639 for (
size_t i=0; i<cells2.size(); ++i) {
640 std::vector<unsigned int> tmp(dim+1);
641 for (
int j=0; j<dim+1; ++j) {
642 assert(cells2[i][j]>=0 && cells2[i][j]<vertices2.size());
643 tmp[j] = cells2[i][j] + vertices1.size();
645 factory.insertElement(Dune::GeometryType(Dune::GeometryType::simplex,dim),tmp);
647 std::cout <<
"done." << std::endl;
649 boost::timer::cpu_timer timer;
650 std::unique_ptr<Grid> grid(factory.createGrid());
651 std::cout <<
"grid creation finished in " << boost::timer::format(timer.elapsed()) << std::endl;
677 template<
class DataType,
class FunctionSpaceElement>
678 void readData(std::string
const& datafile, std::string
const& dataname, std::string
const& componentname,
681 constexpr int numberOfComponents = FunctionSpaceElement::StorageValueType::dimension;
686 std::vector<Dune::FieldVector<DataType, numberOfComponents>> dataVector;
689 std::cout <<
"Reading additional data." << std::endl;
690 std::cout <<
"Opening " << datafile <<
" ...\n";
691 std::unique_ptr<AmiraMesh> am(AmiraMesh::read(datafile.c_str()));
694 throw FileIOException(
"could not open Amira mesh file for reading",datafile,__FILE__,__LINE__);
699 throw LookupException(
"data " + componentname +
" not found at location " + dataname +
" in Amira mesh file " + datafile,
704 std::cout <<
"number of entries: " << dataVector.size() << std::endl;
705 std::cout <<
"number of components: " << numberOfComponents << std::endl;
710 for(
size_t i=0; i<dataVector.size(); ++i)
711 for(
size_t j=0; j<numberOfComponents; ++j)
726 template<
class Scalar,
int numberOfComponents>
727 void readData(std::string
const& datafile, std::string
const& dataname, std::string
const& componentname,
731 std::cout << std::endl;
732 std::cout <<
"Reading additional vertex data" << std::endl;
733 std::cout <<
"opening " << datafile << std::endl;
734 AmiraMesh* am = AmiraMesh::read(datafile.c_str());
736 throw std::runtime_error(
ImplementationDetails::exceptionMessage(
"readData(std::string const&, std::string const&, std::string const&, std::vector<Dune::FieldVector>&)", datafile, __LINE__));
742 throw std::runtime_error(
ImplementationDetails::exceptionMessage(
"readData(std::string const&, std::string const&, std::string const&, std::vector<Dune::FieldVector>&)", dataname, componentname, __LINE__));
760 template <
class VarSetDesc>
762 typename VarSetDesc::VariableSet& data){
764 int const numberOfComponents = result_of::at_c<typename VarSetDesc::VariableSet::Functions, 0>::type::Components;
765 typedef std::vector<Dune::FieldVector<float,numberOfComponents> > DataVector;
766 std::vector<Dune::FieldVector<float,numberOfComponents> > vertices;
770 std::cout <<
"Reading undeformed geometry\n";
771 std::cout <<
"opening " << gridfile <<
'\n';
772 AmiraMesh* am = AmiraMesh::read(gridfile.c_str());
773 if(!am)
throw std::runtime_error(
ImplementationDetails::exceptionMessage(
"readDeformationIntoVariableSetRepresentation(std::string const&, std::string const&, VariableSet::VariableSet&)", gridfile, __LINE__));
779 throw std::runtime_error(
ImplementationDetails::exceptionMessage(
"readDeformationIntoVariableSetRepresentation(std::string const&, std::string const&, VariableSet::VariableSet&)",
"Nodes",
"Coordinates",__LINE__));
786 std::cout << std::endl;
787 std::cout <<
"Reading deformed geometry" << std::endl;
788 std::cout <<
"opening " << datafile << std::endl;
789 am = AmiraMesh::read(datafile.c_str());
790 if(!am)
throw std::runtime_error(
ImplementationDetails::exceptionMessage(
"readDeformationIntoVariableSetRepresentation(std::string const&, std::string const&, VariableSet::VariableSet&)", datafile, __LINE__));
795 throw std::runtime_error(
"readDeformationIntoVariableSetRepresentation(std::string const&, std::string const&, VariableSet::VariableSet&)",
"Nodes",
"Coordinates", __LINE__);
802 assert(nodeData.size()==vertices.size());
805 for(
size_t i=0; i<nodeData.size(); ++i)
806 nodeData[i]=nodeData[i]-vertices[i];
809 std::vector<double> tmpVec(nodeData.size()*numberOfComponents);
810 for(
size_t i=0; i<nodeData.size(); ++i)
811 for(
size_t j=0; j<numberOfComponents; ++j)
812 tmpVec[numberOfComponents*i+j] = (
double)nodeData[i][j];
814 data.read(tmpVec.begin());
828 template<
class FunctionSpaceElement,
class FileScalar=
float>
830 int const numberOfComponents = FunctionSpaceElement::Components;
831 typedef std::vector<Dune::FieldVector<FileScalar,numberOfComponents> > DataVector;
833 std::vector<Dune::FieldVector<FileScalar,numberOfComponents> > vertices;
837 std::cout <<
"Reading undeformed geometry\n";
838 std::cout <<
"opening " << gridfile <<
'\n';
839 AmiraMesh* am = AmiraMesh::read(gridfile.c_str());
853 std::cout << std::endl;
854 std::cout <<
"Reading deformed geometry" << std::endl;
855 std::cout <<
"opening " << datafile << std::endl;
856 am = AmiraMesh::read(datafile.c_str());
869 assert(nodeData.size()==vertices.size());
872 for(
size_t i=0; i<nodeData.size(); ++i)
873 nodeData[i]=nodeData[i]-vertices[i];
876 std::vector<Scalar> tmpVec(nodeData.size()*numberOfComponents);
877 for(
size_t i=0; i<nodeData.size(); ++i)
878 for(
size_t j=0; j<FunctionSpaceElement::Components; ++j)
883 template<
class Gr
idView,
class FunctionSpaceElement,
class FileScalar=
float>
885 int const numberOfComponents = FunctionSpaceElement::Components;
886 typedef std::vector<Dune::FieldVector<FileScalar,numberOfComponents> > DataVector;
888 std::vector<Dune::FieldVector<FileScalar,numberOfComponents> > vertices;
892 std::cout <<
"Reading deformed geometry" << std::endl;
893 std::cout <<
"opening " << datafile << std::endl;
894 AmiraMesh *am = AmiraMesh::read(datafile.c_str());
907 assert(nodeData.size()==vertices.size());
910 auto vIter = gridView.template begin<GridView::dimension>();
911 auto vend = gridView.template end<GridView::dimension>();
913 for(;vIter!=vend;++vIter)
915 nodeData[i] -= vIter->geometry().corner(0);
922 std::vector<Scalar> tmpVec(nodeData.size()*numberOfComponents);
923 for(
size_t i=0; i<nodeData.size(); ++i)
924 for(
size_t j=0; j<FunctionSpaceElement::Components; ++j)
935 template <
class Gr
id>
938 int const dim = Grid::dimension;
940 typedef typename Grid::LeafGridView LeafView;
941 std::vector<int> boundaryIndices;
942 std::unique_ptr<Grid> grid = readGrid<Grid,float>(gridfile, boundaryIndices);
947 Space space(gridManager, gridManager.
grid().leafGridView(), 1);
948 typedef boost::fusion::vector<Space const*> Spaces;
949 Spaces spaces(&space);
950 typedef boost::fusion::vector< VariableDescription<0,1,0> > VariableDescriptions;
952 std::string name[1] = {
"boundary ids" };
953 VarSetDesc varSetDesc(spaces, name);
954 typename VarSetDesc::VariableSet indices(varSetDesc);
957 std::vector<Dune::FieldVector<int,dim> > boundaryVertices;
959 std::string
const comp_name(
"BoundaryTriangles");
960 std::string
const node_name(
"Nodes");
962 ImplementationDetails::readData<int,dim>(gridfile, comp_name, node_name, boundaryVertices);
963 std::vector<double> tmp(gridManager.
grid().size(dim),0);
964 for(
int i=0; i<boundaryIndices.size(); ++i){
965 tmp[boundaryVertices[i][0]-1] = boundaryIndices[i];
966 tmp[boundaryVertices[i][1]-1] = boundaryIndices[i];
967 tmp[boundaryVertices[i][2]-1] = boundaryIndices[i];
969 indices.read(tmp.begin());
974 writeVTKFile(gridManager.
grid().leafGridView(), varSetDesc, indices, savefilename,options);
A wrapper class for conveniently providing exceptions with context information.
A representation of a finite element function space defined over a domain covered by a grid.
An exception class for file IO errors.
A class for representing finite element functions.
StorageType const & coefficients() const
Provides read-only access to the coefficients of the finite element basis functions.
Space::Scalar Scalar
scalar field type
Grid const & grid() const
Returns a const reference on the owned grid.
An exception that can be thrown whenever a key lookup fails.
A class that stores information about a set of variables.
Lagrange Finite Elements.
bool boundaryIdByByte(std::string const &gridFile)
std::string exceptionMessage(std::string const &function, std::string const &gridfile, int line)
bool readData(AmiraMesh &am, char const *location, char const *name, std::vector< Dune::FieldVector< value_type, components > > &out, bool verbose=false)
void extractData(size_t const n, Source const *source, std::vector< Dune::FieldVector< value_type, components > > &data, bool verbose=false)
void readEdgePositions(Grid const &grid, Dune::GridFactory< Grid > const &factory, AmiraMesh &am, std::vector< Dune::FieldVector< ScalarEd, Grid::dimension > > &edgeDisplacement)
std::unique_ptr< Grid > readGrid(std::string const &gridfile, int initialGridSize=0, std::vector< int > *boundaryIds=nullptr, std::vector< Dune::FieldVector< ScalarEd, Grid::dimension > > *edgeDisplacement=nullptr, double scale=1.0)
function reading an Amira mesh file in ASCII format.
void readDeformation(std::string const &gridfile, std::string const &datafile, FunctionSpaceElement &data)
function reading return a fe-function describing the deformation.
void boundaryConditionsToScalarField(std::string const &gridfile, std::string const &savefilename=std::string("boundaryConditions"), int initialGridSize=0)
Read boundary indices and save as scalar field in .vtu-file.
std::unique_ptr< Grid > mergeGrids(std::string const &gridfile1, std::string const &gridfile2, int initialGridSize=0, std::vector< int > *boundaryIds=nullptr, double scale1=1.0, double scale2=1.0)
function joining two Amira mesh files in ASCII format into one grid.
void readData(std::string const &datafile, std::string const &dataname, std::string const &componentname, FunctionSpaceElement &data, bool verbose=false)
function reading additional data from an Amira mesh file in ASCII format.
void readDeformationIntoVariableSetRepresentation(std::string const &gridfile, std::string const &datafile, typename VarSetDesc::VariableSet &data)
function reading return a FE-function describing the deformation.
void readDeformation2(GridView const &gridView, std::string const &datafile, FunctionSpaceElement &data)
auto & component(LinearProductSpace< Scalar, Sequence > &x)
options for VTK/AMIRA output
Output of mesh and solution for visualization software.