43 #include <curl/curl.h>
51 #include "Structure.h"
73 static string ugrSyntax =
74 "ugr5(dim:int32, rangeVariable:string, [rangeVariable:string, ... ] condition:string)";
79 struct UgridRestrictArgs {
81 vector<libdap::Array *> rangeVars;
82 string filterExpression;
91 static void addRangeVar(DDS *dds, libdap::Array *rangeVar, map<
string, vector<MeshDataVariable *> *> *rangeVariables) {
97 BaseType *meshVar = dds->var(meshVarName);
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);
108 vector<MeshDataVariable *> *requestedRangeVarsForMesh;
109 map<string, vector<MeshDataVariable *> *>::iterator mit = rangeVariables->find(meshVarName);
110 if(mit == rangeVariables->end()){
112 BESDEBUG(
"ugrid",
"addRangeVar() - MeshTopology object for '" << meshVarName <<
"' does NOT exist. Getting a 'new' one... " << endl);
114 requestedRangeVarsForMesh =
new vector<MeshDataVariable *>();
115 (*rangeVariables)[meshVarName] = requestedRangeVarsForMesh;
119 BESDEBUG(
"ugrid",
"addRangeVar() - MeshTopology object for '" << meshVarName <<
"' exists. Retrieving... " << endl);
120 requestedRangeVarsForMesh = mit->second;
123 requestedRangeVarsForMesh->push_back(mdv);
130 static UgridRestrictArgs processUgrArgs(
int argc, BaseType *argv[]) {
132 BESDEBUG(
"ugrid",
"processUgrArgs() - BEGIN" << endl);
134 UgridRestrictArgs args;
135 args.rangeVars = vector<libdap::Array *>();
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)");
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 "
155 args.dimension = (
locationType) dynamic_cast<Int32&>(*argv[0]).value();
156 BESDEBUG(
"ugrid",
"args.dimension: " << libdap::long_to_string(args.dimension) << endl);
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 "
167 args.filterExpression =
dynamic_cast<Str&
>(*bt).value();
168 BESDEBUG(
"ugrid",
"args.filterExpression: '" << args.filterExpression <<
"' (AS RECEIVED)" << endl);
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);
184 for (
int i = 1; i < (argc - 1); 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 "
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());
198 args.rangeVars.push_back(newRangeVar);
201 BESDEBUG(
"ugrid",
"processUgrArgs() - END" << endl);
208 static string arrayState(libdap::Array *dapArray,
string indent){
210 libdap::Array::Dim_iter thisDim;
211 stringstream arrayState;
213 arrayState << indent <<
"dapArray: '" << dapArray->name() <<
"' " ;
214 arrayState <<
"type: '" << dapArray->type_name( ) <<
"' " ;
216 arrayState <<
"read(): " << dapArray->read() <<
" ";
217 arrayState <<
"read_p(): " << dapArray->read_p() <<
" ";
220 for(thisDim= dapArray->dim_begin(); thisDim!=dapArray->dim_end() ;thisDim++){
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) <<
" ";
228 return arrayState.str();
232 static void copyUsingSubsetIndex(libdap::Array *sourceArray, vector<unsigned int> *subsetIndex,
void *result){
233 BESDEBUG(
"ugrid",
"ugrid::copyUsingIndex() - BEGIN" << endl);
235 switch (sourceArray->var()->type()) {
237 sourceArray->value(subsetIndex, (dods_byte *)result);
240 sourceArray->value(subsetIndex, (dods_uint16 *)result);
243 sourceArray->value(subsetIndex, (dods_int16 *)result);
246 sourceArray->value(subsetIndex, (dods_uint32 *)result);
249 sourceArray->value(subsetIndex, (dods_int32 *)result);
253 sourceArray->value(subsetIndex, (dods_float32 *)result);
256 sourceArray->value(subsetIndex, (dods_float64 *)result);
260 throw InternalErr(__FILE__, __LINE__,
261 "ugrid::hgr5::copyUsingSubsetIndex() - Unknown DAP type encountered.");
264 BESDEBUG(
"ugrid",
"ugrid::copyUsingIndex() - END" << endl);
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);
273 for(
unsigned int i=0; i<index->size() ; ++i){
274 s << ((i>0)?
", ":
" ");
278 BESDEBUG(
"ugrid",
"indexToString() - END"<< endl);
289 static void rDAWorker(
MeshDataVariable *mdv, libdap::Array::Dim_iter thisDim, vector<unsigned int> *slab_subset_index,
294 BESDEBUG(
"ugrid",
"rDAWorker() - slab_subset_index" << vectorToString(slab_subset_index) <<
" size: "
295 << libdap::long_to_string(slab_subset_index->size()) << endl);
301 BESDEBUG(
"ugrid",
"rdaWorker() - thisDim: '" << dapArray->dimension_name(thisDim) <<
"'" << endl);
302 BESDEBUG(
"ugrid",
"rdaWorker() - locationCoordinateDim: '" << dapArray->dimension_name(locationCoordinateDim) <<
"'" << endl);
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);
309 BESDEBUG(
"ugrid",
"rdaWorker() - array state: " << arrayState(dapArray,
" "));
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);
317 dapArray->add_constraint(thisDim, start, stride, stop);
320 BESDEBUG(
"ugrid",
"rdaWorker() - Found locationCoordinateDim" << endl);
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.";
325 throw Error(malformed_expr, msg);
328 BESDEBUG(
"ugrid",
"rdaWorker() - Arrived At Last Dimension" << endl);
330 dapArray->set_read_p(
false);
332 BESDEBUG(
"ugrid",
"rdaWorker() - dap array: " << arrayState(dapArray,
" "));
334 vector<unsigned int> lastDimHyperSlabLocation;
335 NDimensionalArray::retrieveLastDimHyperSlabLocationFromConstrainedArrray(dapArray, &lastDimHyperSlabLocation);
337 BESDEBUG(
"ugrid",
"rdaWorker() - lastDimHyperSlabLocation: "
338 << NDimensionalArray::vectorToIndices(&lastDimHyperSlabLocation) << endl);
348 copyUsingSubsetIndex(dapArray, slab_subset_index, slab);
359 static libdap::Array *restrictRangeVariableByOneDHyperSlab(
361 vector<unsigned int> *slab_subset_index
364 long restrictedSlabSize = slab_subset_index->size();
366 BESDEBUG(
"ugrid",
"restrictRangeVariableByOneDHyperSlab() - slab_subset_index"<< vectorToString(slab_subset_index) <<
367 " size: " << libdap::long_to_string(restrictedSlabSize) << endl);
369 libdap::Array *sourceDapArray = mdv->
getDapArray();
371 BESDEBUG(
"ugrid",
"restrictDapArrayByOneDHyperSlab() - locationCoordinateDim: '" <<
380 vector<unsigned int> resultArrayShape(sourceDapArray->dimensions(
true));
384 for(
unsigned int i=0; i< resultArrayShape.size(); i++){
385 msg <<
"[" << resultArrayShape[i] <<
"]";
387 BESDEBUG(
"ugrid",
"restrictDapArrayByOneDHyperSlab() - Constrained source array shape" << msg.str() << endl);
393 resultArrayShape[sourceDapArray->dimensions(
true) - 1] = restrictedSlabSize;
394 libdap::Type dapType = sourceDapArray->var()->type();
397 BESDEBUG(
"ugrid",
"restrictDapArrayByOneDHyperSlab() - UGrid restricted HyperSlab has "<< restrictedSlabSize <<
" elements." << endl);
398 BESDEBUG(
"ugrid",
"restrictDapArrayByOneDHyperSlab() - Array is of type '"<< libdap::type_name(dapType) <<
"'" << endl);
400 for(
unsigned int i=0; i< resultArrayShape.size(); i++){
401 msg <<
"[" << resultArrayShape[i] <<
"]";
403 BESDEBUG(
"ugrid",
"restrictDapArrayByOneDHyperSlab() - resultArrayShape" << msg.str() << endl);
404 msg.str(std::string());
410 rDAWorker(mdv, sourceDapArray->dim_begin(), slab_subset_index, result);
413 libdap::Array *resultDapArray = result->
getArray(sourceDapArray);
419 return resultDapArray;
439 void ugr5(
int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
441 BESDEBUG(
"ugrid",
"ugr5() - BEGIN" << endl);
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>";
449 Str *response =
new Str(
"info");
450 response->set_value(info);
456 UgridRestrictArgs args = processUgrArgs(argc, argv);
461 map<string, vector<MeshDataVariable *> *> *meshToRangeVarsMap =
new map<string, vector<MeshDataVariable *> *>();
464 vector<libdap::Array *>::iterator it;
465 for (it = args.rangeVars.begin(); it != args.rangeVars.end(); ++it) {
466 addRangeVar(&dds, *it, meshToRangeVarsMap);
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);
483 Structure *dapResult =
new Structure(
"ugr_result");
489 vector<MeshDataVariable *>::iterator rvit;
490 map<string, vector<MeshDataVariable *> *>::iterator mit;
491 for (mit = meshToRangeVarsMap->begin(); mit != meshToRangeVarsMap->end(); ++mit) {
493 string meshVariableName = mit->first;
494 vector<MeshDataVariable *> *requestedRangeVarsForMesh = mit->second;
496 vector<BaseType *> dapResults;
501 BESDEBUG(
"ugrid",
"ugr5() - Adding restricted mesh_topology structure for mesh '" << meshVariableName <<
"' to DAP response." << endl);
504 tdmt->
init(meshVariableName, &dds);
512 vector<vector<unsigned int> *> location_subset_indices(3);
515 BESDEBUG(
"ugrid",
"ugr5() - there are "<< nodeResultSize <<
" nodes in the subset." << endl);
516 vector<unsigned int> node_subset_index(nodeResultSize);
517 if(nodeResultSize>0){
520 location_subset_indices[
node] = &node_subset_index;
522 BESDEBUG(
"ugrid",
"ugr5() - node_subset_index"<< vectorToString(&node_subset_index) << endl);
526 BESDEBUG(
"ugrid",
"ugr5() - there are "<< faceResultSize <<
" faces in the subset." << endl);
527 vector<unsigned int> face_subset_index(faceResultSize);
528 if(faceResultSize > 0){
531 location_subset_indices[
face] = &face_subset_index;
532 BESDEBUG(
"ugrid",
"ugr5() - face_subset_index: "<< vectorToString(&face_subset_index) << endl);
541 BESDEBUG(
"ugrid",
"ugr5() - Restriction of mesh_topology '"<< tdmt->
getMeshVariable()->name() <<
"' structure completed." << endl);
546 for(rvit=requestedRangeVarsForMesh->begin(); rvit!=requestedRangeVarsForMesh->end(); rvit++){
549 BESDEBUG(
"ugrid",
"ugr5() - Processing MeshDataVariable '"<< mdv->
getName() <<
"' associated with rank/location: "<< mdv->
getGridLocation() << endl);
560 libdap::Array *restrictedRangeVarArray =
561 restrictRangeVariableByOneDHyperSlab(mdv, location_subset_indices[mdv->
getGridLocation()]);
563 BESDEBUG(
"ugrid",
"ugr5() - Adding resulting dapArray '"<< restrictedRangeVarArray->name() <<
"' to dapResults." << endl);
565 dapResults.push_back(restrictedRangeVarArray);
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);
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++){
590 delete requestedRangeVarsForMesh;
592 delete meshToRangeVarsMap;
599 BESDEBUG(
"ugrid",
"ugr5() - END" << endl);
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()
void buildBasicGfTopology()
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)
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.
void convertResultGridFieldStructureToDapObjects(vector< libdap::BaseType * > *results)
void ugr5(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
Subset an irregular mesh (aka unstructured grid).
void getNextLastDimensionHyperSlab(void **slab)
int getResultGridSize(locationType location)
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Identifies the location/rank/dimension that various grid components are associated with...