OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
ugr5.cc
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2002,2003,2011,2012 OPeNDAP, Inc.
7 // Authors: Nathan Potter <ndp@opendap.org>
8 // James Gallagher <jgallagher@opendap.org>
9 // Scott Moe <smeest1@gmail.com>
10 // Bill Howe <billhowe@cs.washington.edu>
11 //
12 // This library is free software; you can redistribute it and/or
13 // modify it under the terms of the GNU Lesser General Public
14 // License as published by the Free Software Foundation; either
15 // version 2.1 of the License, or (at your option) any later version.
16 //
17 // This library is distributed in the hope that it will be useful,
18 // but WITHOUT ANY WARRANTY; without even the implied warranty of
19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 // Lesser General Public License for more details.
21 //
22 // You should have received a copy of the GNU Lesser General Public
23 // License along with this library; if not, write to the Free Software
24 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 //
26 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
27 
28 // NOTE: This file is built only when the gridfields library is linked with
29 // the netcdf_handler (i.e., the handler's build is configured using the
30 // --with-gridfields=... option to the 'configure' script).
31 
32 #include "config.h"
33 
34 #include <limits.h>
35 
36 #include <cstdlib> // used by strtod()
37 #include <cerrno>
38 #include <cmath>
39 #include <iostream>
40 #include <sstream>
41 //#include <cxxabi.h>
42 
43 #include <curl/curl.h>
44 
45 #define DODS_DEBUG
46 
47 #include "BaseType.h"
48 #include "Int32.h"
49 #include "Str.h"
50 #include "Array.h"
51 #include "Structure.h"
52 #include "Error.h"
53 
54 #include "BESDebug.h"
55 #include "util.h"
56 
57 #include "ugrid_utils.h"
58 #include "MeshDataVariable.h"
59 #include "TwoDMeshTopology.h"
60 #include "NDimensionalArray.h"
61 
62 #include "ugr5.h"
63 
64 
65 using namespace std;
66 using namespace libdap;
67 
68 namespace ugrid {
69 
73 static string ugrSyntax =
74  "ugr5(dim:int32, rangeVariable:string, [rangeVariable:string, ... ] condition:string)";
75 
79 struct UgridRestrictArgs {
80  locationType dimension;
81  vector<libdap::Array *> rangeVars;
82  string filterExpression;
83 };
84 
85 
91 static void addRangeVar(DDS *dds, libdap::Array *rangeVar, map<string, vector<MeshDataVariable *> *> *rangeVariables) {
92 
94  mdv->init(rangeVar);
95  string meshVarName = mdv->getMeshName();
96 
97  BaseType *meshVar = dds->var(meshVarName);
98 
99  if(meshVar == 0){
100  string msg = "The range variable '"+mdv->getName()+"' references the mesh variable '"+meshVarName+
101  "' which cannot be located in this dataset.";
102  BESDEBUG("ugrid", "addRangeVar() - " << msg << endl);
103  throw Error(no_such_variable,msg);
104  }
105 
106 
107  // Get the rangeVariable vector for this mesh name from the map.
108  vector<MeshDataVariable *> *requestedRangeVarsForMesh;
109  map<string, vector<MeshDataVariable *> *>::iterator mit = rangeVariables->find(meshVarName);
110  if(mit == rangeVariables->end()){
111  // Not there? Make a new one.
112  BESDEBUG("ugrid", "addRangeVar() - MeshTopology object for '" << meshVarName <<"' does NOT exist. Getting a 'new' one... " << endl);
113 
114  requestedRangeVarsForMesh = new vector<MeshDataVariable *>();
115  (*rangeVariables)[meshVarName] = requestedRangeVarsForMesh;
116  }
117  else {
118  // Sweet! Found it....
119  BESDEBUG("ugrid", "addRangeVar() - MeshTopology object for '" << meshVarName <<"' exists. Retrieving... " << endl);
120  requestedRangeVarsForMesh = mit->second;
121  }
122 
123  requestedRangeVarsForMesh->push_back(mdv);
124 
125 }
126 
130 static UgridRestrictArgs processUgrArgs(int argc, BaseType *argv[]) {
131 
132  BESDEBUG( "ugrid", "processUgrArgs() - BEGIN" << endl);
133 
134  UgridRestrictArgs args;
135  args.rangeVars = vector<libdap::Array *>();
136 
137  // Check number of arguments; BESDEBUG is a macro. Use #define
138  // DODS_DEBUG to activate the debugging stuff.
139  if (argc < 3)
140  throw Error(malformed_expr,
141  "Wrong number of arguments to ugrid restrict function: "
142  + ugrSyntax + " was passed "
143  + long_to_string(argc) + " argument(s)");
144 
145  BaseType * bt;
146 
147  // ---------------------------------------------
148  // Process the first arg, which is the rank of the Restriction Clause
149  bt = argv[0];
150  if (bt->type() != dods_int32_c)
151  throw Error(malformed_expr,
152  "Wrong type for first argument, expected DAP Int32. "
153  + ugrSyntax + " was passed a/an "
154  + bt->type_name());
155  args.dimension = (locationType) dynamic_cast<Int32&>(*argv[0]).value();
156  BESDEBUG( "ugrid", "args.dimension: " << libdap::long_to_string(args.dimension) << endl);
157 
158 
159  // ---------------------------------------------
160  // Process the last argument, the relational/filter expression used to restrict the ugrid content.
161  bt = argv[argc - 1];
162  if (bt->type() != dods_str_c)
163  throw Error(malformed_expr,
164  "Wrong type for third argument, expected DAP String. "
165  + ugrSyntax + " was passed a/an "
166  + bt->type_name());
167  args.filterExpression = dynamic_cast<Str&>(*bt).value();
168  BESDEBUG( "ugrid", "args.filterExpression: '" << args.filterExpression << "' (AS RECEIVED)" << endl);
169 
170  int decodedLength;
171  CURL *curl = curl_easy_init( );
172  char *decodedFilterExpression = curl_easy_unescape(curl , args.filterExpression.c_str() , args.filterExpression.size() , &decodedLength );
173  curl_easy_cleanup(curl );
174  args.filterExpression = string(decodedFilterExpression,decodedLength);
175  BESDEBUG( "ugrid", "args.filterExpression: '" << args.filterExpression << "' (URL DECODED)" << endl);
176  curl_free(decodedFilterExpression);
177 
178  // --------------------------------------------------
179  // Process the range variables selected by the user.
180  // We know that argc>=3, because we checked so the
181  // following loop will try to find at least one rangeVar,
182  // and it won't try to process the first or last members
183  // of argv.
184  for (int i = 1; i < (argc - 1); i++) {
185  bt = argv[i];
186  if (bt->type() != dods_array_c)
187  throw Error(malformed_expr,
188  "Wrong type for second argument, expected DAP Array. "
189  + ugrSyntax + " was passed a/an "
190  + bt->type_name());
191 
192  libdap::Array *newRangeVar = dynamic_cast<libdap::Array*>(bt);
193  if (newRangeVar == 0) {
194  throw Error(malformed_expr,
195  "Wrong type for second argument. " + ugrSyntax
196  + " was passed a/an " + bt->type_name());
197  }
198  args.rangeVars.push_back(newRangeVar);
199  }
200 
201  BESDEBUG("ugrid", "processUgrArgs() - END" << endl);
202 
203  return args;
204 
205 }
206 
207 
208 static string arrayState(libdap::Array *dapArray, string indent){
209 
210  libdap::Array::Dim_iter thisDim;
211  stringstream arrayState;
212  arrayState << endl;
213  arrayState << indent << "dapArray: '" << dapArray->name() << "' " ;
214  arrayState << "type: '" << dapArray->type_name( ) << "' " ;
215 
216  arrayState << "read(): " << dapArray->read() << " ";
217  arrayState << "read_p(): " << dapArray->read_p() << " ";
218  arrayState << endl;
219 
220  for(thisDim= dapArray->dim_begin(); thisDim!=dapArray->dim_end() ;thisDim++){
221 
222  arrayState << indent << " dim: '" << dapArray->dimension_name(thisDim) << "' ";
223  arrayState << indent << " start: " << dapArray->dimension_start(thisDim) << " ";
224  arrayState << indent << " stride: " << dapArray->dimension_stride(thisDim) << " ";
225  arrayState << indent << " stop: " << dapArray->dimension_stop(thisDim) << " ";
226  arrayState << endl;
227  }
228  return arrayState.str();
229 }
230 
231 
232 static void copyUsingSubsetIndex(libdap::Array *sourceArray, vector<unsigned int> *subsetIndex, void *result){
233  BESDEBUG("ugrid", "ugrid::copyUsingIndex() - BEGIN" << endl);
234 
235  switch (sourceArray->var()->type()) {
236  case dods_byte_c:
237  sourceArray->value(subsetIndex, (dods_byte *)result);
238  break;
239  case dods_uint16_c:
240  sourceArray->value(subsetIndex, (dods_uint16 *)result);
241  break;
242  case dods_int16_c:
243  sourceArray->value(subsetIndex, (dods_int16 *)result);
244  break;
245  case dods_uint32_c:
246  sourceArray->value(subsetIndex, (dods_uint32 *)result);
247  break;
248  case dods_int32_c:
249  sourceArray->value(subsetIndex, (dods_int32 *)result);
250  break;
251 
252  case dods_float32_c:
253  sourceArray->value(subsetIndex, (dods_float32 *)result);
254  break;
255  case dods_float64_c:
256  sourceArray->value(subsetIndex, (dods_float64 *)result);
257  break;
258 
259  default:
260  throw InternalErr(__FILE__, __LINE__,
261  "ugrid::hgr5::copyUsingSubsetIndex() - Unknown DAP type encountered.");
262  }
263 
264  BESDEBUG("ugrid", "ugrid::copyUsingIndex() - END" << endl);
265 }
266 
267 static string vectorToString(vector<unsigned int> *index){
268  BESDEBUG("ugrid", "indexToString() - BEGIN"<< endl);
269  BESDEBUG("ugrid", "indexToString() - index.size(): " << libdap::long_to_string(index->size()) << endl);
270  stringstream s;
271  s << "[";
272 
273  for(unsigned int i=0; i<index->size() ; ++i){
274  s << ((i>0)?", ":" ");
275  s << (*index)[i];
276  }
277  s << "]";
278  BESDEBUG("ugrid", "indexToString() - END"<< endl);
279 
280  return s.str();
281 }
282 
283 
284 
285 
289 static void rDAWorker(MeshDataVariable *mdv, libdap::Array::Dim_iter thisDim, vector<unsigned int> *slab_subset_index,
290  NDimensionalArray *results)
291 {
292  libdap::Array *dapArray = mdv->getDapArray();
293 
294  BESDEBUG("ugrid", "rDAWorker() - slab_subset_index" << vectorToString(slab_subset_index) << " size: "
295  << libdap::long_to_string(slab_subset_index->size()) << endl);
296 
297  // The locationCoordinateDimension is the dimension of the array that is associated with the ugrid "rank" - e.g. it is the
298  // dimension that ties the variable to the 'nodes' (rank 0) or 'edges' (rank 1) or 'faces' (rank 2) of the ugrid.
299  libdap::Array::Dim_iter locationCoordinateDim = mdv->getLocationCoordinateDimension();
300 
301  BESDEBUG("ugrid", "rdaWorker() - thisDim: '" << dapArray->dimension_name(thisDim) << "'" << endl);
302  BESDEBUG("ugrid", "rdaWorker() - locationCoordinateDim: '" << dapArray->dimension_name(locationCoordinateDim) << "'" << endl);
303  // locationCoordinateDim is, e.g., 'nodes'. jhrg 10/25/13
304  if (thisDim != locationCoordinateDim) {
305  unsigned int start = dapArray->dimension_start(thisDim, true);
306  unsigned int stride = dapArray->dimension_stride(thisDim, true);
307  unsigned int stop = dapArray->dimension_stop(thisDim, true);
308 
309  BESDEBUG("ugrid", "rdaWorker() - array state: " << arrayState(dapArray, " "));
310 
311  for (unsigned int dimIndex = start; dimIndex <= stop; dimIndex += stride) {
312  dapArray->add_constraint(thisDim, dimIndex, 1, dimIndex);
313  rDAWorker(mdv, thisDim + 1, slab_subset_index, results);
314  }
315 
316  // Reset the constraint for this dimension.
317  dapArray->add_constraint(thisDim, start, stride, stop);
318  }
319  else {
320  BESDEBUG("ugrid", "rdaWorker() - Found locationCoordinateDim" << endl);
321 
322  if ((thisDim + 1) != dapArray->dim_end()) {
323  string msg = "rDAWorker() - The location coordinate dimension is not the last dimension in the array. Hyperslab subsetting of this dimension is not supported.";
324  BESDEBUG("ugrid", msg << endl);
325  throw Error(malformed_expr, msg);
326  }
327 
328  BESDEBUG("ugrid", "rdaWorker() - Arrived At Last Dimension" << endl);
329 
330  dapArray->set_read_p(false);
331 
332  BESDEBUG("ugrid", "rdaWorker() - dap array: " << arrayState(dapArray, " "));
333 
334  vector<unsigned int> lastDimHyperSlabLocation;
335  NDimensionalArray::retrieveLastDimHyperSlabLocationFromConstrainedArrray(dapArray, &lastDimHyperSlabLocation);
336 
337  BESDEBUG("ugrid", "rdaWorker() - lastDimHyperSlabLocation: "
338  << NDimensionalArray::vectorToIndices(&lastDimHyperSlabLocation) << endl);
339 
340  // unused. 4/7/14 jhrg. unsigned int elementCount;
341 
342  void *slab;
343  //results->getLastDimensionHyperSlab(&lastDimHyperSlabLocation, &slab, &elementCount);
344  results->getNextLastDimensionHyperSlab(&slab);
345 
346  dapArray->read();
347 
348  copyUsingSubsetIndex(dapArray, slab_subset_index, slab);
349  }
350 }
351 
359 static libdap::Array *restrictRangeVariableByOneDHyperSlab(
360  MeshDataVariable *mdv,
361  vector<unsigned int> *slab_subset_index
362  ){
363 
364  long restrictedSlabSize = slab_subset_index->size();
365 
366  BESDEBUG("ugrid", "restrictRangeVariableByOneDHyperSlab() - slab_subset_index"<< vectorToString(slab_subset_index) <<
367  " size: " << libdap::long_to_string(restrictedSlabSize) << endl);
368 
369  libdap::Array *sourceDapArray = mdv->getDapArray();
370 
371  BESDEBUG("ugrid", "restrictDapArrayByOneDHyperSlab() - locationCoordinateDim: '" <<
372  sourceDapArray->dimension_name(mdv->getLocationCoordinateDimension()) << "'" << endl);
373 
374  // We want the manipulate the Array's Dimensions so that only a single dimensioned slab of the location coordinate dimension
375  // is read at a time. We need to cache the original constrained dimensions so that we can build the correct collection of
376  // location coordinate dimension slabs.
377 
378  // Now we need to compute the shape of the final subset result array from the source range variable array and the slab subset.
379  // What's the shape of the source array with any constraint applied?
380  vector<unsigned int> resultArrayShape(sourceDapArray->dimensions(true));
381  NDimensionalArray::computeConstrainedShape(sourceDapArray, &resultArrayShape );
382 
383  stringstream msg;
384  for(unsigned int i=0; i< resultArrayShape.size(); i++){
385  msg << "[" << resultArrayShape[i] << "]";
386  }
387  BESDEBUG("ugrid", "restrictDapArrayByOneDHyperSlab() - Constrained source array shape" << msg.str() << endl);
388  msg.str("");
389 
390  // Now, we know that the result array has a last dimension slab size determined by the slab_subset_index (whichwas made by the ugrid sub-setting),
391  // so we make the result array shape reflect that
392 
393  resultArrayShape[sourceDapArray->dimensions(true) - 1] = restrictedSlabSize; // jhrg 10/25/13 resultArrayShape.last() = ...
394  libdap::Type dapType = sourceDapArray->var()->type();
395 
396 
397  BESDEBUG("ugrid", "restrictDapArrayByOneDHyperSlab() - UGrid restricted HyperSlab has "<< restrictedSlabSize << " elements." << endl);
398  BESDEBUG("ugrid", "restrictDapArrayByOneDHyperSlab() - Array is of type '"<< libdap::type_name(dapType) << "'" << endl);
399 
400  for(unsigned int i=0; i< resultArrayShape.size(); i++){
401  msg << "[" << resultArrayShape[i] << "]";
402  }
403  BESDEBUG("ugrid", "restrictDapArrayByOneDHyperSlab() - resultArrayShape" << msg.str() << endl);
404  msg.str(std::string());
405 
406  // Now we make a new NDimensionalArray instance that we will use to hold the results.
407  NDimensionalArray *result = new NDimensionalArray(&resultArrayShape, dapType);
408 
409  // And we pass that along with other stuff into the recursive rDAWorker that's going to go get all the stuff
410  rDAWorker(mdv, sourceDapArray->dim_begin(), slab_subset_index, result);
411 
412  // And now that the recursion we grab have the NDimensionalArray cough up the rteuslt as a libdap::Array
413  libdap::Array *resultDapArray = result->getArray(sourceDapArray);
414 
415  // Delete the NDimensionalArray
416  delete result;
417 
418  // Return the result as libdap:Array
419  return resultDapArray;
420 }
421 
439 void ugr5(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
440 {
441  BESDEBUG("ugrid", "ugr5() - BEGIN" << endl);
442 
443  string info = string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
444  + "<function name=\"ugr5\" version=\"0.1\">\n"
445  + "Server function for Unstructured grid operations.\n" + "usage: "
446  + ugrSyntax + "\n"+ "</function>";
447 
448  if (argc == 0) {
449  Str *response = new Str("info");
450  response->set_value(info);
451  *btpp = response;
452  return;
453  }
454 
455  // Process and QC the arguments
456  UgridRestrictArgs args = processUgrArgs(argc, argv);
457 
458  // Each range variable is associated with a "mesh" i.e. a mesh topology variable. Since there may be more than one mesh in a
459  // dataset, and the user may request more than one range variable for each mesh we need to sift through the list of requested
460  // range variables and organize them by mesh topology variable name.
461  map<string, vector<MeshDataVariable *> *> *meshToRangeVarsMap = new map<string, vector<MeshDataVariable *> *>();
462 
463  // For every Range variable in the arguments list, locate it and ingest it.
464  vector<libdap::Array *>::iterator it;
465  for (it = args.rangeVars.begin(); it != args.rangeVars.end(); ++it) {
466  addRangeVar(&dds, *it, meshToRangeVarsMap);
467  }
468  BESDEBUG("ugrid", "ugr5() - The user requested "<< args.rangeVars.size() << " range data variables." << endl);
469  BESDEBUG("ugrid", "ugr5() - The user's request referenced "<< meshToRangeVarsMap->size() << " mesh topology variables." << endl);
470 
471  // ----------------------------------
472  // OK, so up to this point we have not read any data from the data set, but we have QC'd the inputs and verified that
473  // it looks like the request is consistent with the semantics of the dataset.
474  // Now it's time to read some data and pack it into the GridFields library...
475 
476 
477  // TODO This returns a single structure but it would make better sense to the
478  // world if it could return a vector of objects and have them appear at the
479  // top level of the DDS.
480  // FIXME fix the names of the variables in the mesh_topology attributes
481  // If the server side function can be made to return a DDS or a collection of BaseType's then the
482  // names won't change and the original mesh_topology variable and it's metadata will be valid
483  Structure *dapResult = new Structure("ugr_result");
484 
485 
486  // Since we only want each ugrid structure to appear in the results one time (cause otherwise we might be trying to add
487  // the same variables with the same names to the result multiple times.) we grind on this by iterating over the
488  // names of the mesh topology names.
489  vector<MeshDataVariable *>::iterator rvit;
490  map<string, vector<MeshDataVariable *> *>::iterator mit;
491  for (mit = meshToRangeVarsMap->begin(); mit != meshToRangeVarsMap->end(); ++mit) {
492 
493  string meshVariableName = mit->first;
494  vector<MeshDataVariable *> *requestedRangeVarsForMesh = mit->second;
495 
496  vector<BaseType *> dapResults;
497 
498  // Building the restricted TwoDMeshTopology without adding any range variables and then converting the result
499  // Grid field to Dap Objects should return all of the Ugrid structural stuff - mesh variable, node coordinate variables,
500  // face and edge coordinate variables if present.
501  BESDEBUG("ugrid", "ugr5() - Adding restricted mesh_topology structure for mesh '" << meshVariableName << "' to DAP response." << endl);
502 
503  TwoDMeshTopology *tdmt = new TwoDMeshTopology();
504  tdmt->init(meshVariableName, &dds);
505 
506  tdmt->buildBasicGfTopology();
507  tdmt->addIndexVariable(node);
508  tdmt->addIndexVariable(face);
509  tdmt->applyRestrictOperator(args.dimension, args.filterExpression);
510 
511  // 3: because there are nodes (rank = 0), edges (rank = 1), and faces (rank = 2). jhrg 10/25/13
512  vector<vector<unsigned int> *> location_subset_indices(3);
513 
514  long nodeResultSize = tdmt->getResultGridSize(node);
515  BESDEBUG("ugrid", "ugr5() - there are "<< nodeResultSize << " nodes in the subset." << endl);
516  vector<unsigned int> node_subset_index(nodeResultSize);
517  if(nodeResultSize>0){
518  tdmt->getResultIndex(node, &node_subset_index[0]);
519  }
520  location_subset_indices[node] = &node_subset_index;
521 
522  BESDEBUG("ugrid", "ugr5() - node_subset_index"<< vectorToString(&node_subset_index) << endl);
523 
524 
525  long faceResultSize = tdmt->getResultGridSize(face);
526  BESDEBUG("ugrid", "ugr5() - there are "<< faceResultSize << " faces in the subset." << endl);
527  vector<unsigned int> face_subset_index(faceResultSize);
528  if(faceResultSize > 0){
529  tdmt->getResultIndex(face, &face_subset_index[0]);
530  }
531  location_subset_indices[face] = &face_subset_index;
532  BESDEBUG("ugrid", "ugr5() - face_subset_index: "<< vectorToString(&face_subset_index) << endl);
533 
534 
535 
536  // This gets all the stuff that's attached to the grid - which at this point does not include the range variables but does include the
537  // index variable. good enough for now but need to drop the index....
539 
540 
541  BESDEBUG("ugrid", "ugr5() - Restriction of mesh_topology '"<< tdmt->getMeshVariable()->name() << "' structure completed." << endl);
542 
543  // now that we have the mesh topology variable we are going to look at each of the requested
544  // range variables (aka MeshDataVariable instances) and we're going to subset that using the
545  // gridfields library and add its subset version to the results.
546  for(rvit=requestedRangeVarsForMesh->begin(); rvit!=requestedRangeVarsForMesh->end(); rvit++){
547  MeshDataVariable *mdv = *rvit;
548 
549  BESDEBUG("ugrid", "ugr5() - Processing MeshDataVariable '"<< mdv->getName() << "' associated with rank/location: "<< mdv->getGridLocation() << endl);
550 
551 
553 
554 
555 
560  libdap::Array *restrictedRangeVarArray =
561  restrictRangeVariableByOneDHyperSlab(mdv, location_subset_indices[mdv->getGridLocation()]);
562 
563  BESDEBUG("ugrid", "ugr5() - Adding resulting dapArray '"<< restrictedRangeVarArray->name() << "' to dapResults." << endl);
564 
565  dapResults.push_back(restrictedRangeVarArray);
566 
567 
568  }
569 
570  delete tdmt;
571 
572 
573  BESDEBUG("ugrid", "ugr5() - Adding GF::GridField results to DAP structure " << dapResult->name() << endl);
574  for (vector<BaseType *>::iterator btIt=dapResults.begin(); btIt != dapResults.end(); ++btIt) {
575  BaseType *bt = *btIt;
576  BESDEBUG("ugrid", "ugr5() - Adding variable "<< bt->name() << " to DAP structure " << dapResult->name() << endl);
577  dapResult->add_var_nocopy(bt);
578  }
579  }
580 
581  *btpp = dapResult;
582 
583  BESDEBUG("ugrid", "ugr5() - Releasing maps and vectors..." << endl);
584  for (mit = meshToRangeVarsMap->begin(); mit != meshToRangeVarsMap->end(); ++mit) {
585  vector<MeshDataVariable *> *requestedRangeVarsForMesh = mit->second;
586  for(rvit=requestedRangeVarsForMesh->begin(); rvit!=requestedRangeVarsForMesh->end(); rvit++){
587  MeshDataVariable *mdv = *rvit;
588  delete mdv;
589  }
590  delete requestedRangeVarsForMesh;
591  }
592  delete meshToRangeVarsMap;
593 
594 
595 
596 
597 
598 
599  BESDEBUG("ugrid", "ugr5() - END" << endl);
600 
601  return;
602 }
603 
604 
605 } // namespace ugrid_restrict
void applyRestrictOperator(locationType loc, string filterExpression)
libdap::BaseType * getMeshVariable()
void getResultIndex(locationType location, void *target)
void init(libdap::Array *dapArray)
libdap::Array::Dim_iter getLocationCoordinateDimension()
libdap::Array * getArray(libdap::Array *templateArray)
void init(string meshVarName, libdap::DDS *dds)
only call this from the constructor?? Seems like the thing to do, but then the constructor will be po...
void setLocationCoordinateDimension(MeshDataVariable *mdv)
STL namespace.
locationType getGridLocation()
static class NCMLUtil overview
libdap::Array * getDapArray()
void addIndexVariable(locationType location)
Adds an index variable at the gridfields rank as indicated by the passed locationType.
long computeConstrainedShape(libdap::Array *a, std::vector< unsigned int > *shape)
Compute the constrained shape of the Array and return it in a vector.
Definition: fojson_utils.cc:61
locationType
Definition: LocationType.h:31
void convertResultGridFieldStructureToDapObjects(vector< libdap::BaseType * > *results)
void ugr5(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
Subset an irregular mesh (aka unstructured grid).
Definition: ugr5.cc:439
void getNextLastDimensionHyperSlab(void **slab)
int getResultGridSize(locationType location)
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
Identifies the location/rank/dimension that various grid components are associated with...