GeoTessCPPExamples  2.0
PopulateModel3D.cc
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 "CPPUtils.h"
37 #include "GeoTessGrid.h"
38 #include "GeoTessModel.h"
39 #include "GeoTessPosition.h"
40 #include "AK135Model.h"
41 
42 using namespace geotess;
43 
44 /**
45  * An example of populating a 3D model with data. The application
46  * loads a existing GeoTessGrid object from a file, populates it
47  * with information from the ak135 model to build a 3D version of
48  * 1D ak135 model. The resulting model has 7 layers supported by
49  * 3 multi-level tessellations. The first tessellation (index 0)
50  * supports the inner and outer core. The second tessellation
51  * supports the three mantle layers. The third and final tessellation
52  * supports the lower and upper crust.
53  * <p>
54  * The program takes one command line argument which specifies the
55  * full path to the file GeoTessModels/crust20.geotess
56  * that was delivered with the GeoTess package.
57  */
58 int main(int argc, char** argv)
59 {
60  try
61  {
62  if(argc < 2)
63  {
64  cout << "Must supply a single command line argument specifying path to the GeoTessModels directory" << endl;
65  return -1;
66  }
67 
68  string path = argv[1];
69 
70  // specify the path to the file containing the grid to be used for
71  // this test. This information was passed in as a command line
72  // argument. Grids were included in the software delivery and
73  // are available from the GeoTess website. Grids can also be
74  // constructed using the GeoTessBuilder software. The grid
75  // required for this example is in a file called
76  // small_model_grid.ascii which is in the GeoTessModels
77  // directory delivered with GeoTess.
78  string inputGridFileName = CPPUtils::insertPathSeparator(path, "small_model_grid.ascii");
79 
80  cout << "Example that illustrates how to populate a 3D model." << endl << endl;
81 
82  // Create a MetaData object in which we can specify information
83  // needed for model construction.
84  GeoTessMetaData* metaData = new GeoTessMetaData();
85 
86  // specify the ellipsoid that is to be used when interacting with this model.
87  // This call is really unnecessary here because WGS84 is the default,
88  // but other options are possible.
89  metaData->setEarthShape("WGS84");
90 
91  // Specify a description of the model. This information is not
92  // processed in any way by GeoTess. It is carried around for
93  // information purposes.
94  metaData->setDescription("Simple example of populating a 3D GeoTess model\ncomprised of 3 multi-level tessellations\nauthor: Sandy Ballard\ncontact: sballar@sandia.gov");
95 
96  // Specify a list of layer names delimited by semi-colons
97  metaData->setLayerNames("INNER_CORE; OUTER_CORE; LOWER_MANTLE; TRANSITION_ZONE; UPPER_MANTLE; LOWER_CRUST; UPPER_CRUST");
98 
99  // Specify the relationship between grid tessellations and model layers.
100  // the list has nLayers elements where each element specifies the
101  // index of the multilevel tessellation that supports the
102  // corresponding layer. In this example, the model has
103  // 7 layers and 3 multi-level tessellations.
104  // Layers 0 (inner core) and 1 (outer core) are
105  // supported by tessellation 0 which has 64 degree triangles (huge!)
106  // Layers 2,3 and 4 (3 mantle layer) are supported by tessellation 1
107  // which has 32 degree triangles.
108  // Layers 5 and 6 (crust) are supported by tessellation 2.
109  // which has 16 degree triangles
110  int layerTessIds[] = {0, 0, 1, 1, 1, 2, 2};
111 
112  // set the layerTessIds in the model. setLayerTessIds() must be called after
113  // setLayerNames(), not before.
114  metaData->setLayerTessIds(layerTessIds);
115 
116  // specify the names of the attributes and the units of the
117  // attributes in two Strings delimited by semi-colons.
118  metaData->setAttributes("Vp; Vs; rho", "km/sec; km/sec; g/cc");
119 
120  // specify the GeoTessDataType for the data. All attributes, in all
121  // profiles, will have the same data type. Note that this
122  // applies only to the data; radii are always stored as floats.
123  metaData->setDataType(GeoTessDataType::FLOAT);
124 
125  // specify the name of the software that is going to generate
126  // the model. This gets stored in the model for future reference.
127  metaData->setModelSoftwareVersion("GeoTessCPPExamples.PopulateModel3D 1.0.0");
128 
129  // specify the date when the model was generated. This gets
130  // stored in the model for future reference.
131  metaData->setModelGenerationDate(CpuTimer::now());
132 
133  // call a GeoTessModel constructor to build the model. This will
134  // load the grid, and initialize all the data structures to null.
135  // To be useful, we will have to populate the data structures.
136  // GeoTessModel assumes ownership of the pointer to metaData and
137  // will delete it in its destructor.
138  GeoTessModel* model = new GeoTessModel(inputGridFileName, metaData);
139 
140  // retrieve a reference to the EarthShape that should be used when interacting with
141  // this model. This object will be used to convert between geographic and geocentric
142  // coordinates, and between depth and radius.
143  EarthShape& ellipsoid = model->getEarthShape();
144 
145  // We need a source of model data that we can use to populate
146  // our new model. AK135Model is a representation of the 1D
147  // radially symmetric velocity model which we have hardcoded
148  // into this example.
149  AK135Model ak135;
150 
151  vector<vector<float> > attributeValues;
152  vector<float> radii;
153 
154  // Now we will populate the model with Profiles. At this point, the
155  // model has a 2D array of GeoTessProfile objects with dimensions
156  // nVertices x nLayers with all the elements of the array initialized
157  // to null. We will now populate the Profiles array.
158  //
159  // loop over the 7 layers of the model (inner_core, outer_core, etc)
160  for (int layer=0; layer<model->getNLayers(); ++layer)
161  {
162  // now loop over every vertex in the grid, connected and not-connected.
163  for (int vtx = 0; vtx < model->getNVertices(); ++vtx)
164  {
165  // retrieve a reference to the unit vector corresponding to the i'th vertex
166  const double* vertex = model->getGrid().getVertex(vtx);
167 
168  // find the latitude and longitude of vertex, in degrees
169  double lat = ellipsoid.getLatDegrees(vertex);
170  double lon = ellipsoid.getLonDegrees(vertex);
171 
172  // for the current vertex and layer, we need a 1D array of radii
173  // and a 2D array of attribute values (nNodes by nAttributes) that
174  // together define the distribution of model attributes (vp, vs and
175  // density) along a radial profile through this layer.
176 
177  // Note that the number of radii and number of attribute nodes
178  // are not always the same. Here are the possibilities:
179  // <br>In the crustal layers, there will be two radii and
180  // a single attribute node, indicating that vp, vs and density
181  // are constants in the profiles through crustal layers.
182  // <br>In the core and mantle, the number of radii and
183  // the number of attibute nodes will be equal, indicating
184  // that vp, vs and density vary continuously within each layer
185  // in the radial direction.
186 
187  ak135.getLayerProfile(lat, lon, layer, radii, attributeValues);
188 
189  // pass the vertexID, layer number, radii and values to
190  // the GeoTessModel. The radii and attribute values will
191  // be copied from these structures into GeoTess objects.
192  model->setProfile(vtx, layer, radii, attributeValues);
193 
194  }
195  }
196 
197  // At this point, we have a fully functional GeoTessModel object
198  // that we can work with.
199 
200  // print a bunch of information about the model to the screen.
201  cout << model->toString() << endl << endl;
202 
203  cout << "Radial profile at the south pole:" << endl;
204  cout << "Radius (km) Vp (km/sec) Vs (km/sec) Density (g/cc)" << endl;
205  cout << fixed << setprecision(3);
206  for (int layer=0; layer < model->getNLayers(); ++layer)
207  {
208  GeoTessProfile* p = model->getProfile(11, layer);
209  cout << "Layer " << layer << " " << model->getMetaData().getLayerName(layer) <<
210  " of type " << p->getType().toString() << endl;
211  for (int j=0; j<p->getNRadii(); ++j)
212  {
213  cout << setw(10) << p->getRadius(j);
214  if (j < p->getNData())
215  for (int k=0; k<model->getMetaData().getNAttributes(); ++k)
216  cout << setw(10) << p->getData(j)->getFloat(k);
217  cout << endl;
218  }
219  }
220 
221  cout << endl << endl;
222 
223  // write the model to a file. Note that before the model is
224  // written to file, a test is performed to ensure that all the layer
225  // radii are consistent. It must be true that no layer has negative
226  // thickness and that the radius of the top of each layer is equal
227  // to the radius of the bottom of the next layer, within a
228  // small tolerance. If any of these conditions are not satisfied,
229  // the model is not written and an exception is thrown.
230 
231 // string outputFile = CPPUtils::insertPathSeparator(path, "small_model.ascii");
232 // model->writeModel(outputFile, "*");
233 // cout << "model written to file: " << outputFile << endl << endl;
234 
235  // Now let's test the model by interpolating some data from it.
236 
237  // Instantiate a GeoTessPosition object, giving it a reference to the model.
238  // Specify which type of interpolation is to be used: linear or natural neighbor.
239  GeoTessPosition* position = model->getPosition(GeoTessInterpolatorType::NATURAL_NEIGHBOR);
240 
241  // set the latitude and longitude of the GeoTessPosition object. This is
242  // the position on the Earth where we want to interpolate some data.
243  double lat = 30.;
244  double lon = 90.;
245 
246  // convert the latitude and longitude into an earth-centered unit vector.
247  double v[3];
248  ellipsoid.getVectorDegrees(lat, lon, v);
249 
250  // get the index of the layer that supports the upper crust.
251  int layerID = model->getMetaData().getLayerIndex("UPPER_CRUST");
252 
253  // specify layer index and geographic position where we want to interpolate data.
254  // By calling 'setTop', the radius of the interpolation position will be set to
255  // the top of layer with index layerID.
256  position->setTop(layerID, v);
257 
258  cout << fixed << setprecision(3);
259 
260  cout << "Interpolation lat, lon, depth = "
261  << ellipsoid.getLatDegrees(position->getVector()) << " deg, "
262  << ellipsoid.getLonDegrees(position->getVector()) << " deg, "
263  << position->getDepth() << " km" << endl << endl;
264 
265 
266  // retrieve the interpolated model values at the most recent location specified
267  // in the GeoTessPostion object.
268  double vp = position->getValue(0);
269  double vs = position->getValue(1);
270  double rho = position->getValue(2);
271 
272  // Output the interpolated values
273  cout << "Interpolated vp = " << setw(6) << vp << " " << model->getMetaData().getAttributeUnit(0) << endl;
274  cout << "Interpolated vs = " << setw(6) << vs << " " << model->getMetaData().getAttributeUnit(1) << endl;
275  cout << "Interpolated rho = " << setw(6) << rho << " " << model->getMetaData().getAttributeUnit(2) << endl;
276  cout << endl;
277 
278  // print out the index of the triangle in which point resides.
279  cout << "Interpolated point resides in triangle index = " << position->getTriangle() << endl;
280 
281  // print out a table with the node indexes, node lat, node lon and
282  // interpolation coefficients for the nodes of the triangle that
283  // contains the point.
284  cout << " Node Lat Lon Coeff" << endl;
285 
286  // get the indexes of the vertices that contribute to the interpolation.
287  const vector<int>& x = position->getVertices();
288 
289  // get the interpolation coefficients used in interpolation.
290  const vector<double>& coef = position->getHorizontalCoefficients();
291 
292  const GeoTessGrid& gridnew = model->getGrid();
293  for (int j = 0; j < (int) x.size(); ++j)
294  {
295  cout << setw(6) << x[j] <<
296  setprecision(4) << setw(11) <<
297  ellipsoid.getLatDegrees(gridnew.getVertex(x[j])) <<
298  setprecision(4) << setw(11) <<
299  ellipsoid.getLonDegrees(gridnew.getVertex(x[j])) <<
300  setprecision(6) << setw(11) <<
301  coef[j] << endl;
302  }
303 
304  delete position;
305  delete model;
306 
307  cout << endl << "End of populateModel3D" << endl << endl;
308 
309  }
310  catch (const GeoTessException& ex)
311  {
312  cout << endl << ex.emessage << endl;
313  return 1;
314  }
315  catch (...)
316  {
317  cout << endl << "Unidentified error detected " << endl
318  << __FILE__ << " " << __LINE__ << endl;
319  return 2;
320  }
321  return 0;
322 }
geotess
Definition: AK135Model.h:55
main
int main(int argc, char **argv)
Definition: PopulateModel3D.cc:58
geotess::AK135Model::getLayerProfile
void getLayerProfile(const double &lat, const double &lon, const int &layer, vector< float > &r, vector< vector< float > > &nodeData)
Definition: AK135Model.h:96
geotess::AK135Model
Definition: AK135Model.h:62
AK135Model.h