using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using CaeMesh; using CaeGlobals; using CaeResults; using System.Runtime.Serialization; using DynamicTypeDescriptor; namespace CaeModel { [Serializable] public enum HydrostaticPressureCutoffEnum { [StandardValue("None", Description = "None", DisplayName = "None")] None, [StandardValue("Positive", Description = "Positive cutoff", DisplayName = "Positive cutoff")] Positive, [StandardValue("Negative", Description = "Negative cutoff", DisplayName = "Negative cutoff")] Negative } [Serializable] public class HydrostaticPressure : VariablePressure, IPreviewable, ISerializable { // Variables private EquationContainer _x1; //ISerializable private EquationContainer _y1; //ISerializable private EquationContainer _z1; //ISerializable private EquationContainer _x2; //ISerializable private EquationContainer _y2; //ISerializable private EquationContainer _z2; //ISerializable private EquationContainer _n1; //ISerializable private EquationContainer _n2; //ISerializable private EquationContainer _n3; //ISerializable private EquationContainer _firstPointPressure; //ISerializable private EquationContainer _secondPointPressure; //ISerializable private HydrostaticPressureCutoffEnum _hydrostaticPressureCutoff; //ISerializable [NonSerialized] private Vec3D _n; [NonSerialized] private double _d1; [NonSerialized] private double _d2; [NonSerialized] private double _a; [NonSerialized] private double _b; [NonSerialized] private DateTime _lastUpdate; // Properties public EquationContainer X1 { get { return _x1; } set { SetX1(value); } } public EquationContainer Y1 { get { return _y1; } set { SetY1(value); } } public EquationContainer Z1 { get { return _z1; } set { SetZ1(value); } } public EquationContainer X2 { get { return _x2; } set { SetX2(value); } } public EquationContainer Y2 { get { return _y2; } set { SetY2(value); } } public EquationContainer Z2 { get { return _z2; } set { SetZ2(value); } } public EquationContainer N1 { get { return _n1; } set { SetN1(value); } } public EquationContainer N2 { get { return _n2; } set { SetN2(value); } } public EquationContainer N3 { get { return _n3; } set { SetN3(value); } } public EquationContainer FirstPointPressure { get { return _firstPointPressure; } set { SetFirstPointPressure(value); } } public EquationContainer SecondPointPressure { get { return _secondPointPressure; } set { SetSecondPointPressure(value); } } public HydrostaticPressureCutoffEnum HydrostaticPressureCutoff { get { return _hydrostaticPressureCutoff; } set { _hydrostaticPressureCutoff = value; } } // Constructors public HydrostaticPressure(string name, string regionName, RegionTypeEnum regionType, bool twoD, bool complex, double phaseDeg) : this(name, regionName, regionType, new double[] { 0, 0, 0 }, new double[] { 0, 0, 0 }, 0, 0, 0, 0, 0, twoD, complex, phaseDeg) { } public HydrostaticPressure(string name, string regionName, RegionTypeEnum regionType, double[] firstPointCoor, double[] secondPointCoor, double nx, double ny, double nz, double firstPointPressure, double secondPointPressure, bool twoD, bool complex, double phaseDeg) : base(name, regionName, regionType, twoD, complex, phaseDeg) { X1 = new EquationContainer(typeof(StringLengthConverter), firstPointCoor[0]); Y1 = new EquationContainer(typeof(StringLengthConverter), firstPointCoor[1]); Z1 = new EquationContainer(typeof(StringLengthConverter), firstPointCoor[2]); X2 = new EquationContainer(typeof(StringLengthConverter), secondPointCoor[0]); Y2 = new EquationContainer(typeof(StringLengthConverter), secondPointCoor[1]); Z2 = new EquationContainer(typeof(StringLengthConverter), secondPointCoor[2]); N1 = new EquationContainer(typeof(StringLengthConverter), nx); N2 = new EquationContainer(typeof(StringLengthConverter), ny); N3 = new EquationContainer(typeof(StringLengthConverter), nz); // FirstPointPressure = new EquationContainer(typeof(StringPressureConverter), firstPointPressure); SecondPointPressure = new EquationContainer(typeof(StringPressureConverter), secondPointPressure); // _hydrostaticPressureCutoff = HydrostaticPressureCutoffEnum.None; } public HydrostaticPressure(SerializationInfo info, StreamingContext context) : base(info, context) { // Compatibility for version v1.4.0 if (_regionType == RegionTypeEnum.PartName) _regionType = RegionTypeEnum.Selection; _hydrostaticPressureCutoff = HydrostaticPressureCutoffEnum.None; // foreach (SerializationEntry entry in info) { switch (entry.Name) { // Compatibility for version v1.4.0 case "_firstPointCoor": double[] coor1 = (double[])entry.Value; X1 = new EquationContainer(typeof(StringLengthConverter), coor1[0]); Y1 = new EquationContainer(typeof(StringLengthConverter), coor1[1]); Z1 = new EquationContainer(typeof(StringLengthConverter), coor1[2]); break; // Compatibility for version v1.4.0 case "_secondPointCoor": double[] coor2 = (double[])entry.Value; X2 = new EquationContainer(typeof(StringLengthConverter), coor2[0]); Y2 = new EquationContainer(typeof(StringLengthConverter), coor2[1]); Z2 = new EquationContainer(typeof(StringLengthConverter), coor2[2]); break; case "_x1": SetX1((EquationContainer)entry.Value, false); break; case "_y1": SetY1((EquationContainer)entry.Value, false); break; case "_z1": SetZ1((EquationContainer)entry.Value, false); break; case "_x2": SetX2((EquationContainer)entry.Value, false); break; case "_y2": SetY2((EquationContainer)entry.Value, false); break; case "_z2": SetZ2((EquationContainer)entry.Value, false); break; case "_n1": // Compatibility for version v1.4.0 if (entry.Value is double valueN1) N1 = new EquationContainer(typeof(StringLengthConverter), valueN1); else SetN1((EquationContainer)entry.Value, false); break; case "_n2": // Compatibility for version v1.4.0 if (entry.Value is double valueN2) N2 = new EquationContainer(typeof(StringLengthConverter), valueN2); else SetN2((EquationContainer)entry.Value, false); break; case "_n3": // Compatibility for version v1.4.0 if (entry.Value is double valueN3) N3 = new EquationContainer(typeof(StringLengthConverter), valueN3); else SetN3((EquationContainer)entry.Value, false); break; case "_firstPointPressure": // Compatibility for version v1.4.0 if (entry.Value is double valueP1) FirstPointPressure = new EquationContainer(typeof(StringPressureConverter), valueP1); else SetFirstPointPressure((EquationContainer)entry.Value, false); break; case "_secondPointPressure": // Compatibility for version v1.4.0 if (entry.Value is double valueP2) SecondPointPressure = new EquationContainer(typeof(StringPressureConverter), valueP2); else SetSecondPointPressure((EquationContainer)entry.Value, false); break; case "_hydrostaticPressureCutoff": _hydrostaticPressureCutoff = (HydrostaticPressureCutoffEnum)entry.Value; break; default: break; } } } // Methods private void SetX1(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _x1, value, null, checkEquation); } private void SetY1(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _y1, value, null, checkEquation); } private void SetZ1(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _z1, value, Check2D, checkEquation); } private void SetX2(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _x2, value, null, checkEquation); } private void SetY2(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _y2, value, null, checkEquation); } private void SetZ2(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _z2, value, Check2D, checkEquation); } private void SetN1(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _n1, value, null, checkEquation); } private void SetN2(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _n2, value, null, checkEquation); } private void SetN3(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _n3, value, Check2D, checkEquation); } private void SetFirstPointPressure(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _firstPointPressure, value, null, checkEquation); } private void SetSecondPointPressure(EquationContainer value, bool checkEquation = true) { EquationContainer.SetAndCheck(ref _secondPointPressure, value, null, checkEquation); } // private double Check2D(double value) { if (_twoD) return 0; else return value; } // IContainsEquations public override void CheckEquations() { base.CheckEquations(); // _x1.CheckEquation(); _y1.CheckEquation(); _z1.CheckEquation(); _x2.CheckEquation(); _y2.CheckEquation(); _z2.CheckEquation(); _n1.CheckEquation(); _n2.CheckEquation(); _n3.CheckEquation(); _firstPointPressure.CheckEquation(); _secondPointPressure.CheckEquation(); } // public bool IsProperlyDefined(out string error) { error = ""; Vec3D p1 = new Vec3D(_x1.Value, _y1.Value, _z1.Value); Vec3D p2 = new Vec3D(_x2.Value, _y2.Value, _z2.Value); Vec3D n = new Vec3D(_n1.Value, _n2.Value, _n3.Value); // if (n.Normalize() > 0) { double d1 = -Vec3D.DotProduct(n, p1); // d1: distance of the plane through p1 from origin double d2 = -Vec3D.DotProduct(n, p2); // d2: distance of the plane through p2 from origin // if (Math.Abs(d1 - d2) < 1E-6) { error = "The first and the second point must not be on a plane perpendicular to the pressure direction."; return false; } } else { error = "The pressure direction is not properly defined."; return false; } // return true; } public FeResults GetPreview(FeModel model, string resultName, UnitSystem unitSystem) { FeMesh targetMesh = model.Mesh; PartExchangeData allData = new PartExchangeData(); targetMesh.GetAllNodesAndCells(out allData.Nodes.Ids, out allData.Nodes.Coor, out allData.Cells.Ids, out allData.Cells.CellNodeIds, out allData.Cells.Types); // FeSurface surface = targetMesh.Surfaces[_surfaceName]; FeNodeSet nodeSet = targetMesh.NodeSets[surface.NodeSetName]; HashSet nodeIds = new HashSet(nodeSet.Labels); // float[] values = new float[allData.Nodes.Coor.Length]; // for (int i = 0; i < values.Length; i++) { if (nodeIds.Contains(allData.Nodes.Ids[i])) { values[i] = (float)GetPressureForPoint(model, allData.Nodes.Coor[i]); } else { values[i] = float.NaN; } } // Dictionary nodeIdsLookUp = new Dictionary(); for (int i = 0; i < allData.Nodes.Coor.Length; i++) nodeIdsLookUp.Add(allData.Nodes.Ids[i], i); FeResults results = new FeResults(resultName, unitSystem); results.SetMesh(targetMesh, nodeIdsLookUp); // Add distances FieldData fieldData = new FieldData(FOFieldNames.Imported); fieldData.GlobalIncrementId = 1; fieldData.StepType = StepTypeEnum.Static; fieldData.Time = 1; fieldData.MethodId = 1; fieldData.StepId = 1; fieldData.StepIncrementId = 1; // Add values Field field = new Field(fieldData.Name); field.AddComponent(FOComponentNames.PRESS, values); results.AddField(fieldData, field); // return results; } // Variable pressure public override double GetPressureForPoint(FeModel model, double[] point) { DateTime now = DateTime.Now; TimeSpan delta = now - _lastUpdate; if (delta.TotalMilliseconds > 1000) { _n = new Vec3D(_n1.Value, _n2.Value, _n3.Value); _n.Normalize(); // _d1 = -(_x1.Value * _n.X + _y1.Value * _n.Y + _z1.Value * _n.Z); _d2 = -(_x2.Value * _n.X + _y2.Value * _n.Y + _z2.Value * _n.Z); // _a = _firstPointPressure.Value; _b = (_secondPointPressure.Value - _firstPointPressure.Value) / (_d2 - _d1); // _lastUpdate = now; } double d = -(point[0] * _n.X + point[1] * _n.Y + point[2] * _n.Z); // double p = _a + _b * (d - _d1); // if (_hydrostaticPressureCutoff == HydrostaticPressureCutoffEnum.None) return p; else if (_hydrostaticPressureCutoff == HydrostaticPressureCutoffEnum.Positive) return p > 0 ? 0 : p; else if (_hydrostaticPressureCutoff == HydrostaticPressureCutoffEnum.Negative) return p < 0 ? 0 : p; else throw new NotSupportedException(); } public override double[] GetPressuresForPoints(FeModel model, double[][] points) { double[] values = new double[points.Length]; _n = new Vec3D(_n1.Value, _n2.Value, _n3.Value); _n.Normalize(); // _d1 = -(_x1.Value * _n.X + _y1.Value * _n.Y + _z1.Value * _n.Z); _d2 = -(_x2.Value * _n.X + _y2.Value * _n.Y + _z2.Value * _n.Z); // _a = _firstPointPressure.Value; _b = (_secondPointPressure.Value - _firstPointPressure.Value) / (_d2 - _d1); // double d; double p; for (int i = 0; i < points.Length; i++) { d = -(points[i][0] * _n.X + points[i][1] * _n.Y + points[i][2] * _n.Z); // p = _a + _b * (d - _d1); // if (_hydrostaticPressureCutoff == HydrostaticPressureCutoffEnum.None) values[i] = p; else if (_hydrostaticPressureCutoff == HydrostaticPressureCutoffEnum.Positive) values[i] = p > 0 ? 0 : p; else if (_hydrostaticPressureCutoff == HydrostaticPressureCutoffEnum.Negative) values[i] = p < 0 ? 0 : p; else throw new NotSupportedException(); } return values; } // ISerialization public new void GetObjectData(SerializationInfo info, StreamingContext context) { // Using typeof() works also for null fields base.GetObjectData(info, context); // info.AddValue("_x1", _x1, typeof(EquationContainer)); info.AddValue("_y1", _y1, typeof(EquationContainer)); info.AddValue("_z1", _z1, typeof(EquationContainer)); info.AddValue("_x2", _x2, typeof(EquationContainer)); info.AddValue("_y2", _y2, typeof(EquationContainer)); info.AddValue("_z2", _z2, typeof(EquationContainer)); info.AddValue("_n1", _n1, typeof(EquationContainer)); info.AddValue("_n2", _n2, typeof(EquationContainer)); info.AddValue("_n3", _n3, typeof(EquationContainer)); info.AddValue("_firstPointPressure", _firstPointPressure, typeof(EquationContainer)); info.AddValue("_secondPointPressure", _secondPointPressure, typeof(EquationContainer)); info.AddValue("_hydrostaticPressureCutoff", _hydrostaticPressureCutoff, typeof(HydrostaticPressureCutoffEnum)); } } }