CppNoddy  0.92
Loading...
Searching...
No Matches
TwoD_Mapped_Node_Mesh.h
Go to the documentation of this file.
1/// \file TwoD_Mapped_Node_Mesh.h
2/// A specification for a two dimensional mapped mesh object. Data
3/// is stored on a nodal mesh that is non-uniform (in general). This
4/// class essentially combines the mapping function for the mesh into
5/// the 2D storage of the data.
6
7#ifndef TWOD_MAPPED_NODE_MESH_H
8#define TWOD_MAPPED_NODE_MESH_H
9
10#include <vector>
11#include <fstream>
12
13#include <OneD_Node_Mesh.h>
14#include <DenseVector.h>
15#include <Types.h>
16
17namespace CppNoddy {
18
19 /// A two dimensional (mapped) mesh utility object.
20 template <typename _Type>
22 public:
23
24 /// Mapping function that provides a computational X coordinate
25 /// from a physical coordinate.
26 /// \param zeta The physical coordinate
27 /// \return The corresponding computational coordinate
28 virtual double FnComp_X(const double& zeta) const {
29 std::string problem;
30 problem = "The TwoD_Mapped_Node_Mesh::FnComp_X method has not been implemented.\n";
31 problem += "You have to implement this method to define the mesh.\n";
32 throw ExceptionRuntime(problem);
33 }
34
35 /// Mapping function that provides the first derivative of the
36 /// computational m_X coordinate as a function of the physical coordinate.
37 /// \param zeta The physical coordinate
38 /// \return The corresponding derivative of the computational coordinate
39 virtual double FnComp_Xd(const double& zeta) const {
40 std::string problem;
41 problem = "The TwoD_Mapped_Node_Mesh::FnComp_Xd method has not been implemented.\n";
42 problem += "You have to implement this method to define the mesh.\n";
43 throw ExceptionRuntime(problem);
44 }
45
46 /// Mapping function that provides the second derivative of the
47 /// computational X coordinate as a function of the physical coordinate.
48 /// \param zeta The physical coordinate
49 /// \return The corresponding derivative of the computational coordinate
50 virtual double FnComp_Xdd(const double& zeta) const {
51 std::string problem;
52 problem = "The TwoD_Mapped_Node_Mesh::FnComp_Xdd method has not been implemented.\n";
53 problem += "You have to implement this method to define the mesh.\n";
54 throw ExceptionRuntime(problem);
55 }
56
57 /// Mapping function that provides the
58 /// computational Y coordinate as a function of the physical coordinate.
59 /// \param eta The physical coordinate
60 /// \return The corresponding derivative of the computational coordinate
61 virtual double FnComp_Y(const double& eta) const {
62 std::string problem;
63 problem = "The TwoD_Mapped_Node_Mesh::FnComp_Y method has not been implemented.\n";
64 problem += "You have to implement this method to define the mesh.\n";
65 throw ExceptionRuntime(problem);
66 }
67
68 /// Mapping function that provides the first derivative of the
69 /// computational Y coordinate as a function of the physical coordinate.
70 /// \param eta The physical coordinate
71 /// \return The corresponding derivative of the computational coordinate
72 virtual double FnComp_Yd(const double& eta) const {
73 std::string problem;
74 problem = "The TwoD_Mapped_Node_Mesh::FnComp_Yd method has not been implemented.\n";
75 problem += "You have to implement this method to define the mesh.\n";
76 throw ExceptionRuntime(problem);
77 }
78
79 /// Mapping function that provides the second derivative of the
80 /// computational Y coordinate as a function of the physical coordinate.
81 /// \param eta The physical coordinate
82 /// \return The corresponding derivative of the computational coordinate
83 virtual double FnComp_Ydd(const double& eta) const {
84 std::string problem;
85 problem = "The TwoD_Mapped_Node_Mesh::FnComp_Ydd method has not been implemented.\n";
86 problem += "You have to implement this method to define the mesh.\n";
87 throw ExceptionRuntime(problem);
88 }
89
91 {}
92
93 /// ctor of a blank mesh
94 TwoD_Mapped_Node_Mesh(const double left, const double right, const double bottom, const double top, const std::size_t nx, const std::size_t ny, const std::size_t nvars) : m_left(left), m_right(right), m_bottom(bottom), m_top(top), m_nx(nx), m_ny(ny), m_nv(nvars) {
95#ifdef DEBUG
96 std::cout << "[DEBUG] making a blank TwoD_Mapped_Node_Mesh\n";
97 std::cout << "[DEBUG] a " << nx << " by " << ny << " mesh with " << nvars << " variables.\n";
98#endif
99 // initialise the storage, but fill these below in init_mapping()
104 // we'll store the data as ( x, y, v ) -> x * ny * nv + y * nv + v
106 // user needs to call init_mapping() to set up m_compX, m_compY after this
107#ifdef DEBUG
108 std::cout << "[DEBUG] leaving the TwoD_Mapped_Node_Mesh ctor.\n";
109#endif
110 }
111
112
113 // ctor from a file
114 TwoD_Mapped_Node_Mesh(std::string filename, const std::size_t nx, const std::size_t ny, const std::size_t nv) :
115 m_nx(nx), m_ny(ny), m_nv(nv) {
116 // need storage for the coordinates
121 // we'll store the data as ( x, y, v ) -> x * ny * nv + y * nv + v
123 // now read the mesh from the given filename -- this also updates the m_X data
124 read(filename, true);
125 // set up the private member data on the box size.
126 m_left = m_X[0];
127 m_right = m_X[m_nx-1];
128 m_bottom = m_Y[0];
129 m_top = m_Y[m_ny-1];
130 // user needs to call init_mapping() to set up m_compX, m_compY after this
131 }
132
133
134 // Construct the coordinate mapping. The computational mesh is uniform
135 // with m_nx x m_ny nodes. The physical mesh spans the domain m_left to m_right
136 // and m_bottom to m_top, and its nodes are non-uniformly spaced. The physical
137 // nodes are found by inverting the mapping with Newton iteration.
138 void init_mapping();
139
140 std::pair<double,double> get_comp_step_sizes() const;
141
142 /// dtor
144 {}
145
146 /// Access operator for a nodal point that returns a vector
147 /// \param nodex The nodal index value in the first direction
148 /// \param nodey The nodal index value in the second direction
149 /// \return The vector of variables stored at the node
150 DenseVector<_Type> operator()(const std::size_t nodex, const std::size_t nodey);
151
152 /// Access operator for a nodal point/variable in the mesh
153 /// \param nodex The nodal index value in the first direction
154 /// \param nodey The nodal index value in the second direction
155 /// \param var The variable index to be accessed
156 _Type& operator()(const std::size_t nodex, const std::size_t nodey, const std::size_t var);
157
158 /// Const access operator for a nodal point/variable in the mesh
159 /// \param nodex The nodal index value in the first direction
160 /// \param nodey The nodal index value in the second direction
161 /// \param var The variable index to be accessed
162 const _Type& operator()(const std::size_t nodex, const std::size_t nodey, const std::size_t var) const;
163
164 /// Access the physical nodal position - as a pair.
165 /// \param nodex The x nodal position to return
166 /// \param nodey The y nodal position to return
167 /// \return The spatial position of this node as a pair
168 std::pair<double, double> coord(const std::size_t nodex, const std::size_t nodey) const;
169
170 /// Set the variables stored at A SPECIFIED node
171 /// \param nodex The x nodal index to be set
172 /// \param nodey The y nodal index to be set
173 /// \param U The vector of VARIABLES to be written to this nodal point
174 void set_nodes_vars(const std::size_t nodex, const std::size_t nodey, const DenseVector<_Type>& U);
175
176 /// Get the variables stored at A SPECIFIED node -- equivalent to mesh(nodex,nodey).
177 /// \param nodex The x nodal index to be returned
178 /// \param nodey The y nodal index to be returned
179 /// \return The vector of VARIABLES stored at this nodal point
180 DenseVector<_Type> get_nodes_vars(const std::size_t nodex, const std::size_t nodey) const;
181
182 /// Get the number of nodes in the two directions of the 2D mesh
183 /// \return A pair consisting of the number of nodes in the 2 directions
184 std::pair< std::size_t, std::size_t > get_nnodes() const;
185
186 /// Get the number of variables that are stored at each node
187 /// \return The number of variables that have data stored at
188 /// each nodal point
189 std::size_t get_nvars() const;
190
191 /// Access the vector of x-nodal positions
192 /// \return A vector of the nodal positions for this mesh
194
195 /// Access the vector of y-nodal positions
196 /// \return A vector of the nodal positions for this mesh
198
199 /// Get a cross section of the 2D mesh at a specified (constant) x node
200 /// \param nodex The x nodal index at which the cross section is to be taken
201 /// \return A 1D nodal mesh
202 OneD_Node_Mesh<_Type> get_xsection_at_xnode(const std::size_t nodex) const;
203
204 /// Get a cross section of the 2D mesh at a specified (constant) y node
205 /// \param nodey The y nodal index at which the cross section is to be taken
206 /// \return A 1D nodal mesh
207 OneD_Node_Mesh<_Type> get_xsection_at_ynode(const std::size_t nodey) const;
208
209 /// A simple method for reading data from a file
210 /// \param filename The filename to write the data to (will overwrite)
211 /// \param reset Will reset the nodal positions using those from the file
212 void read(std::string filename, const bool reset = false);
213
214 /// A simple method for dumping data to a file for gnuplot surface plotting
215 /// \param filename The filename to write the data to (will overwrite)
216 void dump_gnu(std::string filename) const;
217
218 /// Normalise all data in the mesh based on one variable.
219 /// \param var This var will have its peak (absolute) value as +/-unity
220 /// following the normalisation. All other variables will also be rescaled by
221 /// the same amount.
222 void normalise(const std::size_t& var);
223
224 /// Rescale all values stored in the mapped mesh by a scalar
225 /// \param value The scalar that is to multiply all mesh content
226 void scale(const _Type& value) {
227 m_vars.scale(value);
228 }
229
230 /// Find the maximum stored absolute value in the mesh for a
231 /// given variable -- no interpolation is used
232 /// \param var The variable index whose maximum is being asked for
233 /// \return The value of the maximum (abs value)
234 double max(unsigned var) {
235 double max(0.0);
236 // step through the nodes
237 for(unsigned nodex = 0; nodex < m_nx; ++nodex) {
238 for(unsigned nodey = 0; nodey < m_ny; ++nodey) {
239 if(std::abs(m_vars[(nodex * m_ny + nodey) * m_nv + var ]) > max) {
240 max = std::abs(m_vars[(nodex * m_ny + nodey) * m_nv + var ]);
241 }
242 }
243 }
244 return max;
245 }
246
247 /// Get a bilinearly interpolated value at a specified point
248 /// \param x Physical (unmapped) x-coordinate in the 2D mesh
249 /// \param y Physical (unmapped) y-coordinate in the 2D mesh
250 /// \return A vector of bilinearly interpolated values
251 DenseVector<_Type> get_interpolated_vars(const double& x, const double& y)
252 {
253 double compX = FnComp_X(x);
254 double compY = FnComp_Y(y);
255 const double tol(1.e-8);
256 // check start and end
257 if ((compX < m_compX[0] - tol) || (compX > m_compX[m_nx-1] + tol)) {
258 std::string problem;
259 problem = " The TwoD_Node_Mesh.get_interpolated_vars method has been called with \n";
260 problem += " an x coordinate that lies outside the mesh. \n";
261 throw ExceptionRuntime(problem);
262 }
263 // check start and end
264 if ((compY < m_compY[0] - tol) || (compY > m_compY[m_ny-1] + tol)) {
265 std::string problem;
266 problem = " The TwoD_Node_Mesh.get_interpolated_vars method has been called with \n";
267 problem += " a y coordinate that lies outside the mesh. \n";
268 throw ExceptionRuntime(problem);
269 }
270 int bottom_j(-1);
271 for (unsigned j = 0; j < m_ny-1; ++j) {
272 if ((compY >= m_compY[j] - tol) && (compY <= m_compY[j+1] + tol)) {
273 bottom_j = j;
274 }
275 }
276 if (bottom_j == -1) {
277 std::string problem;
278 problem = " The TwoD_Node_Mesh.get_interpolated_vars method is broken.\n";
279 throw ExceptionRuntime(problem);
280 }
281 //
282 OneD_Node_Mesh<_Type> bottom_row( m_compX, m_nv );
284 for (std::size_t i = 0; i < m_nx; ++i ) {
285 bottom_row.set_nodes_vars(i, this -> get_nodes_vars(i, bottom_j));
286 top_row.set_nodes_vars(i, this -> get_nodes_vars(i, bottom_j+1));
287 }
288 const double compY1 = m_compY[ bottom_j ];
289 const double compY2 = m_compY[ bottom_j+1 ];
290 DenseVector<_Type> result =
291 top_row.get_interpolated_vars(compX)*(compY-compY1)/(compY2-compY1)
292 + bottom_row.get_interpolated_vars(compX)*(compY2-compY)/(compY2-compY1);
293 return result;
294 }
295
296
297
298 protected:
299
300 // domain boundaries in physical space
302 // we'll store the number of nodes
303 std::size_t m_nx, m_ny, m_nv;
304 // store computational space (uniform) x nodal points
305 // just for convenience since it is uniform we don't need to
307 // store computational space (uniform) y nodal points
308 // just for convenience since it is uniform we don't need to
310 // store physical space (non-uniform) x nodal points
312 // store physical space (non-uniform) y nodal points
314 // store the nodal values
316 };
317
318 template <typename _Type>
319 inline DenseVector<_Type> TwoD_Mapped_Node_Mesh<_Type>::operator()(const std::size_t nodex, const std::size_t nodey ) {
320#ifdef PARANOID
321 if(nodex > m_nx - 1 || nodey > m_ny - 1) {
322 std::string problem;
323 problem = " The TwoD_Mapped_Node_Mesh.operator() method is trying to \n";
324 problem += " access a nodal point that is not in the mesh. \n";
325 throw ExceptionRange(problem, m_nx, nodex, m_ny, nodey);
326 }
327#endif
328 return get_nodes_vars(nodex,nodey);
329 }
330
331
332 template <typename _Type>
333 inline _Type& TwoD_Mapped_Node_Mesh<_Type>::operator()(const std::size_t nodex, const std::size_t nodey, const std::size_t var) {
334#ifdef PARANOID
335 if(nodex > m_nx - 1 || nodey > m_ny - 1) {
336 std::string problem;
337 problem = " The TwoD_Mapped_Node_Mesh.operator() method is trying to \n";
338 problem += " access a nodal point that is not in the mesh. \n";
339 throw ExceptionRange(problem, m_nx, nodex, m_ny, nodey);
340 }
341 if(var > m_nv - 1) {
342 std::string problem;
343 problem = " The TwoD_Mapped_Node_Mesh.operator() method is trying to \n";
344 problem += " access a variable index that is not in the mesh. \n";
345 throw ExceptionRange(problem, m_nv, var);
346 }
347#endif
348 return m_vars[(nodex * m_ny + nodey) * m_nv + var ];
349 }
350
351 template <typename _Type>
352 inline const _Type& TwoD_Mapped_Node_Mesh<_Type>::operator()(const std::size_t nodex, const std::size_t nodey, const std::size_t var) const {
353#ifdef PARANOID
354 if(nodex > m_nx - 1 || nodey > m_ny - 1) {
355 std::string problem;
356 problem = " The TwoD_Mapped_Node_Mesh.operator() method is trying to \n";
357 problem += " access a nodal point that is not in the mesh. \n";
358 throw ExceptionRange(problem, m_nx, nodex, m_ny, nodey);
359 }
360 if(var > m_nv - 1) {
361 std::string problem;
362 problem = " The TwoD_Mapped_Node_Mesh.operator() method is trying to \n";
363 problem += " access a variable index that is not in the mesh. \n";
364 throw ExceptionRange(problem, m_nv, var);
365 }
366#endif
367 return m_vars[(nodex * m_ny + nodey) * m_nv + var ];
368 }
369
370 template <typename _Type>
371 inline std::pair<double, double> TwoD_Mapped_Node_Mesh<_Type>::coord(const std::size_t nodex, const std::size_t nodey) const {
372#ifdef PARANOID
373 if(nodex > m_nx - 1 || nodey > m_ny - 1) {
374 std::string problem;
375 problem = " The TwoD_Mapped_Node_Mesh.coord method is trying to \n";
376 problem += " access a nodal point that is not in the mesh. \n";
377 throw ExceptionRange(problem, m_nx, nodex, m_ny, nodey);
378 }
379#endif
380 std::pair< double, double > pos;
381 pos.first = m_X[ nodex ];
382 pos.second = m_Y[ nodey ];
383 return pos;
384 }
385
386}
387
388#endif // TWOD_MAPPED_NODE_MESH_H
@ U
Definition: BVPKarman.cpp:20
Specification for a templated DenseVector class – a dense, dynamic, vector object.
A specification for a one dimensional mesh object.
Some standard typedefs.
An DenseVector class – a dense vector object.
Definition: DenseVector.h:34
An exception to indicate that a CppNoddy container has been accessed with index/indices outside the m...
Definition: Exceptions.h:117
A generic runtime exception.
Definition: Exceptions.h:158
A one dimensional mesh utility object.
DenseVector< _Type > get_interpolated_vars(const _Xtype &pos) const
Get the variable data at an interpolated position using a first order scheme.
void set_nodes_vars(const std::size_t node, const DenseVector< _Type > &u)
Set the variables stored at A SPECIFIED node.
A two dimensional (mapped) mesh utility object.
virtual double FnComp_X(const double &zeta) const
Mapping function that provides a computational X coordinate from a physical coordinate.
DenseVector< _Type > get_interpolated_vars(const double &x, const double &y)
Get a bilinearly interpolated value at a specified point.
void read(std::string filename, const bool reset=false)
A simple method for reading data from a file.
DenseVector< _Type > get_nodes_vars(const std::size_t nodex, const std::size_t nodey) const
Get the variables stored at A SPECIFIED node – equivalent to mesh(nodex,nodey).
DenseVector< double > & xnodes()
Access the vector of x-nodal positions.
std::pair< double, double > get_comp_step_sizes() const
void init_mapping()
Sometimes a useful mapping is painful to invert analytically.
virtual double FnComp_Ydd(const double &eta) const
Mapping function that provides the second derivative of the computational Y coordinate as a function ...
OneD_Node_Mesh< _Type > get_xsection_at_xnode(const std::size_t nodex) const
Get a cross section of the 2D mesh at a specified (constant) x node.
double max(unsigned var)
Find the maximum stored absolute value in the mesh for a given variable – no interpolation is used.
void set_nodes_vars(const std::size_t nodex, const std::size_t nodey, const DenseVector< _Type > &U)
Set the variables stored at A SPECIFIED node.
void scale(const _Type &value)
Rescale all values stored in the mapped mesh by a scalar.
std::pair< std::size_t, std::size_t > get_nnodes() const
Get the number of nodes in the two directions of the 2D mesh.
void normalise(const std::size_t &var)
Normalise all data in the mesh based on one variable.
DenseVector< double > & ynodes()
Access the vector of y-nodal positions.
virtual double FnComp_Yd(const double &eta) const
Mapping function that provides the first derivative of the computational Y coordinate as a function o...
virtual double FnComp_Xdd(const double &zeta) const
Mapping function that provides the second derivative of the computational X coordinate as a function ...
TwoD_Mapped_Node_Mesh(std::string filename, const std::size_t nx, const std::size_t ny, const std::size_t nv)
DenseVector< _Type > operator()(const std::size_t nodex, const std::size_t nodey)
Access operator for a nodal point that returns a vector.
std::size_t get_nvars() const
Get the number of variables that are stored at each node.
virtual double FnComp_Y(const double &eta) const
Mapping function that provides the computational Y coordinate as a function of the physical coordinat...
TwoD_Mapped_Node_Mesh(const double left, const double right, const double bottom, const double top, const std::size_t nx, const std::size_t ny, const std::size_t nvars)
ctor of a blank mesh
virtual double FnComp_Xd(const double &zeta) const
Mapping function that provides the first derivative of the computational m_X coordinate as a function...
void dump_gnu(std::string filename) const
A simple method for dumping data to a file for gnuplot surface plotting.
std::pair< double, double > coord(const std::size_t nodex, const std::size_t nodey) const
Access the physical nodal position - as a pair.
OneD_Node_Mesh< _Type > get_xsection_at_ynode(const std::size_t nodey) const
Get a cross section of the 2D mesh at a specified (constant) y node.
A collection of OO numerical routines aimed at simple (typical) applied problems in continuum mechani...

© 2012

R.E. Hewitt