using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CaeMesh; using CaeGlobals; using System.ComponentModel; using System.Xml.Linq; using System.Numerics; using System.Diagnostics.Eventing.Reader; namespace CaeResults { [Serializable] public enum DataTypeEnum { None, Scalar, Vector, Tensor } [Serializable] public enum DataStateEnum { OK, UpdateComplexMinMax, UpdateResultFieldOutput } [Serializable] public struct IDValuePair { public int Id; public float Value; } [Serializable] public class Field : NamedClass { // Variables private DataTypeEnum _dataType; private OrderedDictionary _components; private bool _complex; private DataStateEnum _dataState; // Properties public DataTypeEnum DataType { get { return _dataType == DataTypeEnum.None ? FOFieldNames.GetDataType(_name) : _dataType; } set { _dataType = value; } } public bool Complex { get { return _complex; } set { _complex = value; } } public DataStateEnum DataState { get { return _dataState; } set { _dataState = value; } } // Constructor public Field(string name) : base(name) { _components = new OrderedDictionary("Components"); // _complex = false; _dataState = DataStateEnum.OK; _dataType = DataType; } public Field(Field field) : base(field) { _components = new OrderedDictionary("Components"); foreach (var entry in field._components) _components.Add(entry.Key, new FieldComponent(entry.Value)); // copy // _dataType = field._dataType; _complex = field._complex; _dataState = field._dataState; } // Static methods public static void WriteToBinaryWriter(Field field, System.IO.BinaryWriter bw) { if (field == null) { bw.Write((int)0); } else { bw.Write((int)1); // Name bw.Write(field._name); // Components if (field._components == null) bw.Write((int)0); else { bw.Write((int)1); // bw.Write(field._components.Count); foreach (var entry in field._components) FieldComponent.WriteToBinaryWriter(entry.Value, bw); } // bw.Write(field.Complex); bw.Write((int)field.DataState); // bw.Write(field.Active); bw.Write(field.Visible); bw.Write(field.Valid); bw.Write(field.Internal); } } public static Field ReadFromBinaryReader(System.IO.BinaryReader br, int version) { int numItems; FieldComponent component; // int exists = br.ReadInt32(); if (exists == 1) { string name = br.ReadString(); Field field = new Field(name); // Components exists = br.ReadInt32(); if (exists == 1) { numItems = br.ReadInt32(); // field._components = new OrderedDictionary("Components"); for (int i = 0; i < numItems; i++) { component = FieldComponent.ReadFromBinaryReader(br, version); field._components.Add(component.Name, component); } } // if (version >= 1_004_000) { field.Complex = br.ReadBoolean(); field.DataState = (DataStateEnum)br.ReadInt32(); // field.Active = br.ReadBoolean(); field.Visible = br.ReadBoolean(); field.Valid = br.ReadBoolean(); field.Internal = br.ReadBoolean(); } return field; } return null; } // Methods public void AddComponent(FieldComponent component) { _components.Add(component.Name, component); } public void AddComponent(string name, float[] values, bool invariant = false) { _components.Add(name, new FieldComponent(name, values, invariant)); } public string[] GetComponentNames() { return _components.Keys.ToArray(); } public bool ContainsComponent(string name) { return _components.ContainsKey(name); } public bool IsComponentInvariant(string name) { return _components[name].Invariant; } public float[] GetComponentValues(string name) { if (_components.ContainsKey(name)) return _components[name].Values; else return null; } public float GetComponentAbsMax(string name) { float max = Math.Abs(_components[name].Max.Value); float min = Math.Abs(_components[name].Min.Value); return Math.Max(min, max); } public float GetComponentMax(string name) { return _components[name].Max.Value; } public int GetComponentMaxId(string name) { return _components[name].Max.Id; } public float GetComponentMin(string name) { return _components[name].Min.Value; } public int GetComponentMinId(string name) { return _components[name].Min.Id; } public void ReplaceComponent(string name, FieldComponent newComponent) { _components.Replace(name, name, newComponent); } public FieldComponent RemoveComponent(string name) { FieldComponent removedComponent; _components.TryRemove(name, out removedComponent); return removedComponent; } // public void RemoveInvariants() { int count = 0; if (_dataType == DataTypeEnum.Vector) { count += _components.ContainsKey(FOComponentNames.All) ? 1 : 0; if (_components.Count() - count == 3) { _components.Remove(FOComponentNames.All); } } else if (_dataType == DataTypeEnum.Tensor) { count += _components.ContainsKey(FOComponentNames.Mises) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.Tresca) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.SgnMaxAbsPri) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.PrincipalMax) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.PrincipalMid) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.PrincipalMin) ? 1 : 0; // if (_components.Count - count == 6) { _components.Remove(FOComponentNames.Mises); _components.Remove(FOComponentNames.Tresca); _components.Remove(FOComponentNames.SgnMaxAbsPri); _components.Remove(FOComponentNames.PrincipalMax); _components.Remove(FOComponentNames.PrincipalMid); _components.Remove(FOComponentNames.PrincipalMin); } } } public void ComputeInvariants() { if (_dataType == DataTypeEnum.Vector) ComputeVectorFieldInvariant(); else if (_dataType == DataTypeEnum.Tensor) ComputeTensorFieldInvariant(); } private void ComputeVectorFieldInvariant() { int count = 0; count += _components.ContainsKey(FOComponentNames.All) ? 1 : 0; // if (_components.Count - count == 3) { _components.Remove(FOComponentNames.All); // count = 0; float[][] values = new float[3][]; foreach (var entry in _components) { values[count++] = entry.Value.Values; } // float[] magnitude = new float[values[0].Length]; for (int i = 0; i < magnitude.Length; i++) { magnitude[i] = (float)Math.Sqrt(values[0][i] * values[0][i] + values[1][i] * values[1][i] + values[2][i] * values[2][i]); } _components.Insert(0, FOComponentNames.All, new FieldComponent(FOComponentNames.All, magnitude, true)); } } private void ComputeTensorFieldInvariant() { int count = 0; count += _components.ContainsKey(FOComponentNames.Mises) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.Tresca) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.SgnMaxAbsPri) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.PrincipalMax) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.PrincipalMid) ? 1 : 0; count += _components.ContainsKey(FOComponentNames.PrincipalMin) ? 1 : 0; // if (_components.Count - count == 6) { _components.Remove(FOComponentNames.Mises); _components.Remove(FOComponentNames.Tresca); _components.Remove(FOComponentNames.SgnMaxAbsPri); _components.Remove(FOComponentNames.PrincipalMax); _components.Remove(FOComponentNames.PrincipalMid); _components.Remove(FOComponentNames.PrincipalMin); // count = 0; float[][] values = new float[6][]; foreach (var entry in _components) { values[count++] = entry.Value.Values; } // float[] vonMises = new float[values[0].Length]; float a, b, c; for (int i = 0; i < vonMises.Length; i++) { a = values[0][i] - values[1][i]; b = values[1][i] - values[2][i]; c = values[2][i] - values[0][i]; vonMises[i] = (float)Math.Sqrt(0.5f * (a * a + b * b + c * c + 6 * (values[3][i] * values[3][i] + values[4][i] * values[4][i] + values[5][i] * values[5][i]))); } // Mises _components.Insert(0, FOComponentNames.Mises, new FieldComponent(FOComponentNames.Mises, vonMises, true)); // Principal ComputeAndAddPrincipalInvariants(values); // Tresca float[] tresca = new float[values[0].Length]; float[] eMax = GetComponentValues(FOComponentNames.PrincipalMax); float[] eMin = GetComponentValues(FOComponentNames.PrincipalMin); for (int i = 0; i < tresca.Length; i++) tresca[i] = eMax[i] - eMin[i]; // _components.Insert(1, FOComponentNames.Tresca, new FieldComponent(FOComponentNames.Tresca, tresca, true)); } } private void ComputeAndAddPrincipalInvariants(float[][] values) { // https://en.wikipedia.org/wiki/Cubic_function#General_solution_to_the_cubic_equation_with_arbitrary_coefficients // https://en.wikiversity.org/wiki/Principal_stresses // float[] s0 = new float[values[0].Length]; float[] s1 = new float[values[0].Length]; float[] s2 = new float[values[0].Length]; float[] s3 = new float[values[0].Length]; // float s11; float s22; float s33; float s12; float s23; float s31; // float sp1, sp2, sp3; sp1 = sp2 = sp3 = 0; // for (int i = 0; i < s1.Length; i++) { s11 = values[0][i]; s22 = values[1][i]; s33 = values[2][i]; s12 = values[3][i]; s23 = values[4][i]; s31 = values[5][i]; // Tools.GetPrincipalValuesFromMatrix(s11, s22, s33, s12, s23, s31, ref sp1, ref sp2, ref sp3); Tools.Sort3_descending(ref sp1, ref sp2, ref sp3); // s0[i] = Math.Abs(sp1) > Math.Abs(sp3) ? sp1 : sp3; s1[i] = sp1; s2[i] = sp2; s3[i] = sp3; // if (float.IsNaN(s0[i])) s0[i] = 0; if (float.IsNaN(s1[i])) s1[i] = 0; if (float.IsNaN(s2[i])) s2[i] = 0; if (float.IsNaN(s3[i])) s3[i] = 0; } // AddComponent(FOComponentNames.SgnMaxAbsPri, s0, true); AddComponent(FOComponentNames.PrincipalMax, s1, true); AddComponent(FOComponentNames.PrincipalMid, s2, true); AddComponent(FOComponentNames.PrincipalMin, s3, true); } // public void RemoveNonInvariants() { HashSet componentNames = new HashSet(_components.Keys); // if (_dataType == DataTypeEnum.Vector) { componentNames.Remove(FOComponentNames.All); } else if (_dataType == DataTypeEnum.Tensor) { componentNames.Remove(FOComponentNames.Mises); componentNames.Remove(FOComponentNames.Tresca); componentNames.Remove(FOComponentNames.SgnMaxAbsPri); componentNames.Remove(FOComponentNames.PrincipalMax); componentNames.Remove(FOComponentNames.PrincipalMid); componentNames.Remove(FOComponentNames.PrincipalMin); } // foreach (string componentName in componentNames) _components.Remove(componentName); } public void SetComponentValuesToZero() { foreach (var entr in _components) entr.Value.SetValuesToZero(); } public void SetComponentValuesTo(float value) { foreach (var entr in _components) entr.Value.SetValuesTo(value); } public bool ContainsAllNecessaryComponents() { if (_dataType == DataTypeEnum.Scalar) { if (_components.Count == 1) return true; } else if (_dataType == DataTypeEnum.Vector) { HashSet componentNames = new HashSet(_components.Keys); componentNames.Remove(FOComponentNames.All); if (componentNames.Count == 3) return true; } else if (_dataType == DataTypeEnum.Tensor) { HashSet componentNames = new HashSet(_components.Keys); componentNames.Remove(FOComponentNames.Mises); componentNames.Remove(FOComponentNames.Tresca); componentNames.Remove(FOComponentNames.SgnMaxAbsPri); componentNames.Remove(FOComponentNames.PrincipalMax); componentNames.Remove(FOComponentNames.PrincipalMid); componentNames.Remove(FOComponentNames.PrincipalMin); if (componentNames.Count == 6) return true; } return false; } public static void FindMax(Field fieldMax, Field fieldAng, Field currentField, float angleDeg) { bool update; FieldComponent fieldMaxComponent; FieldComponent fieldAngComponent; FieldComponent currentComponent; // foreach (var entry in fieldMax._components) { update = false; fieldMaxComponent = entry.Value; // if (fieldAng._components.TryGetValue(entry.Key, out fieldAngComponent) && currentField._components.TryGetValue(entry.Key, out currentComponent) && fieldMaxComponent.Values.Length == fieldAngComponent.Values.Length && fieldMaxComponent.Values.Length == currentComponent.Values.Length) { for (int i = 0; i < fieldMaxComponent.Values.Length; i++) { if (currentComponent.Values[i] > fieldMaxComponent.Values[i]) { fieldMaxComponent.Values[i] = currentComponent.Values[i]; fieldAngComponent.Values[i] = angleDeg; update = true; } } } // if (update) { fieldMaxComponent.UpdateMaxMin(); fieldAngComponent.UpdateMaxMin(); } } } public static void FindMin(Field fieldMin, Field fieldAng, Field currentField, float angleDeg) { bool update; FieldComponent fieldMinComponent; FieldComponent fieldAngComponent; FieldComponent currentComponent; // foreach (var entry in fieldMin._components) { update = false; fieldMinComponent = entry.Value; // if (fieldAng._components.TryGetValue(entry.Key, out fieldAngComponent) && currentField._components.TryGetValue(entry.Key, out currentComponent) && fieldMinComponent.Values.Length == fieldAngComponent.Values.Length && fieldMinComponent.Values.Length == currentComponent.Values.Length) { for (int i = 0; i < fieldMinComponent.Values.Length; i++) { if (currentComponent.Values[i] < fieldMinComponent.Values[i]) { fieldMinComponent.Values[i] = currentComponent.Values[i]; fieldAngComponent.Values[i] = angleDeg; update = true; } } } // if (update) { fieldMinComponent.UpdateMaxMin(); fieldAngComponent.UpdateMaxMin(); } } } } }