Dune-Fufem 2.11
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
54 REVERSE
55 };
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=RangeType(0), const RangeType fRangeMax=RangeType(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, const RangeType fRangeMax, 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
139 PortableGreyMap(const double fRangeMin=0, const double fRangeMax=1, const ColorScheme colorscheme=DEFAULT):
140 xDomainMin_(0),
141 xDomainMax_(0),
142 yDomainMin_(0),
143 yDomainMax_(0),
144 fRangeMin_(fRangeMin),
145 fRangeMax_(fRangeMax),
146 colorscheme_(colorscheme)
147 {
148 if (fRangeMax<=fRangeMin)
149 DUNE_THROW(Dune::RangeError, "Range of function values has inverse bounds or zero length.");
150 }
151
163 void readGreyMap(const char* filename, const int width=-1, const int height=-1, const int xoffset=0, const int yoffset=0)
164 {
165 std::string str;
166 std::string pgmID;
167 std::ifstream pgmfile;
168
169 pgmfile.open(filename);
170
171 // get rid of leading comment lines
172 do {
173 std::getline(pgmfile, pgmID);
174 } while (str[0] == 35); // ASCII(35) = #
175
176 if (pgmID[0]!=80) // ASCII(80) = P
177 DUNE_THROW(Dune::Exception,"File is not a PGM-File.");
178
179 int count = 0;
180 while (count < 3)
181 {
182 pgmfile >> std::skipws >> str;
183 if (str[0] == 35)
184 {
185 pgmfile.ignore(1024,10);
186 continue;
187 }
188 else
189 {
190 imgParams_.push_back(std::atoi(str.c_str()));
191 ++count;
192 }
193 }
194
195 int imgWidth = imgParams_[0],
196 imgHeight = imgParams_[1];
197 //maxGreyVal = imgParams_[2];
198
199 count = 0;
200
201
202 width_ = (width < 0) ? imgWidth : width;
203 height_ = (height < 0) ? imgHeight : height;
204
205 if(xDomainMax_-xDomainMin_ <= 0.0)
206 {
207 xDomainMin_ = 0;
208 xDomainMax_ = width_-1;
209
210 yDomainMin_ = 0;
211 yDomainMax_ = height_-1;
212 }
213
214 int value=0;
215
216 int p1 = ceil(log(width_ -1)/log(2)),
217 p2 = ceil(log(height_-1)/log(2));
218 unsigned int i = (p1-p2 >= 0)? p1-p2 : 0;
219 unsigned int j = (p1-p2 >= 0)? 0 : p2-p1;
220
223
224 L[0] = pow(2, p1);
225 L[1] = pow(2, p2);
226 s[0] = pow(2, i);
227 s[1] = pow(2, j);
228
229 grid_ = new GridType(L,s);
230 for (int k=0; k<std::min(p1,p2); ++k)
231 grid_->globalRefine(1);
232
233 basis_ = new Basis(grid_->leafGridView());
234 coeffs_.resize(basis_->size());
235 coeffs_ = 0.0;
236 greyMapFunction_ = new FunctionType(Dune::Functions::makeDiscreteGlobalBasisFunction<RangeType>(*basis_, coeffs_));
237
238 if (pgmID == "P2")
239 {
240 for (int k=0; k < yoffset*imgWidth+xoffset; ++k)
241 pgmfile >> std::skipws >> value;
242
243 for (i=0; i<height_; ++i)
244 {
245 for(j=0; j<width_; ++j)
246 {
247 pgmfile >> std::skipws >> value;
248
249 if (pgmfile.eof())
250 break;
251
252 coeffs_[(height_-1-i)*(L[0]+1)+j] = static_cast<double>(value);
253 }
254
255 for (unsigned int k=0; k < imgWidth-width_; ++k)
256 pgmfile >> std::skipws >> value;
257 }
258 }
259 else
260 DUNE_THROW(Dune::Exception,"File is not an ASCII PGM-File.");
261
262 }
263
283 template <typename FType>
284 static void exportGreyMap( const char* filename,
285 const FType& function,
286 RangeFieldTypeFor<FType> fRangeMin, RangeFieldTypeFor<FType> fRangeMax,
287 const DomainFieldType xDomainMin, const DomainFieldType xDomainMax,
288 const DomainFieldType yDomainMin, const DomainFieldType yDomainMax,
289 const unsigned int width, const unsigned int height,
290 const std::string info="",
291 const unsigned int maxGreyVal=255, const ColorScheme colorscheme=DEFAULT)
292 {
294 using RangeFieldType = RangeFieldTypeFor<FType>;
295
296 DomainFieldType xLength = xDomainMax - xDomainMin;
297 DomainFieldType yLength = yDomainMax - yDomainMin;
298
299 RangeFieldType rangeInterval = fRangeMax-fRangeMin;
300
301 if (xLength <= 0.0 or yLength <= 0.0 or rangeInterval <= 0.0)
302 DUNE_THROW(Dune::RangeError,"Domain has zero or negative extension or range interval has zero length or negative extension(thrown by PortableGreyMap::exportGreyMap.");
303
304 double tFactor = maxGreyVal/rangeInterval;
305
306 DomainType r(0.0);
307 RangeType fval(0.0);
308
309 std::ofstream pgmfile(filename, std::ios::trunc | std::ios::out);
310
311 // write preliminaries ("P2", some comment, height, width, maxGreyVal) to stream
312 pgmfile << "P2" << std::endl << "# file created by PortableGreyMap (dune-fufem)" << std::endl << "# " << info << std::endl << height << " " << width << std::endl << maxGreyVal << std::endl;
313
314 r[0] = xDomainMin;
315 r[1] = yDomainMax;
316
317 for (unsigned int j= 0; j<height; ++j)
318 {
319 r[0] = xDomainMin;
320 for (unsigned int i= 0; i<width; ++i)
321 {
322 fval = function(r);
323
324 // 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
325 int greyval = (colorscheme==DEFAULT ? std::floor((fval[0]-fRangeMin)*tFactor+0.5) : maxGreyVal-std::floor((fval[0]-fRangeMin)*tFactor+0.5) );
326
327 // greyval >> endl >> PGM
328 pgmfile << greyval << std::endl;
329 r[0] = xDomainMin + (i+1)*xLength/(width-1);
330 }
331 r[1] = yDomainMax - (j+1)*yLength/(height-1);
332 }
333
334 // close PGM (?)
335 pgmfile.close();
336 }
337
338 /* \brief evaluates interpolated greymap at global point
339 *
340 * The greymap is evaluated at point x of the domain \f$ \Omega \f$
341 * assuming a linear transformation \f$ \Omega \longrightarrow [0,width_]\times[0,height_]\f$. The returnvalue is scaled
342 * according to \f$[fRangeMin_,fRangeMax_]\f$.
343 *
344 * \param x point in \f$ \Omega \f$ at whicnh to evaluate
345 * \returns the function value
346 */
348 {
349 if (greyMapFunction_==0)
350 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
351
352 DomainType xx = x;
353
354 xx[0] = (x[0]-xDomainMin_)/(xDomainMax_-xDomainMin_)*(width_-1);
355 xx[1] = (x[1]-yDomainMin_)/(yDomainMax_-yDomainMin_)*(height_-1);
356 RangeType r = (*greyMapFunction_)(xx);
357
358 return fRangeMin_ + RangeType((colorscheme_==DEFAULT ? RangeType(r/imgParams_[2]) : (RangeType(1)-r/imgParams_[2]))*(fRangeMax_-fRangeMin_));
359 }
360
361 friend auto localFunction(const PortableGreyMap& pgm)
362 {
363 if (pgm.greyMapFunction_==0)
364 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
365 auto lf = localFunction(*(pgm.greyMapFunction_));
366 return [lf, &pgm](const auto& x) {
367 RangeType r = localGreyMapFunction(x);
368 return pgm.fRangeMin_ + RangeType((pgm.colorscheme_==DEFAULT ? RangeType(r/pgm.imgParams_[2]) : (RangeType(1)-r/pgm.imgParams_[2]))*(pgm.fRangeMax_-pgm.fRangeMin_));
369 };
370 }
371
372 const EntitySet& entitySet() const
373 {
374 if (greyMapFunction_==0)
375 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
376 return greyMapFunction_->entitySet();
377 }
378
379 /* \brief provides read access to the coefficients
380 */
381 const CoeffType& getCoeffs() const
382 {
383 if (greyMapFunction_==0)
384 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
385
386 return coeffs_;
387 }
388
389 /* \brief provides access to the grid on which the interpolated greymap lives
390 */
391 const GridType& getGrid() const
392 {
393 if (greyMapFunction_==0)
394 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
395
396 return *grid_;
397 }
398
399 /* \brief provides access to the width of the imported greymap section
400 */
401 unsigned int getWidth() const
402 {
403 if (greyMapFunction_==0)
404 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
405
406 return width_;
407 }
408
409 /* \brief provides access to the height of the imported greymap section
410 */
411 unsigned int getHeight() const
412 {
413 if (greyMapFunction_==0)
414 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
415
416 return height_;
417 }
418
419 /* \brief provides access to the width of the full (original) greymap image
420 */
421 unsigned int getImgWidth() const
422 {
423 if (greyMapFunction_==0)
424 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
425
426 return imgParams_[0];
427 }
428
429 /* \brief provides access to the height of the full (original) greymap image
430 */
431 unsigned int getImgHeight() const
432 {
433 if (greyMapFunction_==0)
434 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
435
436 return imgParams_[1];
437 }
438
439 /* \brief provides access to the used maximal value in the (original and imported) greymap corresponding to white
440 */
441 unsigned int getWhiteValue() const
442 {
443 if (greyMapFunction_==0)
444 DUNE_THROW(Dune::Exception,"No greymap has been loaded. Use readGreyMap() first.");
445
446 return imgParams_[2];
447 }
448
450 {
451 if (grid_!=0)
452 delete grid_;
453 if (greyMapFunction_!=0)
454 delete greyMapFunction_;
455 if (basis_!=0)
456 delete basis_;
457 }
458};
459
460#endif
461
#define DUNE_THROW(E,...)
friend friend class Entity
GridViewEntitySet< GridView, 0 > EntitySet
T atoi(T... args)
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:347
const CoeffType & getCoeffs() const
Definition portablegreymap.hh:381
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:163
Dune::FieldVector< double, 1 > RangeType
Definition portablegreymap.hh:41
PortableGreyMap(const RangeType fRangeMin, const RangeType fRangeMax, const ColorScheme colorscheme=DEFAULT)
Constructor.
Definition portablegreymap.hh:120
friend auto localFunction(const PortableGreyMap &pgm)
Definition portablegreymap.hh:361
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:421
GridType::Codim< 0 >::Entity Element
Definition portablegreymap.hh:38
Dune::Functions::DiscreteGlobalBasisFunction< Basis, CoeffType, Dune::Functions::HierarchicNodeToRangeMap, RangeType > FunctionType
Definition portablegreymap.hh:46
PortableGreyMap(const DomainType::field_type xDomainMin, const DomainType::field_type xDomainMax, const DomainType::field_type yDomainMin, const DomainType::field_type yDomainMax, const RangeType fRangeMin=RangeType(0), const RangeType fRangeMax=RangeType(1), const ColorScheme colorscheme=DEFAULT)
Constructor.
Definition portablegreymap.hh:98
unsigned int getWidth() const
Definition portablegreymap.hh:401
GridType::Codim< 0 >::Geometry::LocalCoordinate LocalDomainType
Definition portablegreymap.hh:37
const GridType & getGrid() const
Definition portablegreymap.hh:391
~PortableGreyMap()
Definition portablegreymap.hh:449
typename FunctionType::EntitySet EntitySet
Definition portablegreymap.hh:48
typename Dune::BlockVector< RangeType > CoeffType
Definition portablegreymap.hh:45
unsigned int getWhiteValue() const
Definition portablegreymap.hh:441
PortableGreyMap(const double fRangeMin=0, const double fRangeMax=1, const ColorScheme colorscheme=DEFAULT)
Constructor.
Definition portablegreymap.hh:139
const EntitySet & entitySet() const
Definition portablegreymap.hh:372
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:284
typename GridType::template Codim< 0 >::Geometry::GlobalCoordinate DomainType
Definition portablegreymap.hh:40
unsigned int getHeight() const
Definition portablegreymap.hh:411
unsigned int getImgHeight() const
Definition portablegreymap.hh:431
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)