aboutsummaryrefslogtreecommitdiff
path: root/src/patch/patch_edge.hh
blob: 7ba45bbcef09039f561aaf38036328dda686ebbe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// patch_edge.hh -- perpendicular/parallel geometry of one side of a patch
// $Header$
//

//
// prerequisites:
//	<stdio.h>
//	<assert.h>
//	<math.h>
//	"stdc.h"
//	"config.hh"
//	"../jtutil/util.hh"
//	"../jtutil/array.hh"
//	"../jtutil/linear_map.hh"
//	"coords.hh"
//	"grid.hh"
//	"fd_grid.hh"
//	"patch.hh"
//

// everything in this file is inside this namespace
namespace AHFinderDirect
	  {

//*****************************************************************************

//
// patch_edge -- perpendicular/parallel geometry of one side of a patch
//
// A  patch_edge  object is a very light-weight object which represents
// the basic geometry of a min/max rho/sigma side of a patch, i.e. it
// provides which-side-am-I predicates, coordinate conversions between
// (perp,par) and (rho,sigma), etc.  Every patch has (points to) 4  patch_edge
//  objects, one for each of the patch's sides.  See the comments in
// "patch.hh" for a "big picture" discussion of patches, patch edges,
// ghost zones, and patch interpolation regions.
//
// Note that since  patch_edge  has only  const  member functions
// (and members!), a  patch_edge  object is effectively always  const .
// This means there's no harm in always declaring  patch_edge  objects
// to be  const .
//

class	patch_edge
	{
public:
	//
	// ***** meta-info *****
	//

	// meta-info about patch
	patch& my_patch() const { return my_patch_; }

	// meta-info about edge
	bool is_rho() const { return is_rho_; }
	bool is_min() const { return is_min_; }
	bool perp_is_rho() const { return is_rho(); }
	bool par_is_rho() const { return ! is_rho(); }

	// human-readable {min,max}_{rho,sigma} name (for debugging etc)
	const char* name() const
		{
		return is_min()
		       ? (is_rho() ? "min_rho" : "min_sigma")
		       : (is_rho() ? "max_rho" : "max_sigma");
		}

	// are two edges really the same edge?
	bool operator==(const patch_edge& other_edge) const
		{
		return    ( my_patch() == other_edge.my_patch() )
		       && (   is_rho() == other_edge.  is_rho() )
		       && (   is_min() == other_edge.  is_min() );
		}
	bool operator!=(const patch_edge& other_edge) const
		{ return ! operator==(other_edge); }


	//
	// ***** adjacent edges *****
	//

	// get adjacent edges to our min/max par corners
	const patch_edge& min_par_adjacent_edge() const
		{
		return my_patch()
		       .minmax_ang_patch_edge(grid::side_is_min, par_is_rho());
		}
	const patch_edge& max_par_adjacent_edge() const
		{
		return my_patch()
		       .minmax_ang_patch_edge(grid::side_is_max, par_is_rho());
		}
	const patch_edge& minmax_par_adjacent_edge(bool want_min) const
		{
		return want_min ? min_par_adjacent_edge()
				: max_par_adjacent_edge();
		}


	//
	// ***** gridfn subscripting and coordinate maps *****
	//

	// gridfn strides perpendicular/parallel to the edge
	int perp_stride() const
		{ return my_patch().iang_stride(perp_is_rho()); }
	int par_stride() const
		{ return my_patch().iang_stride(par_is_rho()); }
	int ghosted_perp_stride() const
		{ return my_patch().ghosted_iang_stride(perp_is_rho()); }
	int ghosted_par_stride() const
		{ return my_patch().ghosted_iang_stride(par_is_rho()); }

	// coordinate maps perpendicular/parallel to the edge
	// ... range is that of the grid *including* ghost zones
	const jtutil::linear_map<fp>& perp_map() const
		{ return my_patch().ang_map(perp_is_rho()); }
	const jtutil::linear_map<fp>& par_map() const
		{ return my_patch().ang_map(par_is_rho()); }

	// meta-info about perp/par coordinates
	// ... as (mu,nu,phi) tensor indices
	local_coords::coords_set coords_set_perp() const
		{
		return perp_is_rho() ? my_patch().coords_set_rho()
				     : my_patch().coords_set_sigma();
		}
	local_coords::coords_set coords_set_par() const
		{
		return par_is_rho() ? my_patch().coords_set_rho()
				    : my_patch().coords_set_sigma();
		}


	//
	// ***** coordinate conversions *****
	//

	// coordinate conversions based on ghost zone direction
	// ... (iperp,ipar) <--> (perp,par)
	fp perp_of_iperp(int iperp) const
		{ return my_patch().ang_of_iang(perp_is_rho(), iperp); }
	fp par_of_ipar(int ipar) const
		{ return my_patch().ang_of_iang(par_is_rho(), ipar); }
	fp fp_iperp_of_perp(fp perp) const
		{ return my_patch().fp_iang_of_ang(perp_is_rho(), perp); }
	fp fp_ipar_of_par(fp par) const
		{ return my_patch().fp_iang_of_ang(par_is_rho(), par); }
	int iperp_of_perp(fp perp, jtutil::linear_map<fp>::noninteger_action
				   nia = jtutil::linear_map<fp>::nia_error)
		{ return my_patch().iang_of_ang(perp_is_rho(), perp, nia); }
	int ipar_of_par(fp par, jtutil::linear_map<fp>::noninteger_action
				nia = jtutil::linear_map<fp>::nia_error)
		{ return my_patch().iang_of_ang(par_is_rho(), par, nia); }

	// ... (perp,par) --> (rho,sigma)
	int irho_of_iperp_ipar(int iperp, int ipar) const
		{ return perp_is_rho() ? iperp : ipar; }
	int isigma_of_iperp_ipar(int iperp, int ipar) const
		{ return perp_is_rho() ? ipar : iperp; }
	fp rho_of_perp_par(fp perp, fp par) const
		{ return perp_is_rho() ? perp : par; }
	fp sigma_of_perp_par(fp perp, fp par) const
		{ return perp_is_rho() ? par : perp; }
	// ... (rho,sigma) --> (perp,par)
	int iperp_of_irho_isigma(int irho, int isigma) const
		{ return perp_is_rho() ? irho : isigma; }
	int ipar_of_irho_isigma(int irho, int isigma) const
		{ return par_is_rho() ? irho : isigma; }
	fp perp_of_rho_sigma(fp rho, fp sigma) const
		{ return perp_is_rho() ? rho : sigma; }
	fp par_of_rho_sigma(fp rho, fp sigma) const
		{ return par_is_rho() ? rho : sigma; }

	// outer perp of nominal grid on this edge
	// ... this is outermost *grid point*
	fp grid_outer_iperp() const
		{ return my_patch().minmax_iang(is_min(), is_rho()); }
	// ... this is actual outer edge of grid
	//     (might be halfway between two grid points)
	fp grid_outer_perp() const
		{ return my_patch().minmax_ang(is_min(), is_rho()); }
	// ... this is grid_outer_perp() converted back to the iperp
	//     coordinate, but still returned as floating-point;
	//     it will be either integer or half-integer
	fp fp_grid_outer_iperp() const
		{ return fp_iperp_of_perp(grid_outer_perp()); }



	//
	// ***** min/max/outer coordinates of edge *****
	//

	// min/max/size ipar of the edge
	// (these are exteme limits for any iperp, a given ghost zone
	//  or interpolation region may have tighter and/or iperp-dependent
	// limits)
	// ... not including corners
	int min_ipar_without_corners() const
		{ return my_patch().min_iang(par_is_rho()); }
	int max_ipar_without_corners() const
		{ return my_patch().max_iang(par_is_rho()); }
	// ... including corners
	int min_ipar_with_corners() const
		{ return my_patch().ghosted_min_iang(par_is_rho()); }
	int max_ipar_with_corners() const
		{ return my_patch().ghosted_max_iang(par_is_rho()); }
	// ... of the corners themselves
	int min_ipar_corner__min_ipar() const
		{ return min_ipar_with_corners(); }
	int min_ipar_corner__max_ipar() const
		{ return min_ipar_without_corners() - 1; }
	int max_ipar_corner__min_ipar() const
		{ return max_ipar_without_corners() + 1; }
	int max_ipar_corner__max_ipar() const
		{ return max_ipar_with_corners(); }

	// membership predicates for ipar corners, non-corners
	bool ipar_is_in_min_ipar_corner(int ipar) const
		{
		return    (ipar >= min_ipar_corner__min_ipar())
		       && (ipar <= min_ipar_corner__max_ipar());
		}
	bool ipar_is_in_max_ipar_corner(int ipar) const
		{
		return    (ipar >= max_ipar_corner__min_ipar())
		       && (ipar <= max_ipar_corner__max_ipar());
		}
	bool ipar_is_in_corner(int ipar) const
		{
		return    ipar_is_in_min_ipar_corner(ipar)
		       || ipar_is_in_max_ipar_corner(ipar);
		}
	bool ipar_is_in_noncorner(int ipar) const
		{
		return    (ipar >= min_ipar_without_corners())
		       && (ipar <= max_ipar_without_corners());
		}

	// convenience function selecting amongst the above
	// membership predicates
	bool ipar_is_in_selected_part(bool want_corners,
				      bool want_noncorner,
				      int ipar)
		const
		{
		return    (want_corners   && ipar_is_in_corner   (ipar))
		       || (want_noncorner && ipar_is_in_noncorner(ipar));
		}

	// outer (farthest from patch center) iperp of nominal grid
	int nominal_grid_outer_iperp() const
		{
		return my_patch()
		       .minmax_iang(is_min(), is_rho());
		}


	//
	// ***** constructor, destructor *****
	//

	patch_edge(patch& my_patch_in,
		   bool is_min_in, bool is_rho_in)
		: my_patch_(my_patch_in),
		  is_min_(is_min_in), is_rho_(is_rho_in)
		{ }
	// compiler-synthesized (no-op) destructor is fine

private:
	// we forbid copying and passing by value
	// by declaring the copy constructor and assignment operator
	// private, but never defining them
	patch_edge(const patch_edge& rhs);
	patch_edge& operator=(const patch_edge& rhs);

private:
	patch& my_patch_;
	const bool is_min_, is_rho_;
	};

//******************************************************************************

	  }	// namespace AHFinderDirect