1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3
4 #include <config.h>
5
6 #include <dune/grid/onedgrid/onedgridfactory.hh>
7 #include <dune/grid/onedgrid/onedgridindexsets.hh>
8
9 using namespace Dune;
10
11
12 Dune::GridFactory<Dune::OneDGrid >::
GridFactory()13 GridFactory() :
14 factoryOwnsGrid_(true),
15 vertexIndex_(0)
16 {
17 grid_ = new OneDGrid;
18
19 createBegin();
20 }
21
22 Dune::GridFactory<Dune::OneDGrid >::
GridFactory(OneDGrid * grid)23 GridFactory(OneDGrid* grid) :
24 factoryOwnsGrid_(false),
25 vertexIndex_(0)
26 {
27 grid_ = grid;
28
29 createBegin();
30 }
31
32 Dune::GridFactory<Dune::OneDGrid>::
~GridFactory()33 ~GridFactory()
34 {
35 if (grid_ && factoryOwnsGrid_)
36 delete grid_;
37 }
38
39 void Dune::GridFactory<Dune::OneDGrid>::
insertVertex(const Dune::FieldVector<GridFactory<OneDGrid>::ctype,1> & pos)40 insertVertex(const Dune::FieldVector<GridFactory<OneDGrid >::ctype,1>& pos)
41 {
42 vertexPositions_.insert(std::make_pair(pos, vertexIndex_++));
43 }
44
45 void Dune::GridFactory<Dune::OneDGrid>::
insertElement(const GeometryType & type,const std::vector<unsigned int> & vertices)46 insertElement(const GeometryType& type,
47 const std::vector<unsigned int>& vertices)
48 {
49 if (type.dim() != 1)
50 DUNE_THROW(GridError, "You cannot insert a " << type << " into a OneDGrid!");
51
52 if (vertices.size() != 2)
53 DUNE_THROW(GridError, "You cannot insert an element with " << vertices.size() << " vertices into a OneDGrid!");
54
55 elements_.push_back(std::array<unsigned int,2>());
56 elements_.back()[0] = vertices[0];
57 elements_.back()[1] = vertices[1];
58 }
59
60 void Dune::GridFactory<Dune::OneDGrid>::
insertBoundarySegment(const std::vector<unsigned int> & vertices)61 insertBoundarySegment(const std::vector<unsigned int>& vertices)
62 {
63 if (vertices.size() != 1)
64 DUNE_THROW(GridError, "OneDGrid BoundarySegments must have exactly one vertex.");
65
66 boundarySegments_.push_back(vertices[0]);
67 }
68
69 void Dune::GridFactory<Dune::OneDGrid>::
insertBoundarySegment(const std::vector<unsigned int> & vertices,const std::shared_ptr<BoundarySegment<1>> &)70 insertBoundarySegment(const std::vector<unsigned int>& vertices,
71 const std::shared_ptr<BoundarySegment<1> > & /* boundarySegment */)
72 {
73 insertBoundarySegment(vertices);
74 }
75
76 bool Dune::GridFactory<Dune::OneDGrid>::
wasInserted(const typename OneDGrid::LeafIntersection & intersection) const77 wasInserted(const typename OneDGrid::LeafIntersection& intersection) const
78 {
79 bool inserted(false);
80 const auto vtx(intersection.geometry().center()[0]);
81 for(const auto& idx : boundarySegments_)
82 if(std::abs(vertexPositionsByIndex_[idx]-vtx)<1.e-12)
83 {
84 inserted=true;
85 break;
86 }
87 return inserted;
88 }
89
90 unsigned int Dune::GridFactory<Dune::OneDGrid>::
insertionIndex(const typename OneDGrid::LeafIntersection & intersection) const91 insertionIndex(const typename OneDGrid::LeafIntersection& intersection) const
92 {
93 unsigned int insertionIdx(0);
94 const auto vtx(intersection.geometry().center()[0]);
95 for(const auto& idx : boundarySegments_)
96 if(std::abs(vertexPositionsByIndex_[idx]-vtx)<1.e-12)
97 break;
98 else
99 ++insertionIdx;
100 return insertionIdx;
101 }
102
103 std::unique_ptr<OneDGrid> Dune::GridFactory<Dune::OneDGrid>::
createGrid()104 createGrid()
105 {
106 // Prevent a crash when this method is called twice in a row
107 // You never know who may do this...
108 if (grid_==nullptr)
109 return nullptr;
110
111 // Assert that vertices are given
112 assert (vertexPositions_.size() > 0);
113
114 // Insert the vertices into the grid
115 grid_->entityImps_.resize(1);
116 for (const auto& vtx : vertexPositions_)
117 {
118 OneDEntityImp<0> newVertex(0, vtx.first, grid_->getNextFreeId());
119
120 newVertex.leafIndex_ = vtx.second;
121 newVertex.levelIndex_ = vtx.second;
122
123 grid_->vertices(0).push_back(newVertex);
124 }
125
126 // Fill the vector with the vertex positions accessible by index
127 vertexPositionsByIndex_.resize(vertexPositions_.size());
128 for (const auto& vtx : vertexPositions_)
129 vertexPositionsByIndex_[vtx.second] = vtx.first;
130
131 // Set the numbering of the boundary segments
132 if (boundarySegments_.size() > 2)
133 DUNE_THROW(GridError, "You cannot provide more than two boundary segments to a OneDGrid (it must be connected).");
134
135 if (boundarySegments_.size() > 1
136 && vertexPositionsByIndex_[boundarySegments_[0]] > vertexPositions_.begin()->first[0])
137 grid_->reversedBoundarySegmentNumbering_ = true;
138
139 // ///////////////////////////////////////////////////////////////////
140 // Insert the elements into the grid
141 //
142 // This is a 1d grid and it has to be connected. Hence we actually
143 // know where the elements are, even without being told explicitly.
144 // The only thing of interest are the indices.
145 // ///////////////////////////////////////////////////////////////////
146
147 // First sort elements by increasing position. That is how they are expected in the grid data structure
148 std::map<ctype, std::pair<std::array<unsigned int, 2>, unsigned int> > elementsByPosition;
149 for (std::size_t i=0; i<elements_.size(); i++)
150 elementsByPosition.insert(std::make_pair(vertexPositionsByIndex_[elements_[i][0]], // order by position of left vertex
151 std::make_pair(elements_[i], i) // the element and its position in the insertion sequence
152 ));
153
154 auto it = std::get<0>(grid_->entityImps_[0]).begin();
155 auto eIt = elementsByPosition.begin();
156
157 // Looping over the vertices to get all elements assumes that the grid is connected
158 for (size_t i=0; i<vertexPositions_.size()-1; i++, ++eIt)
159 {
160 OneDEntityImp<1> newElement(0, grid_->getNextFreeId(), grid_->reversedBoundarySegmentNumbering_);
161 newElement.vertex_[0] = it;
162 it = it->succ_;
163 newElement.vertex_[1] = it;
164
165 newElement.levelIndex_ = eIt->second.second;
166 newElement.leafIndex_ = eIt->second.second;
167
168 grid_->elements(0).push_back(newElement);
169 }
170
171 // Create the index sets
172 grid_->levelIndexSets_.resize(1);
173 grid_->levelIndexSets_[0] = new OneDGridLevelIndexSet<const OneDGrid>(*grid_, 0);
174 grid_->levelIndexSets_[0]->setSizesAndTypes(vertexPositions_.size(), elements_.size());
175
176 grid_->leafIndexSet_.setSizesAndTypes(vertexPositions_.size(), elements_.size());
177
178 // Hand over the grid and delete the member pointer
179 auto tmp = grid_;
180 grid_ = nullptr;
181 return std::unique_ptr<OneDGrid>(tmp);
182 }
183
184 void Dune::GridFactory<Dune::OneDGrid >::
createBegin()185 createBegin()
186 {
187 vertexPositions_.clear();
188 }
189