Open grumpyinca opened 1 year ago
UML diagrams generated from the eqnset code can identify dependency relationships and thus provide an organized way to recognize an over-specified design situation.
December 8, 2022
January 1, 2023
This diagram is intended as a possible way to represent over-specified situations. It is an incomplete rough draft.
Similar to the previous Hooke'sLaw_DOF_Analysis. More complete but in a more limited subset. FDgrid1.pdf FDgrid1.xlsx
Updated per Jan 14, 2023 conversation: FDgrid2.pdf FDgrid2.xlsx
updated January 16, 2023
(Includes features previously described as "Data Entry View")
Provide a data entry experience that decreases the likelihood of an over-specified design situation by selectively populating related values as the user makes entries. The notion is that alerting at the moment of first conflict will help user comprehension of the over-specification issue because yet-to-be-entered values and their dependencies are not a distraction. Similarly, perhaps the "progressive reveal" aspect of populating the value fields will also improve user comprehension of dependency relationships within the full set of variables.
Add a feature to Calculator View that can optionally hide quantities / variables that are not central to specifying the design. For compression springs, this might include Weight, Cycle_Life, Safe Load and Pitch.
When Calculator view starts, all value fields are empty (blank). The optional values described above default to hidden.
The current convention of white background fill indicating input and gray background fill indicating output continues.
See the "All fields empty" entry in Notes below.
Each time the user enters a value, the code scans related* values for their initialized / uninitialized status.
It is possible that some related values cannot be calculated because other inputs are still missing (uninitialized). Those fields remain empty.
If all necessary values are available (not empty), related empty values get over-written by calculation** from the new input value.
*Related
Related values are those that affect or are affected by the user entered value. The UML diagram above is one way of determining these relationships. These are the variables pointed to in the "sets" and "refs" properties.
**Calculation
Uninitialized values may be calculated by either:
In summary, there are three ways that a value can be established:
If the relationship check determines that a newly entered value allows the calculation of a variable that has already been initialized there is a possibility of over specification. If the existing value and the new calculation are identical within "engineering precision", no further action is required. If the values differ by a greater amount, the user should be alerted. See the "Alert user to possible over-specification" entry in Notes below.
When the relationship check calculates a new value, the algorithm should check the relationships of that new value, i.e. cascaded results or recursive descent.
Some form of "input completed" indication (more visible than just all fields populated) may be desirable. One possibility is a thumbs up icon with a tooltip providing a more detailed description. Another possibility is the presence or absence of the Multi-color Feasibility Indicator. Also, the option to reveal Weight, Cycle_Life, Safe Load and Pitch can appear at this time.
Start with all fields empty.
User selects Material_Type & End_type from table (keep defaults ?)
Key:
variable name
Compute value, compare to previously initialized value, alert if sufficiently different Ref | User enters | Fields get updated | Relationship(s), Notes |
---|---|---|---|
1 | Deflect_2 | {none} | |
2 | OD_Free | {none} | |
3 | Rate | ||
3a | Force_2 | = iF(Rate, Deflect_2) | |
4 | Wire_Dia | ||
4a | {Mean_Dia} | = F(OD_Free, Wire_Dia) | |
4b | Spring_Index | = F({Mean_Dia}, Wire_Dia) | |
4c | Coils_A | = iF(OD_Free, Rate, Wire_Dia, Hot_Factor_Kh) | |
Rate |
= F({Mean_Dia}, Coils_A, Spring_Index, Torsion_Modulus) | ||
4d | Coils_T | = iF(Inactive_Coils, Coils_A) | |
4e | L_Solid | = F(Coils_T, Wire_Dia, Add_Coils_Solid) | |
4f | Stress_2 | = F({Mean_Dia}, Wire_Dia, Force_2) | |
4g | FS_2 | = F(Stress_2, Stress_Lim_Stat) | |
4h | ID_Free | = F({Mean_Dia}, Wire_Dia) | |
{Calc Input Stress_Lim_Stat is a function of Wire_Dia} | |||
{ L_Free constrained by validity. See Notes below} | |||
5 | Force_1 | ||
5a | Deflect_1 | = F(Rate, Force_1) | |
5b | L_Stroke | = iF(Deflect_2, Deflect_1) | |
5c | Stress_1 | = F({Mean_Dia}, Wire_Dia, Force_1) | |
5d | FS_1 | = F(Stress_1, Stress_Lim_Stat) | |
6 | L_Free | ||
6a | Force_Solid | = F(L_Free, Rate, L_Solid) | |
6b | Stress_Solid | = F(Force_Solid, {Mean_Dia}, Wire_Dia) | |
6c | FS_Solid | = F(Stress_Solid, Stress_Lim_Stat) | |
6d | L_1 | = F(L_Free, Deflect_1) | |
6e | L_2 | = F(L_Free, Deflect_2) |
Input completed. See "All fields populated" entry in Notes below.
Make associated UI changes (icon with tooltip, Multi-color Feasibility Indicator, enable optional quantities).
Now that input is complete, further operation of value changes, Search, Seek, etc. should resemble the legacy operation.
See "Allow the user to un-initialize a previously initialized variable" in Notes below.
All fields empty:
Related to Auto-Search:
An implementation where calculation results are determined by extracting the desired value(s) from the model after Fix & Search seems to be closely related to the previously discussed Auto-Search.
Response to "Not Feasible" Search result:
In an implementation where calculation results are determined by extracting the desired value(s) from the model after Fix & Search, a UI design challenge is encountered if Search returns "Not Feasible". Some sort of descriptive status message / alert / pop-up / tooltip is likely a first step. It seems reasonable to allow the user to enter a different value. Perhaps the system can suggest the (known to be inaccurate) value produced by Search. After that, are there other options that don't force the user to guess an appropriate value ?
Alert user to possible over-specification:
When alerting the user of a possible over specified situation, it is desirable to highlight all of the values involved. One possibility is to use the color of the background fill for the values involved. Perhaps the most recently entered value (the one that triggered the conflict alert) should get a light pink background while immediately related values get a light-yellow background.
See February 4, 2023 comment below.
Values become constrained by validity:
In this compression spring example, the value of L_Free becomes constrained by prior entries that determine solid height. Any value specified for L_Free less than the solid height is not valid. Actually, this is just a special case of the previous note entry.
Consider alternative ways to represent / communicate this situation. For example, once the still uninitialized value of L_Free becomes limited by the calculated value of L_Solid, is it reasonable to put (light gray?) text in the L_Free field that says: "> x.xx" where x.xx is the value of L_solid ? Large values of L_Free will cause a constraint on FS_Solid and perhaps FS_2 to be violated. Perhaps it would be best to place an info icon ("i" in blue circle) with tooltip into that field. The tooltip can provide the necessary detail including the upper and lower bounds for L_Free. Also, the same information can appear in the Calculator View Variable Value Input dialog box.
All fields populated:
Allow the user to un-initialize a previously initialized variable:
Even after input is completed, the user should be able to blank a value in order to return to the situation where related values cascade and alerts to possible over-specification are generated. Currently, empty or blank values are not accepted inputs. Discussion suggests that a button labeled "clear", "reset", "empty" or something similar can be provided on the Calculator View Variable Value Input dialog box.
Are there unintended consequences ?
Do we need precedence ?
There are several cases in this example where some sort of ordering is important. For example:
See branch 801.1 for a simplified Hooke's Law Plus Lengths model. Sample screen shots below of Advanced and Calculator View
Proposed structure for adding eqns objects contains refs, eqn, and sets for "Hooke's Law plus Lengths".
{
"name": "Force_1",
"eqns": [{
"eqn": null, // User input
"sets": [o.Rate, o.Deflect_1]
},
{
"refs": [o.Rate, o.Deflect_1],
"eqn": (rate, deflect_1) => {return deflect_1 * rate;}
"sets": [o.L_1]
}]
},
{
"name": "Force_2",
"eqns": [{
"eqn": null, // User input
"sets": [o.Rate, o.Deflect_2]
},
{
"refs": [o.Rate, o.Deflect_2],
"eqn": (rate, deflect_2) => {return deflect_2 * rate;}
"sets": [o.L_2]
}]
},
{
"name": "Rate",
"eqns": [{
"eqn": null, // User input
"sets": [o.Force_1, o.Deflect_1, o.Force_2, o.Deflect_2]
},
{
"refs": [o.Force_1, o.Deflect_1],
"eqn": (force_1, deflect_1) => {return force_1 / deflect_1;}
"sets": [o.L_1]
},
{
"refs": [o.Force_2, o.Deflect_2],
"eqn": (force_2, deflect_2) => {return force_2 / deflect_2;}
"sets": [o.L_2]
}]
},
{
"name": "Deflect_1",
"eqns": [{
"eqn": null, // User input
"sets": [o.Force_1, o.Rate, o.L_Free, o.L_1]
},
{
"refs": [o.Force_1, o.Rate],
"eqn": (force_1, rate) => {return force_1 / rate;}
"sets": [o.L_1]
},
{
"refs": [o.L_Free, o.L_1],
"eqn": (l_free, l_1) => {return l_free - l_1;}
"sets": [o.Rate]
}]
},
{
"name": "Deflect_2",
"eqns": [{
"eqn": null, // User input
"sets": [o.Force_2, o.Rate, o.L_Free, o.L_2]
},
{
"refs": [o.Force_2, o.Rate],
"eqn": (force_2, rate) => {return force_2 / rate;}
"sets": [o.L_2]
},
{
"refs": [o.L_Free, o.L_2],
"eqn": (l_free, l_2) => {return l_free - l_2;}
"sets": [o.Rate]
}]
},
{
"name": "L_Free",
"eqns": [{
"eqn": null, // User input
"sets": [o.L_1, o.Deflect_1, o.L_2, o.Deflect_2]
},
{
"refs": [o.L_1, o.Deflect_1],
"eqn": (l_1, deflect_1) => {return deflect_1 + l_1;}
"sets": [o.Rate]
},
{
"refs": [o.L_2, o.Deflect_2],
"eqn": (l_2, deflect_2) => {return deflect_2 + l_2;}
"sets": [o.Rate]
}]
},
{
"name": "L_1",
"eqns": [{
"eqn": null, // User input
"sets": [o.L_Free, o.Deflect_1]
},
{
"refs": [o.L_Free, o.Deflect_1],
"eqn": (l_free, deflect_1) => {return l_free - deflect_1;}
"sets": [o.Rate]
}]
},
{
"name": "L_2",
"eqns": [{
"eqn": null, // User input
"sets": [o.L_Free, o.Deflect_2]
},
{
"refs": [o.L_Free, o.Deflect_2],
"eqn": (l_free, deflect_2) => {return l_free - deflect_2;}
"sets": [o.Rate]
}]
},
Possible test cases for Hooke's Law (plus length). These are intended for the compression spring example.
Set up then enter value for L_Stroke that requires a negative value for Deflect_1. In production, there is a default constraint for Deflect_1 Min of 0.0.
Ref | User enters | Fields get updated | Relationship(s), Notes |
---|---|---|---|
1 | Force_2 = 20 | {none} | |
2 | Deflect_2 = 2 | ||
2a | Rate =10 | = Force_2 / Deflect_2 | |
3 | L_Stroke = 2.5 | {none} | Any value >2.0 will conflict with Min constraint on Deflect_1 |
Similar to above with different variables, different order.
Ref | User enters | Fields get updated | Relationship(s), Notes |
---|---|---|---|
1 | L_Free = 3.25 | {none} | |
2 | L_Stroke = 2.5 | {none} | |
3 | Force_2 = 20 | {none} | |
4 | Deflect_2 = 2.0 | conflict with Min constraint on Deflect_1 | |
4a | Rate | = Force_2 / Deflect_2 |
Still working this case
Ref | User enters | Fields get updated | Relationship(s), Notes |
---|---|---|---|
1 | Deflect_1 = .5 | {none} | |
2 | Force_1 = 10 | {none} | |
2a | Rate | = Force_1/ Deflect_1 | |
3 | L_1 = 4 | ? | L_Free gets a lower limit |
4 | L_2 = 2 | ||
4a | Deflect_2 | = ? | |
4b | Force_2 | = ? |
Originally written for the Hooke's Law example, this case has been expanded to the full Compression Spring model. Specify force & deflection at one point, force & length at the other and then learn about acceptable ranges for other variables. Try to specify L_Free.
Ref | User enters | Fields get updated | Relationship(s), Notes |
---|---|---|---|
1 | Force_1 = 10 | {none} | |
2 | Deflect_1 = .5 | ||
2a | Rate {=20} | = Force_1/ Deflect_1 | |
3 | Force_2 = 40 | ||
3a | Deflect_2 {=2} | = Force_2 / Rate | |
* | L_Stroke could be calculated by Deflect_2 - Deflect_1 | ||
4 | L_2 = 2.5 | ||
4a | L_Free {=4.5} | = Force_2 / Rate + L_2 | |
* | Any value of L_Free not = 4.5 is over-specified | ||
4b | L_1 {=4.0} | = L_Free - Deflect_1 | |
4c | L_Stroke {=1.5} | = L_1 - L_2 | |
5 | OD_Free = 1.0 | ||
* | OD_Free is constrained to the range 0.54 - 1.07 | ||
6 | Wire_Dia = 0.107 (Non Std) | ||
* | Wire_Dia is constrained to a narrow range | ||
6a | Stress_1 {=21826} | = s_f * Force_1 | |
6b | Stress_2 {=87303} | = s_f * Force_2 | |
6c | FS_1 {=5.974} | = Stress_Lim_Stat / Stress_1 | |
6d | FS_2 {=1.493} | = Stress_Lim_Stat / Stress_2 | |
7 | Coils_T = 15.23 | ||
* | Coils_T is constrained to a single value | ||
7a | Coils_A {=13.23} | = Coils_T - Inactive_Coils | |
7b | L_Solid {=1.63} | Wire_Dia * Coils_T + Add_Coils_Solid |
All values should be populated at this point.
Latest dependency diagram for Compression Spring without any local variables
Computed transitive closure and found that this is not what I wanted. Instead I want to find cycles.
Regarding "Alert user to possible over-specification:" in the January 12, 2023 entry above ...
Today's discussion developed the idea that if the user enters a new (and conflicting) value for an already initialized value, a pop-up could have wording along the lines of:
In order to establish a different value for {this variable}
check boxes to put one or more of these variables in Free status.
{set of variables with checkboxes}
The set of variables with checkboxes would be those variables in fixed status that are known (via sets, refs & eqns) to determine the value of the variable that the user is entering.
A context-sensitive Help button may be provided in order to clarify the issues of over-specification.
This issue is intended to document various discussions on how best to accommodate novice users that are having difficulty with over-specified design situations. While originally intended as a design discussion rather than providing a branch for code development, branches 801.1 and 792.1 have become a home for a simplified Hooke's Law Plus Lengths model.
The UML diagrams are transferred from Slack so as to provide a longer-term repository.