GeoTessCExamples  2.0
TestCrust20.c
Go to the documentation of this file.
1 //- ****************************************************************************
2 //-
3 //- Copyright 2009 Sandia Corporation. Under the terms of Contract
4 //- DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
5 //- retains certain rights in this software.
6 //-
7 //- BSD Open Source License.
8 //- All rights reserved.
9 //-
10 //- Redistribution and use in source and binary forms, with or without
11 //- modification, are permitted provided that the following conditions are met:
12 //-
13 //- * Redistributions of source code must retain the above copyright notice,
14 //- this list of conditions and the following disclaimer.
15 //- * Redistributions in binary form must reproduce the above copyright
16 //- notice, this list of conditions and the following disclaimer in the
17 //- documentation and/or other materials provided with the distribution.
18 //- * Neither the name of Sandia National Laboratories nor the names of its
19 //- contributors may be used to endorse or promote products derived from
20 //- this software without specific prior written permission.
21 //-
22 //- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 //- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 //- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 //- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
26 //- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 //- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 //- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 //- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 //- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 //- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //- POSSIBILITY OF SUCH DAMAGE.
33 //-
34 //- ****************************************************************************
35 
36 #include <math.h>
37 
38 #include "GeoTessModelC.h"
39 #include "GeoTessPositionC.h"
40 #include "InterpolatorTypeC.h"
41 #include "GeoTessUtilsC.h"
42 #include "PointMapC.h"
43 #include <string.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include "ErrorHandler.h"
47 
48 #define len 128
49 
50 #define RAD_TO_DEG 57.295779513082320876798
51 
52 #define DEG_TO_RAD 0.017453292519943295769237
53 
54 void errorCheck(){
55  if(error_exists()){
56  fprintf(stderr, "Error: %s\n", error_getMessage());
57  exit(-1);
58  }
59 }
60 
61 int main(int argc, char** argv)
62 {
63  int i, layer;
64  char path[len];
65  GeoTessModelC* model;
66  GeoTessGridC* grid;
67  GeoTessPositionC* position;
68  GeoTessMetaDataC* meta;
69  PointMapC* pointMap;
70  char* strTmp;
71  double* u;
72  double v[3];
73  double earthRadius;
74 
75  int vertex, node, attribute;
76  double radius, value;
77 
78  double pointA[3];
79  double pointB[3];
80  int nPoints, maxPoints;
81  double requestedDelta;
82  double actualDelta;
83  double** rayPath;
84  double* radii;
85  int* pointIndices;
86  double* weights;
87  int allocatedSize;
88  int actualSize;
89  double sumWeights;
90  double integral;
91 
92  int tessId, levelId, vid, verticesSize, neighborsSize;
93 
94  int* vertices = NULL;
95  int nVertices = 0;
96 
97  int *neighbors = NULL;
98  int size = 0;
99 
100  if (argc != 2){
101  printf("\nMust provide a single command line argument specifying path to the GeoTessModels directory\n");
102  return 1;
103  }
104 
105  // specify the location of the GeoTess Crust 2.0 models.
106  path[0] = '\0';
107  strncat(path, argv[1], len);
108  strncat(path, "/crust20.geotess", len);
109 
110  printf("Loading model from file: %s\n\n", path);
111 
112  // instantiate a model and load the model from file
113  model = geomodel_create(path);
114 
115  errorCheck();
116 
117  // retrieve a reference to the ellipsoid stored in the model. This is usually a reference
118  // to the WGS84 ellipsoid, but not always. The EarthShape is used for converting between
119  // depth and radius and between geographic coordinates and geocentric unit vectors.
120  EarthShapeC* ellipsoid = geomodel_getEarthShape(model);
121 
122  strTmp = geomodel_toString(model);
123  printf("%s", strTmp);
124  free(strTmp);
125  strTmp=NULL;
126 
127  printf("\n");
128  printf("=============================================================================\n");
129  printf("\n");
130  printf("Interpolate Data\n");
131  printf("\n");
132  printf("=============================================================================\n\n");
133 
134  // instantiate a GeoTessPosition object which will manage the
135  // geographic position of an interpolation point, the interpolation
136  // coefficients, etc.
137  position = geoposition_getGeoTessPosition2(model, LINEAR);
138 
139  // set the position in the GeoTessPosition object to
140  // latitude = 30N, longitude = 90E, and radius 6371 km
141  earthshape_getVectorDegrees(ellipsoid, 30., 90., v);
142  geoposition_set2(position, v, 6371.);
143 
144  // regurgitate the position
145  printf("Interpolated model properties at lat, lon = %1.4f, %1.4f:\n\n",
146  earthshape_getLatDegrees(ellipsoid, geoposition_getVector(position)),
147  earthshape_getLonDegrees(ellipsoid, geoposition_getVector(position)));
148 
149  // print a table with values interpolated from the model at the
150  // specified position
151  printf("%s", "Layer Depth Thick vP vS density\n");
152  meta = geomodel_getMetaData(model);
153  for (layer = geometadata_getNLayers(meta) - 1; layer >= 0; --layer)
154  {
155  geoposition_setTop2(position,layer);
156  printf("%3d %10.4f %10.4f %10.4f %10.4f %10.4f\n",
157  layer, geoposition_getDepth(position),
158  geoposition_getLayerThickness2(position), geoposition_getValue(position, 0),
159  geoposition_getValue(position,1), geoposition_getValue(position, 2));
160  }
161 
162  // print out the index of the triangle in which the point resides.
163  printf("Interpolated point resides in triangle index = %d\n\n", geoposition_getTriangle(position));
164 
165  // print out a table with information about the 3 nodes at the
166  // corners of the triangle that contains the interpolation point.
167  // The information output is:
168  // the index of the node,
169  // node latitude in degrees,
170  // node longitude in degrees,
171  // interpolation coefficient, and
172  // distance in degrees from interpolation point.
173  strTmp = geoposition_toString(position);
174  printf("%s\n", strTmp);
175  free(strTmp);
176  strTmp=NULL;
177 
178  // initialize arrays to hold the pointIndices and weights for all the points in
179  // the model that are 'touched' by the interpolation point. These arrays will be resized,
180  // as needed in getWeights().
181  pointIndices = (int*)NULL;
182  weights = (double*)NULL;
183  allocatedSize = 0;
184 
185  // call the getWeights function
186  geoposition_getWeights(position, &pointIndices, &weights, &allocatedSize, &actualSize, 1.0);
187 
188  printf("geoposition_getWeights() returned weights for %d point indices:\n\n", actualSize);
189  printf("pointIndex weight\n");
190  sumWeights = 0;
191  for (i=0; i<actualSize; ++i)
192  {
193  printf("%10d %10.6f\n", pointIndices[i], weights[i]);
194  sumWeights += weights[i];
195  }
196  printf("\nSum of the weights is %1.6f\n", sumWeights);
197 
198  free(pointIndices);
199  pointIndices = NULL;
200  free(weights);
201  weights = NULL;
202 
203  errorCheck();
204 
205  printf("\n");
206  printf("=============================================================================\n");
207  printf("\n");
208  printf("Query Model Data\n");
209  printf("\n");
210  printf("=============================================================================\n\n");
211 
212  // need a GeoTessGridC object, which is a wrapper around a c++ GeoTessGrid object.
213  grid = geomodel_getGrid(model);
214 
215  // now we will extract some information about model values stored
216  // on grid nodes in the model. These are not interpolated values.
217 
218  // consider just one vertex. Vertex 57 is located in Tibet
219  vertex = 57;
220 
221  u = geogrid_getVertex(grid, vertex);
222 
223  earthRadius = earthshape_getEarthRadius(ellipsoid, u);
224 
225  printf("Vertex=%d lat = %1.4f lon = %1.4f ellipsoid_radius = %1.3f\n\n", vertex,
226  earthshape_getLatDegrees(ellipsoid, u),
227  earthshape_getLonDegrees(ellipsoid, u),
228  earthRadius);
229 
230  // write out the first header line which includes the names of the attributes
231  printf(" layer depth");
232  for (attribute=0; attribute<geometadata_getNAttributes(meta); ++attribute)
233  {
234  strTmp = geometadata_getAttributeName(meta, attribute);
235  printf(" %8s", strTmp);
236  free(strTmp);
237  strTmp=NULL;
238  }
239  printf("\n");
240 
241  // print out second header line which includes attribute units
242  printf("layer name (km) ");
243  for (attribute=0; attribute<geometadata_getNAttributes(meta); ++attribute)
244  {
245  strTmp = geometadata_getAttributeUnit(meta, attribute);
246  printf(" %8s", strTmp);
247  free(strTmp);
248  strTmp=NULL;
249  }
250  printf("\n");
251 
252  printf("---------------------------------------------------------------------------\n");
253 
254  // loop over the layers in reverse order (shallowest to deepest)
255  for (layer = geometadata_getNLayers(meta) - 1; layer >= 0; --layer)
256  {
257  // get the name of this layer
258  strTmp = geometadata_getLayerName(meta, layer);
259 
260  // loop over every node in this layer in reverse order (shallowest to deepest).
261  // The upper limit can be either geoprofile_getNRadii(profile) or
262  // geoprofile_getNData(profile). The resulting table will differ depending
263  // on which is chosen.
264  for (node=geomodel_getNRadii(model, vertex, layer)-1; node >= 0; --node)
265  {
266  // get the radius of the current node in km.
267  radius = geomodel_getRadius(model, vertex, layer, node);
268 
269  // print layer id, layer name, profile type and radius
270  printf("%3d %-16s %8.3f", layer, strTmp, earthRadius-radius);
271 
272  // loop over all the attributes (vp, vs, density, etc) and print out values.
273  for (attribute=0; attribute<geometadata_getNAttributes(meta); ++attribute)
274  {
275  value = geomodel_getValueDouble(model, vertex, layer, node, attribute);
276  printf(" %8.3f", value);
277  }
278  printf("\n");
279  }
280  printf("\n");
281  free(strTmp);
282  strTmp=NULL;
283  }
284 
285  errorCheck();
286 
287  printf("\n");
288  printf("=============================================================================\n");
289  printf("\n");
290  printf("Get Weights for a GreatCircle Raypath\n");
291  printf("\n");
292  printf("=============================================================================\n\n");
293 
294  printf("Compute travel time for a ray that travels along the top of the 'soft_sediments' \n");
295  printf("layer of the crust 2.0 model\n\n");
296 
297  // need a PointMap object, which treats all points in the model as if they were in
298  // one huge array.
299  pointMap = geomodel_getPointMap(model);
300 
301  // define two unit vectors, pointA and pointB.
302  // A is located at 0N, 0E and B is located at -10N, -10E.
303  earthshape_getVectorDegrees(ellipsoid, 0., 0., pointA);
304  earthshape_getVectorDegrees(ellipsoid, -10., -10., pointB);
305 
306  // specify the desired angular distance between points along the great circle path.
307  // The actual spacing will be reduced somewhat from this value so that uniform spacing
308  // will be achieved.
309  requestedDelta = 0.5 * DEG_TO_RAD;
310 
311  // number of points that will span the distance from pointA to pointB, inclusive.
312  // used only to ensure that enough memory is allocated to hold arrays rayPath and radii.
313  maxPoints = geoutils_getGreatCirclePointsN(pointA, pointB, requestedDelta, FALSE);
314 
315  // rayPath will be an array of unit vectors equally
316  // spaced along the great circle from pointA to pointB, inclusive
317  rayPath = (double**)malloc(sizeof(double*) * maxPoints);
318  for (i=0; i<maxPoints; ++i)
319  // allocate memory for unit vectors
320  rayPath[i] = (double*)malloc(sizeof(double) * 3);
321 
322  // radii will the radius of each of the points along the rayPath.
323  radii = (double*)malloc(sizeof(double) * maxPoints);
324 
325  // retrieve equally spaced points along the great circle from pointA to pointB, inclusive.
326  // requestedDelta is the desired separation of the points in radians.
327  // actualDelta is the actual point separation which is generally a little less than the requested
328  // value so that the point spacing is uniform.
329  // npoints is the number of points computed.
330  actualDelta = geoutils_getGreatCirclePointsD(pointA, pointB, requestedDelta, FALSE, rayPath, &nPoints);
331 
332  // for this example, set the radii of all points along the rayPath to constant value that is
333  // above the top of the 'soft_sediments' layer.
334  for (i=0; i<nPoints; ++i) radii[i] = 6378. ;
335 
336  // to set the radii to a constant depth of 50 km relative to WGS84 ellipsoid, use this:
337  // for (i=0; i<nPoints; ++i) radii[i] = geoutils_getEarthRadius(rayPath[i]) - 50.;
338 
339  // initialize arrays to hold the pointIndices and weights for all the points in
340  // the model that are 'touched' by the rayPath. A conservative estimate of the
341  // size of these arrays is 180 / triangle edge length in degrees * 5 for 2D models,
342  // and twice that for 3D models.
343  // These arrays will be resized as needed in geomodel_getPathIntegralW().
344  allocatedSize = 0;
345  pointIndices = NULL;
346  weights = NULL;
347 
348  // index of the attribute whose value is to be integrated along the rayPath.
349  // 0 corresponds to p-wave velocity in the current model.
350  attribute = 0;
351 
352  // integrate reciprocal of attribute along the rayPath and get the weights for the specified rayPaths.
353  // -Note that the model stores P-wave velocity in km/sec but we want to integrate 1/velocity along the
354  // ray path so that the integral works out to be travel time in km/sec. // -allocatedSize is the maximum number of elements in pointIndices and weights. If this value is not
355  // big enough to hold all the values, the arrays will be freed and re-malloced with enough space
356  // to hold the required number of values, plus 25%.
357 
358  geomodel_getWeights3D(model, rayPath, radii, NULL, nPoints, LINEAR, LINEAR,
359  &pointIndices, &weights, &allocatedSize, &actualSize);
360 
361  errorCheck();
362 
363  integral = 0.;
364  for (i=0; i<actualSize; ++i)
365  integral += weights[i]/geopoint_getPointValue(pointMap, pointIndices[i], attribute);
366 
367  sumWeights = 0;
368 
369  // loop over all the points in the model that were touched by rayPath
370  // and print out the pointIndex, the associated weight, the lat,lon,depth of the grid point,
371  // the p-wave velocity at the grid point, and the [vertex,layer,node] of the grid point.
372  printf("pointIndex weight lat lon depth vp [vtx, layer, node]\n");
373  for (i=0; i<actualSize; ++i)
374  {
375  char* latLonStr = geopoint_getPointLatLonString(pointMap, pointIndices[i]);
376  printf("%10d %10.6f %s %6.1f %5.2f [%5d, %1d, %1d]\n", pointIndices[i], weights[i],
377  latLonStr,
378  geopoint_getPointDepth(pointMap, pointIndices[i]),
379  geopoint_getPointValue(pointMap, pointIndices[i], attribute),
380  geopoint_getVertexIndex(pointMap, pointIndices[i]),
381  geopoint_getLayerIndex(pointMap, pointIndices[i]),
382  geopoint_getNodeIndex(pointMap, pointIndices[i])
383  );
384  sumWeights += weights[i];
385  free(latLonStr);
386  }
387  printf("\n");
388 
389  printf("requestedDelta = %1.6f degrees\n", requestedDelta * RAD_TO_DEG);
390  printf("actualDelta = %1.6f degrees\n", actualDelta * RAD_TO_DEG);
391  printf("\n");
392 
393  printf("integral = %1.6f sec\n", integral);
394  printf("sumWeights = %1.6f km\n", sumWeights);
395  printf("distance*radius = %1.6f km\n", geoutils_angle(pointA, pointB) * radii[0]);
396  printf("average velocity = %1.6f km/sec\n", sumWeights/integral);
397 
398  printf("\n");
399  printf("actualSize, allocatedSize = %d / %d\n", actualSize, allocatedSize);
400 
401  errorCheck();
402 
403  // free the memory assigned to local variables.
404  for (i=0; i<nPoints; ++i)
405  free(rayPath[i]);
406 
407  free(rayPath);
408  rayPath = NULL;
409  free(radii);
410  radii = NULL;
411  free(pointIndices);
412  pointIndices = NULL;
413  free(weights);
414  weights = NULL;
415 
416 
417  // free the memory allocated for the c GeoTessPositionC wrapper
418  geoposition_destroy(position);
419 
420  // free the memory allocated to the C GeoTessMetaDataC wrapper.
421  geometadata_destroy(meta);
422 
423  // free the memory allocated to the C PointMapC wrapper.
424  geopoint_destroy(pointMap);
425 
426  // free the memory allocated to the C GeoTessModelC wrapper.
427  geomodel_destroy(model);
428 
429  errorCheck();
430 
431  verticesSize = 0;
432  neighborsSize = 0;
433 
434  // instantiate a Grid and load a uniform, 16 degree grid from file
435 // grid = geogrid_create1();
436 // geogrid_loadGrid(grid, "/Users/sballar/Documents/workspace_gmp/GeoTessModels/geotess_grid_16000.geotess");
437 
438  errorCheck();
439 
440  tessId = 0; // you only have one tessellation, which has index 0
441 
442  // find the index of the last level of the specified tessellation.
443  // Just for fun, you could try smaller levels to see what effect if has on the output.
444  levelId = geogrid_getNLevelsTess(grid, tessId)-1;
445 
446  errorCheck();
447 
448  printf("Index of last level on tessellation %d is %d\n\n", tessId, levelId);
449 
450  // get the indices of the all the vertices that are connected by triangles on the specified
451  // tessellation and level.
452  geogrid_getVertexIndices(grid, tessId, levelId, &vertices, &nVertices, &verticesSize);
453 
454  errorCheck();
455 
456  printf("There are %d connected vertices\n\n", nVertices);
457 
458  // loop over all the connected vertices
459  for (vid=0; vid<nVertices; vid += 10000)
460  {
461  // get the indices of the vertices that are connected to the current vertex by a single triangle edge.
462  // geogrid assumes that vertices is unitialized on input. It does not free the memory. It simply
463  // malloc's the required amount of memory for the vertex ids.
464  geogrid_getVertexNeighbors(grid, tessId, levelId, vertices[vid], &neighbors, &size, &neighborsSize);
465 
466  errorCheck();
467 
468  // do what you will with neighbors.
469  printf("vertex %6d neighbors:", vertices[vid]);
470  for (i=0; i<size; ++i)
471  printf(" %5d", neighbors[i]);
472 
473  printf(" Edge lengths in deg:");
474  for (i=0; i<size; ++i)
475  printf(" %5.2f", geoutils_angleDegrees(
476  geogrid_getVertex(grid, vertices[vid]),
477  geogrid_getVertex(grid, neighbors[i])));
478 
479  printf("\n");
480 
481  // free the memory allocated for the neighbors array.
482  // This is not a very sophisticated memory management scheme. This will be improved
483  // in future versions of the CShell interface.
484  }
485 
486  errorCheck();
487 
488  free(neighbors);
489  free(vertices);
490 
491  // free the grid, and also delete the wrapped C++ GeoTessGrid object. We want to delete
492  // the C++ object because in this simple application, no one else has a reference to it.
493  // In future versions of the CShell, the second parameter will be gone because the C++
494  // GeoTessGrid object implements reference counting and hence knows when it needs to be
495  // deleted. The C applications won't have to think about that anymore.
496  geogrid_destroy(grid);
497 
498  errorCheck();
499 
500  return 0;
501 }
main
int main(int argc, char **argv)
Definition: TestCrust20.c:61
len
#define len
Definition: TestCrust20.c:48
RAD_TO_DEG
#define RAD_TO_DEG
Definition: TestCrust20.c:50
errorCheck
void errorCheck()
Definition: TestCrust20.c:54
DEG_TO_RAD
#define DEG_TO_RAD
Definition: TestCrust20.c:52
AK135Model::radii
float radii[7][50]
Definition: PopulateModel3D.c:61