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
192 // how to position the image
193 pp.query_switch("fit", {
194 {"stretch", [&]() {
195 value.fit = Fit::Stretch;
196 }},
197 {"fitheight", [&]() {
198 value.fit = Fit::FitHeight;
199 }},
200 {"fitwidth", [&]() {
201 value.fit = Fit::FitWidth;
202 }},
203 {"coord", [&]() {
204 value.fit = Fit::Coord;
205 // Lower-left coordinates of image in domain
206 pp.queryarr_required("coord.lo", value.coord_lo,Unit::Length());
207 // Upper-right coordinates of image in domain
208 pp.queryarr_required("coord.hi", value.coord_hi,Unit::Length());
209 }}
210 });
211
212 std::string channel;
213 // Color channel to use
214 pp.query_validate("channel",channel,{"r","g","b","R","G","B"});
215 if (channel=="r" || channel=="R") value.channel = Channel::R;
216 else if (channel=="g" || channel=="G") value.channel = Channel::G;
217 else if (channel=="b" || channel=="B") value.channel = Channel::B;
218 else Util::Abort(INFO,"Invalid value for bmp channel - should be r/g/b but received '",channel,"'");
219
220 value.min = (Set::Scalar) value.bmp.min()[value.channel];
221 value.max = (Set::Scalar) value.bmp.max()[value.channel];
222 pp.query_default("min",value.min,0.0); // Scaling value - minimum
223 pp.query_default("max",value.max,255.0); // Scaling value - maximum
224
225 value.scaling_factor = value.unit.normalized_value();
226
227 if (IO::ParmParse::InTraversalMode()) return;
228
229 value.bmp.Define(filename);
230}
231};
232}
233#endif
#define pp_queryclass(...)
Definition ParmParse.H:130
#define INFO
Definition Util.H:24
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
int query_validate(std::string name, int &value, std::vector< int > possibleintvals, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:569
int queryarr_required(std::string name, std::vector< T > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1223
int query_default(std::string name, T &value, T defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:492
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:961
int query_switch(std::string name, std::initializer_list< std::pair< std::string, std::function< void()> > > cases, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:714
static bool InTraversalMode()
Definition ParmParse.cpp:14
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:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:21
AMREX_GPU_HOST_DEVICE void Abort(const char *msg)
Definition Util.cpp:406
Definition Unit.H:21
double normalized_value() const
Definition Unit.H:506
static Unit Length()
Definition Unit.H:198
static Unit Less()
Definition Unit.H:197