Alamo
BMP.H
Go to the documentation of this file.
1//
2// Initialize a field using a bitmap image. (2D only)
3//
4// Note that in GIMP, you must select "do not write color space information"
5// and "24 bit R8 G8 B8" when exporting the BMP file.
6//
7
8#ifndef IC_BMP_H
9#define IC_BMP_H
10#include <cmath>
11
12#include "IC/IC.H"
13#include "Util/Util.H"
14#include "Util/BMP.H"
15#include "Unit/Unit.H"
16#include "Set/Set.H"
17#include "IO/ParmParse.H"
18
19namespace IC
20{
21class BMP : public IC<Set::Scalar>
22{
23public:
24 static constexpr const char* name = "bmp";
25
26 //enum Type {XYZ, XY, YZ, XZ};
28 enum Channel {R=0, G=1, B=2};
29
30 BMP (amrex::Vector<amrex::Geometry> &_geom) : IC(_geom) {}
31
32 BMP (amrex::Vector<amrex::Geometry> &_geom, IO::ParmParse &pp, std::string name) : BMP(_geom)
33 {
34 pp_queryclass(name,*this);
35 }
36 BMP (amrex::Vector<amrex::Geometry> &_geom, Unit a_unit, IO::ParmParse &pp, std::string name) : BMP(_geom)
37 {
38 unit = a_unit;
39 pp_queryclass(name,*this);
40 }
41
42 void Define(std::string bmpfilename)
43 {
44 bmp.Define(bmpfilename);//"Interface_Blur2.bmp");
45 }
46
47 void Add(const int &lev, Set::Field<Set::Scalar> &a_field, Set::Scalar)
48 {
49
50 Set::Vector DX(geom[lev].CellSize());
51 amrex::Box domain = geom[lev].Domain();
52
53 //Set::Scalar width = geom[lev].ProbHi()[0] - geom[lev].ProbLo()[0];
54 //Set::Scalar height = geom[lev].ProbHi()[1] - geom[lev].ProbLo()[1];
55
56 Set::Scalar img_width = (Set::Scalar)(bmp.nx-1);
57 Set::Scalar img_height = (Set::Scalar)(bmp.ny-1);
58 Set::Scalar img_dx = 1.0;
59 Set::Scalar img_dy = 1.0;
60
61 amrex::IndexType type = a_field[lev]->ixType();
62 domain.convert(type);
63
64 Set::Vector domlo(AMREX_D_DECL(geom[lev].ProbLo()[0],geom[lev].ProbLo()[1],0.0));
65 Set::Vector domhi(AMREX_D_DECL(geom[lev].ProbHi()[0],geom[lev].ProbHi()[1],0.0));
66
67 for (amrex::MFIter mfi(*a_field[lev],amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
68 {
69 amrex::Box bx;
70 if (type == amrex::IndexType::TheNodeType()) bx = mfi.grownnodaltilebox();
71 if (type == amrex::IndexType::TheCellType()) bx = mfi.growntilebox();
72 bx = bx & domain;
73
74
75 amrex::Array4<Set::Scalar> const& field = a_field[lev]->array(mfi);
76 amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k)
77 {
78 Set::Vector x = Set::Vector::Zero();
79 // NODE
80 if (type == amrex::IndexType::TheNodeType())
81 {
82 x(0) = domlo(0) + ((amrex::Real)(i)) * geom[lev].CellSize()[0];
83 x(1) = domlo(1) + ((amrex::Real)(j)) * geom[lev].CellSize()[1];
84 }
85 else if (type == amrex::IndexType::TheCellType())
86 {
87 x(0) = domlo(0) + ((amrex::Real)(i) + 0.5) * geom[lev].CellSize()[0];
88 x(1) = domlo(1) + ((amrex::Real)(j) + 0.5) * geom[lev].CellSize()[1];
89 }
90
91 //Set::Scalar x, y;
92 Set::Vector ximg;
93
94 if (fit == Fit::Stretch)
95 {
96 ximg(0) = (x(0) - domlo(0)) / (domhi(0) - domlo(0));
97 ximg(1) = (x(1) - domlo(1)) / (domhi(1) - domlo(1));
98 }
99 else if (fit == Fit::FitWidth)
100 {
101 Set::Scalar aspect_ratio = img_width / img_height;
102 ximg(0) = (x(0) - domlo(0)) / (domhi(0) - domlo(0));
103 ximg(1) = (x(1) - domlo(1)) / (domhi(1) - domlo(1));
104 ximg(1) -= 0.5 - 0.5 / aspect_ratio;
105 ximg(1) *= aspect_ratio;
106 }
107 else if (fit == Fit::FitHeight)
108 {
109 Set::Scalar aspect_ratio = img_height / img_width;
110 ximg(0) = (x(0) - domlo(0)) / (domhi(0) - domlo(0));
111 ximg(1) = (x(1) - domlo(1)) / (domhi(1) - domlo(1));
112 ximg(0) -= 0.5 - 0.5 / aspect_ratio;
113 ximg(0) *= aspect_ratio;
114 }
115 else if (fit == Fit::Coord)
116 {
117 ximg(0) = (x(0) - coord_lo(0)) / (coord_hi(0)-coord_lo(0));
118 ximg(1) = (x(1) - coord_lo(1)) / (coord_hi(1)-coord_lo(1));
119 }
120
121 ximg(0) = std::min(ximg(0),1.0); ximg(1) = std::min(ximg(1),1.0);
122 ximg(0) = std::max(ximg(0),0.0); ximg(1) = std::max(ximg(1),0.0);
123
124 ximg(0) *= img_width;
125 ximg(1) *= img_height;
126
127 int I = (int)(ximg(0));
128 int J = (int)(ximg(1));
129
130 Set::Scalar x1 = I*img_dx, x2 = (I+1)*img_dx;
131 Set::Scalar y1 = J*img_dy, y2 = (J+1)*img_dy;
132
133 if (I < bmp.nx-1 && J < bmp.ny - 1)
134 {
135 Set::Scalar fQ11 = ((Set::Scalar)(bmp(I, J )[channel]) - min) / (max - min);
136 Set::Scalar fQ12 = ((Set::Scalar)(bmp(I, J+1)[channel]) - min) / (max - min);
137 Set::Scalar fQ21 = ((Set::Scalar)(bmp(I+1,J )[channel]) - min) / (max - min);
138 Set::Scalar fQ22 = ((Set::Scalar)(bmp(I+1,J+1)[channel]) - min) / (max - min);
139
140 field(i,j,k) =
141 (fQ11*(x2-ximg(0))*(y2-ximg(1)) + fQ21*(ximg(0)-x1)*(y2-ximg(1)) + fQ12*(x2-ximg(0))*(ximg(1)-y1) + fQ22*(ximg(0)-x1)*(ximg(1)-y1)) / (img_dx * img_dy);
142 }
143 else if (I == bmp.nx-1 && J < bmp.ny - 1)
144 {
145 Set::Scalar fQ11 = ((Set::Scalar)(bmp(I ,J )[channel]) - min) / (max - min);
146 Set::Scalar fQ12 = ((Set::Scalar)(bmp(I ,J+1)[channel]) - min) / (max - min);
147 field(i,j,k) = fQ11 + (fQ12-fQ11) * (ximg(1) - y1);
148 }
149 else if (I < bmp.nx-1 && J == bmp.ny - 1)
150 {
151 Set::Scalar fQ11 = ((Set::Scalar)(bmp(I ,J )[channel]) - min) / (max - min);
152 Set::Scalar fQ21 = ((Set::Scalar)(bmp(I+1,J )[channel]) - min) / (max - min);
153 field(i,j,k) = fQ11 + (fQ21-fQ11) * (ximg(0) - x1);
154 }
155 else if (I == bmp.nx-1 && J == bmp.ny - 1)
156 {
157 Set::Scalar fQ11 = ((Set::Scalar)(bmp(I ,J )[channel]) - min) / (max - min);
158 field(i,j,k) = fQ11;
159 }
160 else
161 {
162 field(i,j,k) = 0.0;
163 }
164
165 if (field.nComp() > 1) field(i,j,k,1) = 1.0 - field(i,j,k,0);
166
167 field(i,j,k,0) *= scaling_factor;
168 if (field.nComp() > 1)
169 field(i,j,k,1) *= scaling_factor;
170
171 });
172 }
173 a_field[lev]->FillBoundary();
174 };
175
176private:
181 Set::Vector coord_lo = Set::Vector::Zero();
182 Set::Vector coord_hi = Set::Vector::Zero();
185
186public:
187 static void Parse(BMP & value, IO::ParmParse & pp)
188 {
189 std::string filename;
190 pp_query_file("filename",filename); // BMP filename.
191 value.bmp.Define(filename);
192
193 std::string fit;
194 // How to position image in space
195 pp_query_validate("fit",fit,{"stretch","fitheight","fitwidth","coord"});
196 if (fit=="stretch") value.fit = Fit::Stretch;
197 else if (fit=="fitheight") value.fit = Fit::FitHeight;
198 else if (fit=="fitwidth") value.fit = Fit::FitWidth;
199 else if (fit=="coord")
200 {
201 value.fit = Fit::Coord;
202 pp_queryarr("coord.lo",value.coord_lo); // Location of lower-left corner in the domain
203 pp_queryarr("coord.hi",value.coord_hi); // Location of upper-right corner in the domain
204 }
205 else Util::Abort(INFO,"Invalid value for bmp fit - should be stretch/fitheight/fitwidth but received '",fit,"'");
206
207 std::string channel;
208 // Color channel to use
209 pp_query_validate("channel",channel,{"r","g","b","R","G","B"});
210 if (channel=="r" || channel=="R") value.channel = Channel::R;
211 else if (channel=="g" || channel=="G") value.channel = Channel::G;
212 else if (channel=="b" || channel=="B") value.channel = Channel::B;
213 else Util::Abort(INFO,"Invalid value for bmp channel - should be r/g/b but received '",channel,"'");
214
215 value.min = (Set::Scalar) value.bmp.min()[value.channel];
216 value.max = (Set::Scalar) value.bmp.max()[value.channel];
217 pp_query_default("min",value.min,0.0); // Scaling value - minimum
218 pp_query_default("max",value.max,255.0); // Scaling value - maximum
219
220 value.scaling_factor = value.unit.normalized_value();
221}
222};
223}
224#endif
#define pp_query_validate(...)
Definition ParmParse.H:103
#define pp_queryarr(...)
Definition ParmParse.H:105
#define pp_query_file(...)
Definition ParmParse.H:104
#define pp_query_default(...)
Definition ParmParse.H:102
#define pp_queryclass(...)
Definition ParmParse.H:109
#define INFO
Definition Util.H:21
Definition BMP.H:22
Unit unit
Definition BMP.H:183
Set::Scalar scaling_factor
Definition BMP.H:184
static void Parse(BMP &value, IO::ParmParse &pp)
Definition BMP.H:187
BMP(amrex::Vector< amrex::Geometry > &_geom, IO::ParmParse &pp, std::string name)
Definition BMP.H:32
Set::Vector coord_lo
Definition BMP.H:181
Channel
Definition BMP.H:28
@ B
Definition BMP.H:28
@ R
Definition BMP.H:28
@ G
Definition BMP.H:28
Set::Scalar min
Definition BMP.H:180
void Define(std::string bmpfilename)
Definition BMP.H:42
Fit
Definition BMP.H:27
@ Coord
Definition BMP.H:27
@ FitWidth
Definition BMP.H:27
@ Stretch
Definition BMP.H:27
@ FitHeight
Definition BMP.H:27
Set::Scalar max
Definition BMP.H:180
Util::BMP bmp
Definition BMP.H:177
Set::Vector coord_hi
Definition BMP.H:182
static constexpr const char * name
Definition BMP.H:24
BMP(amrex::Vector< amrex::Geometry > &_geom, Unit a_unit, IO::ParmParse &pp, std::string name)
Definition BMP.H:36
Fit fit
Definition BMP.H:178
Channel channel
Definition BMP.H:179
void Add(const int &lev, Set::Field< Set::Scalar > &a_field, Set::Scalar)
Definition BMP.H:47
BMP(amrex::Vector< amrex::Geometry > &_geom)
Definition BMP.H:30
amrex::Vector< amrex::Geometry > & geom
Definition IC.H:61
std::array< int, 3 > min()
Definition BMP.H:60
void Define(std::string filename)
Definition BMP.H:17
std::array< int, 3 > max()
Definition BMP.H:71
int ny
Definition BMP.H:84
int nx
Definition BMP.H:84
Initialize a spherical inclusion.
Definition BMP.H:20
amrex::Real Scalar
Definition Base.H:18
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
void Abort(const char *msg)
Definition Util.cpp:225
Definition Unit.H:20
double normalized_value() const
Definition Unit.H:401
static Unit Less()
Definition Unit.H:187