visit-dav / visit

VisIt - Visualization and Data Analysis for Mesh-based Scientific Data
https://visit.llnl.gov
BSD 3-Clause "New" or "Revised" License
427 stars 109 forks source link

Support Engineering User's Integration Point variables via Subset Controls #2602

Open aowen87 opened 5 years ago

aowen87 commented 5 years ago

Engineering users have variables with multiple integration points. The way to think about these is that they are multi-valued variables. For example, if you have a pressure variable over all zones of a mesh, its like having, in each zone a slew of different values for pressure. Each value is computed at a slightly different position within the zone but nonetheless interpreted as the zonal value. Another way to think about these in VisIt parlance may be as array variables. Though, as I understand Chad, only one among the numerous possible values is ever used at any one time and that is different from a VisIt array variable which is kind of a VisIt vector variable on steriods. There are two groups of integration points; all those actually computed by the application and those actually written to the Mili database for visualization. We call these all integration points and available integration points. Typically, Engineering users only ever look at one of the available integration points at a time. Each integration point is like a normal VisIt variable. Its like a mutually exclusive set of variables only one of which can ever be displayed. Do Engineering users ever want to see multiple different integration points in the same plot (e.g. maybe several curve plots derived from different integration points)? The answer would effect whether subset controls (proposed below) is a suitable approach. We could treat each integration point as a sub-menu variable. So, if pressure has 5 integration points labeled 1,3,4,8,17, the plugin's PopMD method would define "pressure/ips/1", "pressure/ips/3", "pressure/ips/4", "pressure/ips/8", "pressure/ips/17". That is certainly the easiest way to think about them. However, with large numbers of integration points, this approach quickly becomes unwieldy. And, in any event, we still loose track of representing for the user the notion of all integration points. It would be better to add support for this via avtArrayMetaData variables and subset controls similarly to how species are handled. A potential space performance issue with using an avtArrayMetaData variable is that VisIt will have to request that the plugin always read all array variable components (e.g. integration points) even if the user is only every looking at one among them. We can consider optimizing this space performance issue away later though. In any event, in the subset controls window, we can present a list of all array variable components (e.g. integration points) with those not available gray'd out. The user could mutually exclusive select from among the avaialble (not gray'd out) integration points and that would effect which integration point is manipulated/displayed in the plots. In this way, integration points would behave kinda sorta like species variables, which we already handle via the subset controls window. The key distinction being that like species, integration point subsetting is really subsetting the value space (or range) of the field and not its domain whereas other subsetting functionality is subsetting the domain of a field. Its not too hard to envision cases where users might want do something like see the average of several of the available integration points. If the integration points have some reference (u,v,w) position(s) within a zone, I could envision the user wanting to specify a uvw-box and then averaging or iterating over the available integration points in that box. But, this would be an advanced feature beyond what Engineering is currently requesting. The required enhancements are somewhat involved... Enhance avtArrayMetadata to specify a map of the available components (e.g. in this case integration points) In use, the plugin would define the total number of components (e.g. integration points) (say something like 50 or 100 for number of components) and then also, optionally, specify a vector of ints of those actually available (say 1,3,4,8,17). Enhance avtArrayMetadata to specify a bool that array components should be treated mutually exclusively (e.g. only one should ever be used at a time). It is concievable that a GetVector call down to the plugin (which is used for Array variables as well as Vector varaibles) could then be enhanced for this mutually exclusive case to also specify which single component to read. This would address the space performance issue mentioned in the paragraphs above. But, this is an optimization we can defer to later if it is not easily implementable. Enhance avtGenericDatabase::GetOuput to do something like ArrayMemberSelect (similar to SpeciesSelect or EnumScalarSelect) which does the work of selecting one, mutually exclusive array component, among many available (and to choose closest if selected is not actually available). Enhance avtSILRestriction and avtSILRestrictionTraverser to handle array member selection similarly to species selection In particular, handle the mutual exclusivity of the member selection Enhance GUI for subset controls may need modest enhancement as well, probably to display the list of array members (allowing some to be grey'd out for those that are not available). If there are cases where multiple integration points need to be in the same plot, we could relax the mutual exclusivity constraint, or the user can use VisIt's expression system to define an expression involving multiple of them. In fact, now that I think about this, maybe instead of doing any of the above, the plugin just loads up such variables as Array variables (avtArrayMetaData during PopulateDatabaseMetadata) and the user just uses the [[array_decompose | http://visitsphinxusermanual.readthedocs.io/en/latest/Quantitative/Expressions.html#arrayexpressions]] expression to pick a given component (integration point).

