Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
TwoDMesh.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Jolien Creighton, Teviet Creighton
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/**
21 * \author Creighton, T. D.
22 * \file
23 * \ingroup TwoDMesh_h
24 * \brief Creates or destroys a hierarchical mesh of templates on an 2-dimensional parameter space.
25 *
26 * ### Description ###
27 *
28 * The routine <tt>LALCreateTwoDMesh()</tt> lays out an unevenly-spaced
29 * mesh on a 2-dimensional parameter space, according to the method
30 * presented in \ref TwoDMesh_h and detailed in
31 * TwoDMeshInternal.c. The parameter \c mesh is a handle to
32 * the head of the newly-created linked list of mesh points, while
33 * \c params points to the parameter structure used to create the
34 * list. On completion, <tt>params->nOut</tt> is set to the number of mesh
35 * points created.
36 *
37 * The routine <tt>LALDestroyTwoDMesh()</tt> destroys the list pointed to
38 * by <tt>*mesh</tt>, including all sub-meshes, and sets
39 * <tt>*mesh</tt>=\c NULL. If <tt>*mesh</tt> is already \c NULL,
40 * nothing is done (this is \e not an erroneous usage). If
41 * \c nFree \f$ \neq \f$ \c NULL, then <tt>*nFree</tt> is set to the number
42 * of nodes freed.
43 *
44 * The routine <tt>LALRefineTwoDMesh()</tt> creates a heirarchical search
45 * mesh by inserting copies of the nodes in the list pointed to by
46 * \c fineMesh into the \c subMesh fields of appropriate nodes in
47 * the list pointed to by \c coarseMesh. The contents of the
48 * \c fineMesh list are untouched. If a \c fineMesh tile does
49 * not overlap with any \c cosarseMesh tile, a warning is generated,
50 * but this is not treated as an error. If an internal error does occur,
51 * the refinement will be left in a state of partial completion; there is
52 * just too much overhead involved in maintaining an uncorrupted copy of
53 * the \c coarseMesh list for it to be worthwhile.
54 *
55 * ### Algorithm ###
56 *
57 * \c LALCreateTwoDMesh() simply creates a dummy node to serve as the
58 * head of the linked list, and calls <tt>LALTwoDMesh()</tt> in
59 * TwoDMeshInternal.c to attach a mesh to it. The details of the
60 * algorithm are given in TwoDMeshInternal.c.
61 *
62 * <tt>LALDestroyTwoDMesh()</tt> navigates down the linked list of mesh
63 * points, destroying them as it goes. It calls itself recursively on
64 * any non-empty sub-meshes to destroy them too.
65 *
66 * <tt>LALRefineTwoDMesh()</tt> moves along the \c fineMesh list; for
67 * each node in the list, it searches the \c coarseMesh list for the
68 * any tile that overlaps with the fine mesh tile. It then \e copies
69 * the fine mesh node (and its submesh, if any) into the coarse mesh
70 * node's \c subMesh list, using <tt>LALTwoDNodeCopy()</tt> in
71 * TwoDMeshInternal.c. Although it uses more memory, this
72 * recursive copy routine is preferred over simple relinking, so as to
73 * avoid any possible memory leaks: destroying the coarse mesh list will
74 * leave the fine mesh list intact, and vice-versa.
75 *
76 * To create a \f$ >2 \f$ ~level hierarchical search mesh, build it from the
77 * bottom up: call <tt>LALRefineTwoDMesh()</tt> to add the finest mesh to
78 * the next finest, add that to the next finest, and so on up to the
79 * coarsest mesh.
80 *
81 * ### Uses ###
82 *
83 * \code
84 * lalDebugLevel XLALPrintError()
85 * LALWarning() LALInfo()
86 * LALTwoDMesh() LALTwoDNodeCopy()
87 * LALFree()
88 * \endcode
89 *
90 * ### Notes ###
91 *
92 */
93
94#include <math.h>
95#include <lal/LALStdlib.h>
96#include <lal/LALConstants.h>
97#include <lal/TwoDMesh.h>
98
99#ifdef __GNUC__
100#define UNUSED __attribute__ ((unused))
101#else
102#define UNUSED
103#endif
104
105void
107 TwoDMeshNode **mesh,
109{
110 TwoDMeshNode head; /* dummy head node */
111 TwoDMeshNode *headPtr; /* pointer to above */
112
113 INITSTATUS( stat );
115
116 /* Check that input parameters exist, but that the mesh handle
117 points to a null pointer. Parameter fields will be checked
118 within the subroutine. */
122
123 /* Ben wants a warning if the widthMaxFac or widthRetryFac are
124 larger than is reasonable. */
125 if ( lalDebugLevel & LALWARNING ) {
126 REAL4 retry = params->widthRetryFac;
127 if ( params->widthMaxFac > LAL_SQRT2 ) {
128 LALWarning( stat, "widthMaxFac > sqrt(2)" );
129 }
130 if ( retry > 1.0 && retry * retry > params->widthMaxFac ) {
131 LALWarning( stat, "widthRetryFac > sqrt(widthMaxFac)" );
132 }
133 }
134
135 /* Create the list using LALTwoDMesh(). */
136 params->nOut = 0;
137 head.next = NULL;
138 headPtr = &head;
139 if ( lalDebugLevel & LALINFO ) {
140 LALInfo( stat, "Generating mesh\n" );
141 }
142 TRY( LALTwoDMesh( stat->statusPtr, &headPtr, params ), stat );
143 if ( lalDebugLevel & LALINFO )
144 if ( ( params->nIn == 0 ) || ( params->nOut < params->nIn ) ) {
145 XLALPrintError( "\n" );
146 LALInfo( stat, "Mesh complete" );
147 XLALPrintError( "\tnumber of mesh points: %u\n", params->nOut );
148 }
149
150 /* Update the output, and exit. */
151 *mesh = head.next;
153 RETURN( stat );
154}
155
156
157
158void
160 TwoDMeshNode **mesh,
161 UINT4 *nFree )
162{
163 INITSTATUS( stat );
165
166 /* Check that all parameters exist. */
168 if ( nFree ) {
169 *nFree = 0;
170 }
171
172 /* Free everything, recursively freeing sub-meshes if necessary. */
173 while ( *mesh ) {
174 UINT4 nSub = 0; /* nodes freed from sub-meshes */
175 TwoDMeshNode *last = *mesh; /* pointer to previous node */
176 if ( last->subMesh ) {
177 TRY( LALDestroyTwoDMesh( stat->statusPtr, &( last->subMesh ),
178 &nSub ), stat );
179 }
180 *mesh = last->next;
181 LALFree( last );
182 if ( nFree ) {
183 *nFree += nSub + 1;
184 }
185 }
186
187 /* If we got here without sigsegving, we're done. */
189 RETURN( stat );
190}
191
192
193
194void
196 TwoDMeshNode *coarseMesh,
197 TwoDMeshNode *fineMesh )
198{
199 BOOLEAN UNUSED found; /* whether a fine point is in any coarse tile */
200 UINT4 UNUSED lost = 0; /* number of fine points not found */
201 TwoDMeshNode *here; /* pointer to coarse mesh list */
202
203 INITSTATUS( stat );
205
208
209 /* Scan through fine mesh. We never return to the head of the fine
210 mesh, so we can directly increment the parameter *finemesh. */
211 for ( ; fineMesh != NULL; fineMesh = fineMesh->next ) {
212 /* Centre, width, height, and slope of fine tile */
213 REAL4 xFine = fineMesh->x;
214 REAL4 yFine = fineMesh->y;
215 REAL4 dxFine = fineMesh->dx;
216 REAL4 dyFine = 0.5 * ( fineMesh->dy[1] - fineMesh->dy[0] );
217 REAL4 mFine = 0.5 * ( fineMesh->dy[1] + fineMesh->dy[0] ) / dxFine;
218
219 /* For each fine mesh tile, scan through coarse mesh, and look for
220 ones that overlap in their x domains. */
221 found = 0;
222 for ( here = coarseMesh; here != NULL; here = here->next ) {
223 REAL4 x = here->x - xFine;
224 if ( fabs( x ) <= dxFine + here->dx ) {
225
226 /* Transform the coarse mesh tile into sheared coordinates
227 centred on the fine mesh tile. */
228 REAL4 y = here->y + mFine * x - yFine;
229 REAL4 dy0 = here->dy[0] + mFine * here->dx;
230 REAL4 dy1 = here->dy[1] + mFine * here->dx;
231
232 /* See if there is any possibility of overlap. */
233 if ( ( fabs( y ) <= dyFine + fabs( dy0 ) ) ||
234 ( fabs( y ) <= dyFine + fabs( dy1 ) ) ) {
235
236 /* We check for overlap on the left and right sides of the
237 common domain of the two tiles. On either side, the
238 coarse tile can be either completely below the fine tile
239 (-1), completely above the fine tile (+1), or overlapping
240 it (0). We store this information in two INT2's,
241 below. */
242 INT2 overlap[2] = { 0, 0 };
243
244 /* Compute height and slope of coarse tile in the sheared
245 coordinates of the fine mesh tile. */
246 REAL4 dy = 0.5 * ( dy1 - dy0 );
247 REAL4 m = 0.5 * ( dy1 + dy0 );
248
249 /* Find leftmost point of overlap of the two tiles relative
250 to the coarse mesh, and test the range of the coarse-mesh
251 tile at that point. */
252 REAL4 xOver = -here->dx;
253 if ( xOver < -x - dxFine ) {
254 xOver = -x - dxFine;
255 }
256 if ( -dy + m * xOver <= dyFine ) {
257 if ( dy + m * xOver >= -dyFine ) {
258 overlap[0] = 0;
259 } else {
260 overlap[0] = -1;
261 }
262 } else {
263 overlap[0] = 1;
264 }
265
266 /* Find rightmost point of overlap of the two tiles relative
267 to the coarse mesh, and test the range of the coarse-mesh
268 tile at that point. */
269 if ( overlap[0] ) {
270 xOver = here->dx;
271 if ( xOver > -x + dxFine ) {
272 xOver = -x + dxFine;
273 }
274 if ( -dy + m * xOver <= dyFine ) {
275 if ( dy + m * xOver >= -dyFine ) {
276 overlap[1] = 0;
277 } else {
278 overlap[1] = -1;
279 }
280 } else {
281 overlap[1] = 1;
282 }
283 }
284
285 /* The two tiles overlap if either side has a value of 0 or
286 if the two sides have opposite sign. */
287 overlap[0] *= overlap[1];
288 if ( !overlap[0] ) {
289
290 /* This is it! Copy the fine mesh node and add it into
291 the coarse submesh. */
292 TwoDMeshNode *copy = NULL;
293 TRY( LALTwoDNodeCopy( stat->statusPtr, &copy, fineMesh ),
294 stat );
295 copy->next = coarseMesh->subMesh;
296 coarseMesh->subMesh = copy;
297 found = 1;
298 }
299 }
300 }
301 }
302 /* If no coarse tile overlapped, make a note of this. */
303 if ( !found ) {
304 lost++;
305 if ( lalDebugLevel & LALINFO ) {
306 LALInfo( stat, "Fine mesh tile has no overlapping coarse tile" );
307 XLALPrintError( "\tlocation: (%f,%f)\n", xFine, yFine );
308 }
309 }
310 }
311 /* If any fine mesh tiles were lost, warn the user. */
313 if ( lost > 0 ) {
314 LALWarning( stat, "Some fine mesh tiles were lost" );
315 XLALPrintError( "\tnumber lost = %u\n", lost );
316 }
317
318 /* Done. */
320 RETURN( stat );
321}
#define LALFree(p)
#define TRY(func, statusptr)
#define ATTATCHSTATUSPTR(statusptr)
#define ASSERT(assertion, statusptr, code, mesg)
#define DETATCHSTATUSPTR(statusptr)
#define INITSTATUS(statusptr)
#define RETURN(statusptr)
#define LAL_SQRT2
unsigned char BOOLEAN
int16_t INT2
uint32_t UINT4
float REAL4
#define lalDebugLevel
LALINFO
LALWARNING
int LALWarning(LALStatus *status, const char *warning)
int LALInfo(LALStatus *status, const char *info)
static const INT4 m
void LALTwoDMesh(LALStatus *status, TwoDMeshNode **tail, TwoDMeshParamStruc *params)
#define TWODMESHH_MSGENUL
Definition: TwoDMesh.h:111
#define TWODMESHH_EOUT
Definition: TwoDMesh.h:104
#define TWODMESHH_ENUL
Definition: TwoDMesh.h:103
void LALCreateTwoDMesh(LALStatus *stat, TwoDMeshNode **mesh, TwoDMeshParamStruc *params)
Definition: TwoDMesh.c:106
void LALTwoDNodeCopy(LALStatus *status, TwoDMeshNode **new_, TwoDMeshNode *old)
void LALRefineTwoDMesh(LALStatus *stat, TwoDMeshNode *coarseMesh, TwoDMeshNode *fineMesh)
Definition: TwoDMesh.c:195
#define TWODMESHH_MSGEOUT
Definition: TwoDMesh.h:112
void LALDestroyTwoDMesh(LALStatus *stat, TwoDMeshNode **mesh, UINT4 *nFree)
Definition: TwoDMesh.c:159
int XLALPrintError(const char *fmt,...) _LAL_GCC_PRINTF_FORMAT_(1
list y
int found
head
This structure represents a single node in a linked list of mesh points, specified in the coordinate ...
Definition: TwoDMesh.h:124
struct tagTwoDMeshNode * next
The next mesh point in the linked list; NULL if this is the tail.
Definition: TwoDMesh.h:128
REAL4 dx
The half-width of the tile centred on the mesh point.
Definition: TwoDMesh.h:126
struct tagTwoDMeshNode * subMesh
The head of a linked list of fine mesh points within the rectangular area spanned by this mesh point ...
Definition: TwoDMesh.h:129
REAL4 dy[2]
The heights of the two right-hand corners of the tile, relative to the mesh point.
Definition: TwoDMesh.h:127
REAL4 y
The coordinates of the mesh point.
Definition: TwoDMesh.h:125
This structure stores the parameters required by the two-dimensional mesh placement functions.
Definition: TwoDMesh.h:142