Dune-Fufem 2.11-git
Loading...
Searching...
No Matches
portablegreymap.hh
Go to the documentation of this file.
1// -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set ts=8 sw=4 et sts=4:
3
4// SPDX-FileCopyrightText: Copyright © DUNE-FUFEM Project contributors, see file AUTHORS.md
5// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
6
7#ifndef PORTABLEGREYMAP_HH
8#define PORTABLEGREYMAP_HH
9
10#include <fstream>
11#include <iostream>
12#include <string>
13#include <vector>
14#include <array>
15
17
18#include <dune/istl/bvector.hh>
19
20#include <dune/grid/yaspgrid.hh>
21
24
33{
34 public:
36
37 typedef GridType::Codim<0>::Geometry::LocalCoordinate LocalDomainType;
39
40 using DomainType = typename GridType::template Codim<0>::Geometry::GlobalCoordinate;
42
44
47
49
56
57 private:
58
59 unsigned int
60 width_,
61 height_;
62
63 DomainType::field_type
64 xDomainMin_,
65 xDomainMax_,
66 yDomainMin_,
67 yDomainMax_;
68
69 const RangeType
70 fRangeMin_,
71 fRangeMax_;
72
74
75 const ColorScheme colorscheme_;
76
77 Basis* basis_;
78 CoeffType coeffs_;
79 FunctionType* greyMapFunction_;
80 GridType* grid_;
81
82 using DomainFieldType = typename Dune::template FieldTraits<DomainType>::field_type;
83
84 template<class Function>
85 using RangeFieldTypeFor = typename Dune::template FieldTraits<std::decay_t<std::invoke_result_t<Function, DomainType>>>::field_type;
86
87 public:
98 PortableGreyMap(const DomainType::field_type xDomainMin, const DomainType::field_type xDomainMax,
99 const DomainType::field_type yDomainMin, const DomainType::field_type yDomainMax,
100 const RangeType fRangeMin=0, const RangeType fRangeMax=1,
101 const ColorScheme colorscheme=DEFAULT):
102 xDomainMin_(xDomainMin),
103 xDomainMax_(xDomainMax),
104 yDomainMin_(yDomainMin),
105 yDomainMax_(yDomainMax),
106 fRangeMin_(fRangeMin),
107 fRangeMax_(fRangeMax),
108 colorscheme_(colorscheme)
109 {
110 if (fRangeMax<=fRangeMin)
111 DUNE_THROW(Dune::RangeError, "Range of function values has inverse bounds or zero length.");
112 }
113
120 PortableGreyMap(const RangeType fRangeMin=0, const RangeType fRangeMax=1, const ColorScheme colorscheme=DEFAULT):
121 xDomainMin_(0),
122 xDomainMax_(0),
123 yDomainMin_(0),
124 yDomainMax_(0),
125 fRangeMin_(fRangeMin),
126 fRangeMax_(fRangeMax),
127 colorscheme_(colorscheme)
128 {
129 if (fRangeMax<=fRangeMin)
130 DUNE_THROW(Dune::RangeError, "Range of function values has inverse bounds or zero length.");
131 }
132
144 void readGreyMap(const char* filename, const int width=-1, const int height=-1, const int xoffset=0, const int yoffset=0)
145 {
146 std::string str;
147 std::string pgmID;
148 std::ifstream pgmfile;
149
150 pgmfile.open(filename);
151
152 // get rid of leading comment lines
153 do {
154 std::getline(pgmfile, pgmID);
155 } while (str[0] == 35); // ASCII(35) = #
156
157 if (pgmID[0]!=80) // ASCII(80) = P
158 DUNE_THROW(Dune::Exception,"File is not a PGM-File.");
159
160 int count = 0;
161 while (count < 3)
162 {
163 pgmfile >> std::skipws >> str;
164 if (str[0] == 35)
165 {
166 pgmfile.ignore(1024,10);
167 continue;
168 }
169 else
170 {
171 imgParams_.push_back(std::atoi(str.c_str()));
172 ++count;
173 }
174 }
175
176 int imgWidth = imgParams_[0],
177 imgHeight = imgParams_[1];
178 //maxGreyVal = imgParams_[2];
179
180 count = 0;
181
182
183 width_ = (width < 0) ? imgWidth : width;
184 height_ = (height < 0) ? imgHeight : height;
185
186 if(xDomainMax_-xDomainMin_ <= 0.0)
187 {
188 xDomainMin_ = 0;
189 xDomainMax_ = width_-1;
190
191 yDomainMin_ = 0;
192 yDomainMax_ = height_-1;
193 }
194
195 int value=0;
196
197 int p1 = ceil(log(width_ -1)/log(2)),
198 p2 = ceil(log(height_-1)/log(2));
199 unsigned int i = (p1-p2 >= 0)? p1-p2 : 0;
200 unsigned int j = (p1-p2 >= 0)? 0 : p2-p1;
201
204
205 L[0] = pow(2, p1);
206 L[1] = pow(2, p2);
207 s[0] = pow(2, i);
208 s[1] = pow(2, j);
209
210 grid_ = new GridType(L,s);
211 for (int k=0; k<std::min(p1,p2); ++k)
212 grid_->globalRefine(1);
213
214 basis_ = new Basis(grid_->leafGridView());
215 coeffs_.resize(basis_->size());
216 coeffs_ = 0.0;
217 greyMapFunction_ = new FunctionType(Dune::Functions::makeDiscreteGlobalBasisFunction<RangeType>(*basis_, coeffs_));
218
219 if (pgmID == "P2")
220 {
221 for (int k=0; k < yoffset*imgWidth+xoffset; ++k)
222 pgmfile >> std::skipws >> value;
223
224 for (i=0; i<height_; ++i)
225 {
226 for(j=0; j<width_; ++j)
227 {
228 pgmfile >> std::skipws >> value;
229
230 if (pgmfile.eof())
231 break;
232
233 coeffs_[(height_-1-i)*(L[0]+1)+j] = static_cast<double>(value);
234 }
235
236 for (unsigned int k=0; k < imgWidth-width_; ++k)
237 pgmfile >> std::skipws >> value;
238 }
239 }
240 else
241 DUNE_THROW(Dune::Exception,"File is not an ASCII PGM-File.");
242
243 }
244
264 template <typename FType>
265 static void exportGreyMap( const char* filename,
266 const FType& function,
267 RangeFieldTypeFor<FType> fRangeMin, RangeFieldTypeFor<FType> fRangeMax,
268 const DomainFieldType xDomainMin, const DomainFieldType xDomainMax,
269 const DomainFieldType yDomainMin, const DomainFieldType yDomainMax,
270 const unsigned int width, const unsigned int height,
271 const std::string info="",
272 const unsigned int maxGreyVal=255, const ColorScheme colorscheme=DEFAULT)
273 {
275 using RangeFieldType = RangeFieldTypeFor<FType>;
276
277 DomainFieldType xLength = xDomainMax - xDomainMin;
278 DomainFieldType yLength = yDomainMax - yDomainMin;
279
280 RangeFieldType rangeInterval = fRangeMax-fRangeMin;
281
282 if (xLength <= 0.0 or yLength <= 0.0 or rangeInterval <= 0.0)
283 DUNE_THROW(Dune::RangeError,"Domain has zero or negative extension or range interval has zero length or negative extension(thrown by PortableGreyMap::exportGreyMap.");
284
285 double tFactor = maxGreyVal/rangeInterval;
286
287 DomainType r(0.0);
288 RangeType fval(0.0);
289
290 std::ofstream pgmfile(filename, std::ios::trunc | std::ios::out);
291
292 // write preliminaries ("P2", some comment, height, width, maxGreyVal) to stream
293 pgmfile << "P2" << std::endl << "# file created by PortableGreyMap (dune-fufem)" << std::endl << "# " << info << std::endl << height << " " << width << std::endl << maxGreyVal << std::endl;
294
295 r[0] = xDomainMin;
296 r[1] = yDomainMax;
297
298 for (unsigned int j= 0; j<height; ++j)
299 {
300 r[0] = xDomainMin;
301 for (unsigned int i= 0; i<width; ++i)
302 {
303 fval = function(r);
304
305 // we transform the function value to the corresponding point in [0,maxGreyVal] and round to the next integer. According to the colorscheme (whether fRangeMin or fRangemax is white) we have to choose the greyvalue
306 int greyval = (colorscheme==DEFAULT ? std::floor((fval-fRangeMin)*tFactor+0.5) : maxGreyVal-std::floor((fval-fRangeMin)*tFactor+0.5) );
307
308 // greyval >> endl >> PGM
309 pgmfile << greyval << std::endl;
310 r[0] = xDomainMin + (i+1)*xLength/(width-1);
311 }
312 r[1] = yDomainMax - (j+1)*yLength/(height-1);
313 }
314
315 // close PGM (?)
316 pgmfile.close();
317 }
318
319 /* \brief evaluates interpolated greymap at global point
320 *
321 * The greymap is evaluated at point x of the domain \f$ \Omega \f$
322 * assuming a linear transformation \f$ \Omega \longrightarrow [0,width_]\times[0,height_]\f$. The returnvalue is scaled
323 * according to \f$[fRangeMin_,fRangeMax_]\f$.
324 *
325 * \param x point in \f$ \Omega \f$ at whicnh to evaluate
326 * \returns the function value
327 */
329 {
330 if (greyMapFunction_==0)
331 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
332
333 DomainType xx = x;
334
335 xx[0] = (x[0]-xDomainMin_)/(xDomainMax_-xDomainMin_)*(width_-1);
336 xx[1] = (x[1]-yDomainMin_)/(yDomainMax_-yDomainMin_)*(height_-1);
337 RangeType r = (*greyMapFunction_)(xx);
338
339 return fRangeMin_ + (colorscheme_==DEFAULT ? r/imgParams_[2] : (1-r/imgParams_[2]))*(fRangeMax_-fRangeMin_);
340 }
341
342 friend auto localFunction(const PortableGreyMap& pgm)
343 {
344 if (pgm.greyMapFunction_==0)
345 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
346 auto lf = localFunction(*(pgm.greyMapFunction_));
347 return [lf, &pgm](const auto& x) {
348 RangeType r = localGreyMapFunction(x);
349 return pgm.fRangeMin_ + (pgm.colorscheme_==DEFAULT ? r/pgm.imgParams_[2] : (1-r/pgm.imgParams_[2]))*(pgm.fRangeMax_-pgm.fRangeMin_);
350 };
351 }
352
353 const EntitySet& entitySet() const
354 {
355 if (greyMapFunction_==0)
356 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
357 return greyMapFunction_->entitySet();
358 }
359
360 /* \brief provides read access to the coefficients
361 */
362 const CoeffType& getCoeffs() const
363 {
364 if (greyMapFunction_==0)
365 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
366
367 return coeffs_;
368 }
369
370 /* \brief provides access to the grid on which the interpolated greymap lives
371 */
372 const GridType& getGrid() const
373 {
374 if (greyMapFunction_==0)
375 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
376
377 return *grid_;
378 }
379
380 /* \brief provides access to the width of the imported greymap section
381 */
382 unsigned int getWidth() const
383 {
384 if (greyMapFunction_==0)
385 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
386
387 return width_;
388 }
389
390 /* \brief provides access to the height of the imported greymap section
391 */
392 unsigned int getHeight() const
393 {
394 if (greyMapFunction_==0)
395 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
396
397 return height_;
398 }
399
400 /* \brief provides access to the width of the full (original) greymap image
401 */
402 unsigned int getImgWidth() const
403 {
404 if (greyMapFunction_==0)
405 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
406
407 return imgParams_[0];
408 }
409
410 /* \brief provides access to the height of the full (original) greymap image
411 */
412 unsigned int getImgHeight() const
413 {
414 if (greyMapFunction_==0)
415 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
416
417 return imgParams_[1];
418 }
419
420 /* \brief provides access to the used maximal value in the (original and imported) greymap corresponding to white
421 */
422 unsigned int getWhiteValue() const
423 {
424 if (greyMapFunction_==0)
425 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
426
427 return imgParams_[2];
428 }
429
431 {
432 if (grid_!=0)
433 delete grid_;
434 if (greyMapFunction_!=0)
435 delete greyMapFunction_;
436 if (basis_!=0)
437 delete basis_;
438 }
439};
440
441#endif
442
#define DUNE_THROW(E,...)
friend friend class Entity
GridViewEntitySet< GridView, 0 > EntitySet
Class wrapping a greymap (acquired from PGM ASCII (P2)-files) providing it as a piecewise bi-linear G...
Definition portablegreymap.hh:33
RangeType operator()(const DomainType &x) const
Definition portablegreymap.hh:328
const CoeffType & getCoeffs() const
Definition portablegreymap.hh:362
Dune::YaspGrid< 2 > GridType
Definition portablegreymap.hh:35
void readGreyMap(const char *filename, const int width=-1, const int height=-1, const int xoffset=0, const int yoffset=0)
reads the specified rectangular section of a greymap (PGM-ASCII)
Definition portablegreymap.hh:144
PortableGreyMap(const DomainType::field_type xDomainMin, const DomainType::field_type xDomainMax, const DomainType::field_type yDomainMin, const DomainType::field_type yDomainMax, const RangeType fRangeMin=0, const RangeType fRangeMax=1, const ColorScheme colorscheme=DEFAULT)
Constructor.
Definition portablegreymap.hh:98
Dune::FieldVector< double, 1 > RangeType
Definition portablegreymap.hh:41
PortableGreyMap(const RangeType fRangeMin=0, const RangeType fRangeMax=1, const ColorScheme colorscheme=DEFAULT)
Constructor.
Definition portablegreymap.hh:120
friend auto localFunction(const PortableGreyMap &pgm)
Definition portablegreymap.hh:342
typename Dune::Functions::LagrangeBasis< GridType::LeafGridView, 1 > Basis
Definition portablegreymap.hh:43
ColorScheme
Definition portablegreymap.hh:52
@ DEFAULT
Definition portablegreymap.hh:53
@ REVERSE
Definition portablegreymap.hh:54
unsigned int getImgWidth() const
Definition portablegreymap.hh:402
GridType::Codim< 0 >::Entity Element
Definition portablegreymap.hh:38
Dune::Functions::DiscreteGlobalBasisFunction< Basis, CoeffType, Dune::Functions::HierarchicNodeToRangeMap, RangeType > FunctionType
Definition portablegreymap.hh:46
unsigned int getWidth() const
Definition portablegreymap.hh:382
GridType::Codim< 0 >::Geometry::LocalCoordinate LocalDomainType
Definition portablegreymap.hh:37
const GridType & getGrid() const
Definition portablegreymap.hh:372
~PortableGreyMap()
Definition portablegreymap.hh:430
typename FunctionType::EntitySet EntitySet
Definition portablegreymap.hh:48
typename Dune::BlockVector< RangeType > CoeffType
Definition portablegreymap.hh:45
unsigned int getWhiteValue() const
Definition portablegreymap.hh:422
const EntitySet & entitySet() const
Definition portablegreymap.hh:353
static void exportGreyMap(const char *filename, const FType &function, RangeFieldTypeFor< FType > fRangeMin, RangeFieldTypeFor< FType > fRangeMax, const DomainFieldType xDomainMin, const DomainFieldType xDomainMax, const DomainFieldType yDomainMin, const DomainFieldType yDomainMax, const unsigned int width, const unsigned int height, const std::string info="", const unsigned int maxGreyVal=255, const ColorScheme colorscheme=DEFAULT)
creates a PGM (P2) file from a given scalar function
Definition portablegreymap.hh:265
typename GridType::template Codim< 0 >::Geometry::GlobalCoordinate DomainType
Definition portablegreymap.hh:40
unsigned int getHeight() const
Definition portablegreymap.hh:392
unsigned int getImgHeight() const
Definition portablegreymap.hh:412
T atoi(T... args)
T close(T... args)
T endl(T... args)
T eof(T... args)
T floor(T... args)
T getline(T... args)
T ignore(T... args)
T min(T... args)
T open(T... args)
T push_back(T... args)
T skipws(T... args)