-----------------------REDMINE MIGRATION----------------------- This ticket was migrated from Redmine. As such, not all information was able to be captured in the transition. Below is a complete record of the original redmine ticket.

Ticket number: 2602 Status: Pending Project: VisIt Tracker: Feature Priority: Normal Subject: Support Engineering User's Integration Point variables via Subset Controls Assigned to: - Category: - Target version: - Author: Mark Miller Start: 04/12/2016 Due date: % Done: 0% Estimated time: Created: 04/12/2016 07:51 pm Updated: 05/04/2018 05:06 pm Likelihood: Severity: Found in version: 2.12.3 Impact: 3 - Medium Expected Use: 3 - Occasional OS: All Support Group: GrizIt Description: Engineering users have variables with multiple integration points. The way to think about these is that they are multi-valued variables. For example, if you have a pressure variable over all zones of a mesh, its like having, in each zone a slew of different values for pressure. Each value is computed at a slightly different position within the zone but nonetheless interpreted as the zonal value. Another way to think about these in VisIt parlance may be as array variables. Though, as I understand Chad, only one among the numerous possible values is ever used at any one time and that is different from a VisIt array variable which is kind of a VisIt vector variable on steriods. There are two groups of integration points; all those actually computed by the application and those actually written to the Mili database for visualization. We call these all integration points and available integration points. Typically, Engineering users only ever look at one of the available integration points at a time. Each integration point is like a normal VisIt variable. Its like a mutually exclusive set of variables only one of which can ever be displayed. Do Engineering users ever want to see multiple different integration points in the same plot (e.g. maybe several curve plots derived from different integration points)? The answer would effect whether subset controls (proposed below) is a suitable approach. We could treat each integration point as a sub-menu variable. So, if pressure has 5 integration points labeled 1,3,4,8,17, the plugin's PopMD method would define "pressure/ips/1", "pressure/ips/3", "pressure/ips/4", "pressure/ips/8", "pressure/ips/17". That is certainly the easiest way to think about them. However, with large numbers of integration points, this approach quickly becomes unwieldy. And, in any event, we still loose track of representing for the user the notion of all integration points. It would be better to add support for this via avtArrayMetaData variables and subset controls similarly to how species are handled. A potential space performance issue with using an avtArrayMetaData variable is that VisIt will have to request that the plugin always read all array variable components (e.g. integration points) even if the user is only every looking at one among them. We can consider optimizing this space performance issue away later though. In any event, in the subset controls window, we can present a list of all array variable components (e.g. integration points) with those not available gray'd out. The user could mutually exclusive select from among the avaialble (not gray'd out) integration points and that would effect which integration point is manipulated/displayed in the plots. In this way, integration points would behave kinda sorta like species variables, which we already handle via the subset controls window. The key distinction being that like species, integration point subsetting is really subsetting the value space (or range) of the field and not its domain whereas other subsetting functionality is subsetting the domain of a field. Its not too hard to envision cases where users might want do something like see the average of several of the available integration points. If the integration points have some reference (u,v,w) position(s) within a zone, I could envision the user wanting to specify a uvw-box and then averaging or iterating over the available integration points in that box. But, this would be an advanced feature beyond what Engineering is currently requesting. The required enhancements are somewhat involved... Enhance avtArrayMetadata to specify a map of the available components (e.g. in this case integration points) In use, the plugin would define the total number of components (e.g. integration points) (say something like 50 or 100 for number of components) and then also, optionally, specify a vector of ints of those actually available (say 1,3,4,8,17). Enhance avtArrayMetadata to specify a bool that array components should be treated mutually exclusively (e.g. only one should ever be used at a time). It is concievable that a GetVector call down to the plugin (which is used for Array variables as well as Vector varaibles) could then be enhanced for this mutually exclusive case to also specify which single component to read. This would address the space performance issue mentioned in the paragraphs above. But, this is an optimization we can defer to later if it is not easily implementable. Enhance avtGenericDatabase::GetOuput to do something like ArrayMemberSelect (similar to SpeciesSelect or EnumScalarSelect) which does the work of selecting one, mutually exclusive array component, among many available (and to choose closest if selected is not actually available). Enhance avtSILRestriction and avtSILRestrictionTraverser to handle array member selection similarly to species selection In particular, handle the mutual exclusivity of the member selection Enhance GUI for subset controls may need modest enhancement as well, probably to display the list of array members (allowing some to be grey'd out for those that are not available). If there are cases where multiple integration points need to be in the same plot, we could relax the mutual exclusivity constraint, or the user can use VisIt's expression system to define an expression involving multiple of them. In fact, now that I think about this, maybe instead of doing any of the above, the plugin just loads up such variables as Array variables (avtArrayMetaData during PopulateDatabaseMetadata) and the user just uses the [[array_decompose | http://visitsphinxusermanual.readthedocs.io/en/latest/Quantitative/Expressions.html#arrayexpressions]] expression to pick a given component (integration point).

Comments: GrizIt can then affect integration point control by the array_decompose() expression. Each time the integration point needs to be changed, GrizIt would redefine the expression and forceredraw of any plots involving it (or all plots).

markcmiller86 commented 5 years ago

Just capturing here code-snipit I used to verify an enhancement I made to the array_decompose expression function to support plotting the closest integration point to a given point id.

The code below was a hack to the (old) Mili plugin to test an example of handling Mili integration points as VisIt array variables. In this hacked example, I was spoofing four integration points actually stored in the database with ids, 2, 16, 29 and 77. The plugin created an Array variable with component names ip2, ip16, ip26 and ip77.

I then created an expression, array_decompose("ArrayVar", 7) (note that 7 is not one of the stored integration point ids. But, the logic I added to the array_decmpose expression function will map this number to the closest integration point in absolute index value which in this example mapped to component named "ip2".

+vtkDataArray*
+avtMiliFileFormat::GetArrayVar(int ts, int dom)
+{
+    int mesh_id = 0;
+    int myints[] = {2,16,29,77};
+    std::vector<int> avail(myints, myints + sizeof(myints)/sizeof(int));
+    vtkFloatArray *rv = vtkFloatArray::New();
+    rv->SetNumberOfComponents(avail.size());
+    rv->SetNumberOfTuples(ncells[dom][mesh_id]);
+    for (size_t i = 0, j = 0; i < 100; i++)
+    {
+        if (std::find(avail.begin(), avail.end(), i) == avail.end())
+            continue;
+        for (size_t k = 0; k < ncells[dom][mesh_id]; k++)
+            rv->SetComponent(k, j, (float) avail[j]);
+        j++;
+    }
+    return rv;
+}

 vtkDataArray *
 avtMiliFileFormat::GetVectorVar(int ts, int dom, const char *name)
 {
+    if (string(name) == "ArrayVar")
+        return GetArrayVar(ts, dom);
+
     if (!readMesh[dom])
         ReadMesh(dom);
     if (!validateVars[dom])
@@ -2358,6 +2380,19 @@
         AddMaterialToMetaData(md, matname, meshname, nmaterials[i], mnames);
         AddMaterialToMetaData(md, nofnmatname, nofnmeshname, nmaterials[i], mnames);

+        {
+            int myints[] = {2,16,29,77};
+            std::vector<int> avail(myints, myints + sizeof(myints)/sizeof(int));
+            std::vector<string> ipnames;
+            for (size_t i = 0; i < avail.size(); i++)
+            {
+                char tmp[32];
+                SNPRINTF(tmp, sizeof(tmp), "ip%d", avail[i]);
+                ipnames.push_back(tmp);
+            }
+            AddArrayVarToMetaData(md, "ArrayVar", ipnames, meshname, AVT_ZONECENT);
+        }
+
markcmiller86 commented 5 years ago

@aowen87 just wanted to mention you here as per our conversation earlier today.