11#include <deal.II/base/function_parser.h>
22 namespace ShallowWaterInitialStates
31 template <
typename Description,
int dim,
typename Number>
42 const std::string subsection)
44 , hyperbolic_system_(hyperbolic_system)
46 filename_ =
"ryujin.tif";
48 "filename", filename_,
"GeoTIFF: image file to load");
50 transformation_ = {0., 0.01, 0., 0., 0., 0.01};
54 "Array \"t[]\" describing an affine transformation between image "
55 "space (indices i and j from bottom left) and real coordinates (x "
56 "and y): x = t[0] + t[1] * i + t[2] * j, and y = t[3] + t[4] * i + "
57 "t[5] * j. (This transformation sets the origin of the image space "
58 "into the bottom left corner with index i to the right and index j "
61 transformation_use_geotiff_ =
true;
62 this->add_parameter(
"transformation use geotiff",
63 transformation_use_geotiff_,
64 "GeoTIFF: read in transformation from GeoTIFF for "
65 "constructing the affine transformation. If set to "
66 "false the manually specified transformation "
67 "parameters will be used instead.");
69 transformation_use_geotiff_origin_ =
false;
71 "transformation use geotiff origin",
72 transformation_use_geotiff_origin_,
73 "GeoTIFF: read in affine shift (i.e., position of "
74 "lower left corner) from GeoTIFF for constructing "
75 "the affine transformation. If set to false the origin specified "
76 "in the transformation parameter will be used instead.");
78 height_expression_ =
"1.4";
80 "water height expression",
82 "A function expression describing the initial total water height");
84 velocity_expression_ =
"0.0";
86 "velocity expression",
88 "A function expression describing the initial velocity");
90 const auto set_up = [
this] {
95 driver_projection =
"";
96 affine_transformation = {0, 0, 0, 0, 0, 0};
97 inverse_affine_transformation = {0, 0, 0, 0, 0, 0};
98 raster_offset = {0, 0};
103 using FP = dealii::FunctionParser<dim>;
109 height_function_ = std::make_unique<FP>(height_expression_);
110 velocity_function_ = std::make_unique<FP>(velocity_expression_);
114 this->parse_parameters_call_back.connect(set_up);
119 const auto z = compute_bathymetry(point);
121 dealii::Tensor<1, 2, Number> primitive;
123 height_function_->set_time(t);
124 primitive[0] = std::max(0., height_function_->value(point) - z);
126 velocity_function_->set_time(t);
127 primitive[1] = velocity_function_->value(point);
129 const auto view = hyperbolic_system_.template view<dim, Number>();
130 return view.from_initial_state(primitive);
135 initial_precomputed_type
final
138 return {compute_bathymetry(point)};
145 void read_in_raster()
const
148 auto dataset_handle = GDALOpen(filename_.c_str(), GA_ReadOnly);
149 AssertThrow(dataset_handle,
150 dealii::ExcMessage(
"GDAL error: file not found"));
152 auto dataset = GDALDataset::FromHandle(dataset_handle);
153 Assert(dataset, dealii::ExcInternalError());
155 const auto driver = dataset->GetDriver();
157 driver_name = driver->GetMetadataItem(GDAL_DMD_LONGNAME);
158 if (dataset->GetProjectionRef() !=
nullptr)
159 driver_projection = dataset->GetProjectionRef();
164 dataset->GetRasterCount() == 1,
166 "GDAL driver error: currently we only support one raster"));
168 const auto raster_band = dataset->GetRasterBand(1);
170 AssertThrow(dataset->GetRasterXSize() == raster_band->GetXSize() &&
171 dataset->GetRasterYSize() == raster_band->GetYSize(),
173 "GDAL driver error: the raster band has a different "
174 "dimension than the (global) raster dimension of the "
175 "geotiff image. This is not supported."));
185 raster_offset = {0, 0};
186 raster_size = {dataset->GetRasterXSize(), dataset->GetRasterYSize()};
188 raster.resize(raster_size[0] * raster_size[1]);
189 const auto error_code = raster_band->RasterIO(
202 AssertThrow(error_code == 0,
204 "GDAL driver error: error reading in geotiff file"));
216 if (transformation_use_geotiff_) {
218 dataset->GetGeoTransform(affine_transformation.data()) == CE_None;
220 dealii::ExcMessage(
"GDAL driver error: no geo transform "
221 "present in geotiff file"));
223 affine_transformation = transformation_;
225 affine_transformation[2] *= -1.;
226 affine_transformation[5] *= -1.;
233 if (transformation_use_geotiff_ ==
false ||
234 transformation_use_geotiff_origin_ ==
false) {
235 const auto j_max = raster_size[1] - 1;
236 affine_transformation[0] =
237 transformation_[0] - j_max * affine_transformation[2];
238 affine_transformation[3] =
239 transformation_[3] - j_max * affine_transformation[5];
252 inverse_affine_transformation[0] = affine_transformation[0];
253 inverse_affine_transformation[3] = affine_transformation[3];
255 const auto determinant =
256 affine_transformation[1] * affine_transformation[5] -
257 affine_transformation[2] * affine_transformation[4];
258 const auto inv = 1. / determinant;
259 inverse_affine_transformation[1] = inv * affine_transformation[5];
260 inverse_affine_transformation[2] = inv * (-affine_transformation[2]);
261 inverse_affine_transformation[4] = inv * (-affine_transformation[4]);
262 inverse_affine_transformation[5] = inv * affine_transformation[1];
264 GDALClose(dataset_handle);
267 std::cout << std::setprecision(16);
268 std::cout <<
"GDAL: driver name = " << driver_name;
269 std::cout <<
"\nGDAL: projection = " << driver_projection;
270 std::cout <<
"\nGDAL: transformation =";
271 for (
const auto &it : affine_transformation)
272 std::cout <<
" " << it;
273 std::cout <<
"\nGDAL: inverse trafo =";
274 for (
const auto &it : inverse_affine_transformation)
275 std::cout <<
" " << it;
276 std::cout <<
"\nGDAL: raster offset =";
277 for (
const auto &it : raster_offset)
278 std::cout <<
" " << it;
279 std::cout <<
"\nGDAL: raster size =";
280 for (
const auto &it : raster_size)
281 std::cout <<
" " << it;
282 std::cout << std::endl;
286 static constexpr auto message =
287 "ryujin has to be configured with GDAL support in order to read in "
289 AssertThrow(
false, dealii::ExcMessage(message));
295 DEAL_II_ALWAYS_INLINE
inline std::array<double, 2>
296 apply_transformation(
const double i,
const double j)
const
298 const auto &at = affine_transformation;
299 const double x = at[0] + at[1] * i + at[2] * j;
300 const double y = at[3] + at[4] * i + at[5] * j;
305 DEAL_II_ALWAYS_INLINE
inline std::array<double, 2>
306 apply_inverse_transformation(
const double x,
const double y)
const
308 const auto &iat = inverse_affine_transformation;
309 const double i = iat[1] * (x - iat[0]) + iat[2] * (y - iat[3]);
310 const double j = iat[4] * (x - iat[0]) + iat[5] * (y - iat[3]);
315 DEAL_II_ALWAYS_INLINE
inline Number
316 compute_bathymetry(
const dealii::Point<dim> &point)
const
323 const double x = point[0];
325 if constexpr (dim >= 2)
327 const auto &[di, dj] = apply_inverse_transformation(x, y);
333 const auto i_left =
static_cast<unsigned int>(std::floor(di));
334 const auto i_right =
static_cast<unsigned int>(std::ceil(di));
335 const auto j_left =
static_cast<unsigned int>(std::floor(dj));
336 const auto j_right =
static_cast<unsigned int>(std::ceil(dj));
338 const bool in_bounds =
340 i_right < static_cast<unsigned int>(raster_size[0]) &&
342 j_right < static_cast<unsigned int>(raster_size[1]);
346 dealii::ExcMessage(
"Raster error: The requested point is outside "
347 "the image boundary of the geotiff file"));
349 const double i_ratio = std::fmod(di, 1.);
350 const double j_ratio = std::fmod(dj, 1.);
352 const auto v_iljl = raster[i_left + j_left * raster_size[0]];
353 const auto v_irjl = raster[i_right + j_left * raster_size[0]];
355 const auto v_iljr = raster[i_left + j_right * raster_size[0]];
356 const auto v_irjr = raster[i_right + j_right * raster_size[0]];
358 const auto v_jl = v_iljl * (1. - i_ratio) + v_irjl * i_ratio;
359 const auto v_jr = v_iljr * (1. - i_ratio) + v_irjr * i_ratio;
361 return v_jl * (1. - j_ratio) + v_jr * j_ratio;
367 std::string filename_;
369 std::array<double, 6> transformation_;
370 bool transformation_use_geotiff_;
371 bool transformation_use_geotiff_origin_;
373 std::string height_expression_;
374 std::string velocity_expression_;
383 mutable std::string driver_name;
384 mutable std::string driver_projection;
385 mutable std::array<double, 6> affine_transformation;
386 mutable std::array<double, 6> inverse_affine_transformation;
387 mutable std::array<int, 2> raster_offset;
388 mutable std::array<int, 2> raster_size;
389 mutable std::vector<float> raster;
393 std::unique_ptr<dealii::FunctionParser<dim>> height_function_;
394 std::unique_ptr<dealii::FunctionParser<dim>> velocity_function_;
void ensure_initialized(const Callable &creator) const
typename Description::HyperbolicSystem HyperbolicSystem
auto initial_precomputations(const dealii::Point< dim > &point) -> typename InitialState< Description, dim, Number >::initial_precomputed_type final
typename View::state_type state_type
state_type compute(const dealii::Point< dim > &point, Number t) final
GeoTIFF(const HyperbolicSystem &hyperbolic_system, const std::string subsection)
typename Description::template HyperbolicSystemView< dim, Number > View
Euler::HyperbolicSystem HyperbolicSystem