399 lines
19 KiB
C#
399 lines
19 KiB
C#
|
|
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<int> nodeIds = new HashSet<int>(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<int, int> nodeIdsLookUp = new Dictionary<int, int>();
|
|||
|
|
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));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|