6134 lines
296 KiB
C#
6134 lines
296 KiB
C#
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.Runtime.Serialization;
|
|
using System.Security.AccessControl;
|
|
using System.Runtime.Remoting.Metadata.W3cXsd2001;
|
|
using System.Collections.Concurrent;
|
|
using System.Data;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Xml.Linq;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using static CaeGlobals.Geometry2;
|
|
using System.Numerics;
|
|
using System.Linq.Expressions;
|
|
using System.Runtime.InteropServices.WindowsRuntime;
|
|
using System.Diagnostics;
|
|
|
|
namespace CaeResults
|
|
{
|
|
[Serializable]
|
|
public class FeResults //: ISerializable
|
|
{
|
|
// Variables
|
|
[NonSerialized]
|
|
private Dictionary<int, int> _nodeIdsLookUp; // [globalId][resultsId] for values
|
|
[NonSerialized]
|
|
private OrderedDictionary<FieldData, Field> _fields;
|
|
[NonSerialized]
|
|
private OrderedDictionary<string, Field> _fieldDataHashField;
|
|
[NonSerialized]
|
|
private Dictionary<int, FeNode> _undeformedNodes;
|
|
[NonSerialized]
|
|
private float _scale;
|
|
[NonSerialized]
|
|
private int _stepId;
|
|
[NonSerialized]
|
|
private int _stepIncrementId;
|
|
[NonSerialized]
|
|
private bool _complexResultChanged;
|
|
//
|
|
public static readonly string[][] ComplexFieldNames = new string[][] { new string[] { FOFieldNames.Disp,
|
|
FOFieldNames.DispR,
|
|
FOFieldNames.DispI,
|
|
FOFieldNames.DispMag,
|
|
FOFieldNames.DispPha,
|
|
FOFieldNames.DispMax,
|
|
FOFieldNames.DispMaxAng,
|
|
FOFieldNames.DispMin,
|
|
FOFieldNames.DispMinAng},
|
|
new string[] { FOFieldNames.Stress,
|
|
FOFieldNames.StressR,
|
|
FOFieldNames.StressI,
|
|
FOFieldNames.StressMag,
|
|
FOFieldNames.StressPha,
|
|
FOFieldNames.StressMax,
|
|
FOFieldNames.StressMaxAng,
|
|
FOFieldNames.StressMin,
|
|
FOFieldNames.StressMinAng},
|
|
new string[] { FOFieldNames.ZZStr,
|
|
FOFieldNames.ZZStrR,
|
|
FOFieldNames.ZZStrI ,
|
|
FOFieldNames.ZZStrMag,
|
|
FOFieldNames.ZZStrPha,
|
|
FOFieldNames.ZZStrMax,
|
|
FOFieldNames.ZZStrMaxAng,
|
|
FOFieldNames.ZZStrMin,
|
|
FOFieldNames.ZZStrMinAng},
|
|
new string[] { FOFieldNames.ToStrain,
|
|
FOFieldNames.ToStraiR,
|
|
FOFieldNames.ToStraiI,
|
|
FOFieldNames.ToStraiMag,
|
|
FOFieldNames.ToStraiPha,
|
|
FOFieldNames.ToStraiMax,
|
|
FOFieldNames.ToStraiMaxAng,
|
|
FOFieldNames.ToStraiMin,
|
|
FOFieldNames.ToStraiMinAng},
|
|
new string[] { FOFieldNames.MeStrain,
|
|
FOFieldNames.MeStraiR,
|
|
FOFieldNames.MeStraiI,
|
|
FOFieldNames.MeStraiMag,
|
|
FOFieldNames.MeStraiPha,
|
|
FOFieldNames.MeStraiMax,
|
|
FOFieldNames.MeStraiMaxAng,
|
|
FOFieldNames.MeStraiMin,
|
|
FOFieldNames.MeStraiMinAng},
|
|
new string[] { FOFieldNames.Forc,
|
|
FOFieldNames.ForcR,
|
|
FOFieldNames.ForcI,
|
|
FOFieldNames.ForcMag,
|
|
FOFieldNames.ForcPha,
|
|
FOFieldNames.ForcMax,
|
|
FOFieldNames.ForcMaxAng,
|
|
FOFieldNames.ForcMin,
|
|
FOFieldNames.ForcMinAng},
|
|
new string[] { FOFieldNames.HError,
|
|
FOFieldNames.HErrorR,
|
|
FOFieldNames.HErrorI,
|
|
FOFieldNames.HErrorMag,
|
|
FOFieldNames.HErrorPha,
|
|
FOFieldNames.HErrorMax,
|
|
FOFieldNames.HErrorMaxAng,
|
|
FOFieldNames.HErrorMin,
|
|
FOFieldNames.HErrorMinAng},
|
|
new string[] { FOFieldNames.Error,
|
|
FOFieldNames.ErrorR,
|
|
FOFieldNames.ErrorI,
|
|
FOFieldNames.ErrorMag,
|
|
FOFieldNames.ErrorPha,
|
|
FOFieldNames.ErrorMax,
|
|
FOFieldNames.ErrorMaxAng,
|
|
FOFieldNames.ErrorMin,
|
|
FOFieldNames.ErrorMinAng}};
|
|
//
|
|
private string _hashName;
|
|
private string _fileName;
|
|
private FeMesh _mesh;
|
|
private OrderedDictionary<string, ResultFieldOutput> _resultFieldOutputs;
|
|
private OrderedDictionary<string, ResultHistoryOutput> _resultHistoryOutputs;
|
|
[NonSerialized]
|
|
private HistoryResults _history;
|
|
private DateTime _dateTime;
|
|
private UnitSystem _unitSystem;
|
|
private string _deformationFieldOutputName;
|
|
private ComplexResultTypeEnum _complexResultType;
|
|
private float _complexAngleDeg;
|
|
|
|
|
|
|
|
// Properties
|
|
public Dictionary<int, FeNode> UndeformedNodes { get { return _undeformedNodes; } }
|
|
public string HashName { get { return _hashName; } set { _hashName = value; } }
|
|
public string FileName { get { return _fileName; } set { _fileName = value; } }
|
|
public FeMesh Mesh { get { return _mesh; } set { _mesh = value; } }
|
|
public DateTime DateTime { get { return _dateTime; } set { _dateTime = value; } }
|
|
public UnitSystem UnitSystem { get { return _unitSystem; } set { _unitSystem = value; } }
|
|
public string DeformationFieldOutputName
|
|
{
|
|
get
|
|
{
|
|
OrderedDictionary<string, string> possibleNames = GetPossibleDeformationFieldOutputNamesMap();
|
|
foreach (var entry in possibleNames)
|
|
{
|
|
if (entry.Value == _deformationFieldOutputName) return entry.Key;
|
|
}
|
|
return "";
|
|
}
|
|
set
|
|
{
|
|
string newDeformationFieldOutputName;
|
|
OrderedDictionary<string, string> possibleNames = GetPossibleDeformationFieldOutputNamesMap();
|
|
if (possibleNames.TryGetValue(value, out newDeformationFieldOutputName)) { }
|
|
else newDeformationFieldOutputName = possibleNames.Values.First();
|
|
// Reset global mesh deformation settings if needed
|
|
if (newDeformationFieldOutputName != _deformationFieldOutputName)
|
|
{
|
|
_deformationFieldOutputName = newDeformationFieldOutputName;
|
|
ResetScaleStepIncrement();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Constructor
|
|
public FeResults(string fileName, UnitSystem unitSystem)
|
|
{
|
|
_fileName = fileName;
|
|
_hashName = Tools.GetRandomString(8);
|
|
_mesh = null;
|
|
_resultFieldOutputs = new OrderedDictionary<string, ResultFieldOutput>("ResultFieldOutputs",
|
|
StringComparer.OrdinalIgnoreCase);
|
|
_resultHistoryOutputs = new OrderedDictionary<string, ResultHistoryOutput>("ResultHistoryOutputs",
|
|
StringComparer.OrdinalIgnoreCase);
|
|
_nodeIdsLookUp = null;
|
|
_fields = new OrderedDictionary<FieldData, Field>("Fields");
|
|
_fieldDataHashField = new OrderedDictionary<string, Field>("HashFieldPairs");
|
|
_history = new HistoryResults("History");
|
|
if (unitSystem == null) _unitSystem = new UnitSystem();
|
|
else _unitSystem = unitSystem;
|
|
_deformationFieldOutputName = FOFieldNames.Disp;
|
|
_complexResultChanged = false;
|
|
}
|
|
//public FeResults(SerializationInfo info, StreamingContext context)
|
|
//{
|
|
|
|
//}
|
|
//// ISerialization
|
|
//public void GetObjectData(SerializationInfo info, StreamingContext context)
|
|
//{
|
|
// // Using typeof() works also for null fields
|
|
// //info.AddValue("_meshRepresentation", _meshRepresentation, typeof(MeshRepresentation));
|
|
// //info.AddValue("_meshRefinements", _meshRefinements, typeof(OrderedDictionary<string, FeMeshRefinement>));
|
|
// //info.AddValue("_parts", _parts, typeof(OrderedDictionary<string, BasePart>));
|
|
// //info.AddValue("_nodeSets", _nodeSets, typeof(OrderedDictionary<string, FeNodeSet>));
|
|
// //info.AddValue("_elementSets", _elementSets, typeof(OrderedDictionary<string, FeElementSet>));
|
|
// //info.AddValue("_surfaces", _surfaces, typeof(OrderedDictionary<string, FeSurface>));
|
|
// //info.AddValue("_referencePoints", _referencePoints, typeof(OrderedDictionary<string, FeReferencePoint>));
|
|
// //info.AddValue("_maxNodeId", _maxNodeId, typeof(int));
|
|
// //info.AddValue("_maxElementId", _maxElementId, typeof(int));
|
|
// //info.AddValue("_boundingBox", _boundingBox, typeof(BoundingBox));
|
|
//}
|
|
|
|
// Static methods
|
|
public static void WriteToFileStream(FeResults results, FileStream fileStream, CompressionLevel compressionLevel)
|
|
{
|
|
if (results == null)
|
|
{
|
|
// Write the result state
|
|
Tools.WriteIntToFileStream(fileStream, -1);
|
|
}
|
|
else
|
|
{
|
|
// Write the result state
|
|
Tools.WriteIntToFileStream(fileStream, 1);
|
|
// Write the results mesh data
|
|
using (BinaryWriter bw = new BinaryWriter(new MemoryStream()))
|
|
{
|
|
Dictionary<int, FeNode> tmp = results.Mesh.Nodes;
|
|
results.Mesh.Nodes = results._undeformedNodes;
|
|
FeMesh.WriteToBinaryWriter(results.Mesh, bw);
|
|
results.Mesh.Nodes = tmp;
|
|
// Node lookup
|
|
if (results._nodeIdsLookUp == null) bw.Write(-1);
|
|
else
|
|
{
|
|
bw.Write(1);
|
|
//
|
|
bw.Write(results._nodeIdsLookUp.Count);
|
|
foreach (var entry in results._nodeIdsLookUp)
|
|
{
|
|
bw.Write(entry.Key);
|
|
bw.Write(entry.Value);
|
|
}
|
|
}
|
|
// Rewind the writer
|
|
bw.Flush();
|
|
bw.BaseStream.Position = 0;
|
|
// Compress the writer
|
|
byte[] compressedData = Tools.Compress(bw.BaseStream, compressionLevel);
|
|
// Write the length of the compressed data
|
|
Tools.WriteIntToFileStream(fileStream, compressedData.Length);
|
|
// Write the compressed data
|
|
fileStream.Write(compressedData, 0, compressedData.Length);
|
|
}
|
|
// Fields
|
|
if (results._fields == null)
|
|
{
|
|
// Write the field state
|
|
Tools.WriteIntToFileStream(fileStream, -1);
|
|
}
|
|
else
|
|
{
|
|
// Write the field state
|
|
Tools.WriteIntToFileStream(fileStream, 1);
|
|
// Set complex to real
|
|
ComplexResultTypeEnum prevComplexResultType = results._complexResultType;
|
|
float prevComplexAngleDeg = results._complexAngleDeg;
|
|
results.SetComplexResultTypeAndAngle(ComplexResultTypeEnum.Real, 0);
|
|
// Delete complex results
|
|
results.RemoveComplexResults();
|
|
// Write the number of fields
|
|
Tools.WriteIntToFileStream(fileStream, results._fields.Count);
|
|
// Write fields separately to prevent BinaryWriter out of memory exception
|
|
foreach (var entry in results._fields)
|
|
{
|
|
entry.Value.RemoveInvariants();
|
|
//
|
|
using (BinaryWriter bw = new BinaryWriter(new MemoryStream()))
|
|
{
|
|
FieldData.WriteToBinaryWriter(entry.Key, bw);
|
|
Field.WriteToBinaryWriter(entry.Value, bw);
|
|
// Rewind the writer
|
|
bw.Flush();
|
|
bw.BaseStream.Position = 0;
|
|
// Compress the writer
|
|
byte[] compressedData = Tools.Compress(bw.BaseStream, compressionLevel);
|
|
// Write the length of the compressed data
|
|
Tools.WriteIntToFileStream(fileStream, compressedData.Length);
|
|
// Write the compressed data
|
|
fileStream.Write(compressedData, 0, compressedData.Length);
|
|
}
|
|
//
|
|
entry.Value.ComputeInvariants();
|
|
}
|
|
// Prepare complex
|
|
results.PrepareComplexResults();
|
|
// Reset complex
|
|
results.SetComplexResultTypeAndAngle(prevComplexResultType, prevComplexAngleDeg);
|
|
}
|
|
// History
|
|
if (results._history == null)
|
|
{
|
|
// Write the history state
|
|
Tools.WriteIntToFileStream(fileStream, -1);
|
|
}
|
|
else
|
|
{
|
|
// Write the history state
|
|
Tools.WriteIntToFileStream(fileStream, 1);
|
|
//
|
|
HistoryResults.WriteToFileStream(results._history, fileStream, compressionLevel);
|
|
}
|
|
}
|
|
}
|
|
public static void ReadFromFileStream(FeResults results, FileStream fileStream, int version)
|
|
{
|
|
int numItems;
|
|
int numOfBytes;
|
|
FieldData fieldData;
|
|
Field field;
|
|
HistoryResults history;
|
|
byte[] compressedData;
|
|
// Read the result state
|
|
int exists = Tools.ReadIntFromFileStream(fileStream);
|
|
if (exists == 1)
|
|
{
|
|
// Mesh
|
|
numOfBytes = Tools.ReadIntFromFileStream(fileStream);
|
|
compressedData = new byte[numOfBytes];
|
|
fileStream.Read(compressedData, 0, compressedData.Length);
|
|
//
|
|
using (MemoryStream memoryStream = new MemoryStream(compressedData))
|
|
using (BinaryReader br = new BinaryReader(Tools.Decompress(memoryStream)))
|
|
{
|
|
FeMesh.ReadFromBinaryReader(results.Mesh, br, version);
|
|
//
|
|
results.InitializeUndeformedNodes();
|
|
// Node lookup
|
|
exists = br.ReadInt32();
|
|
if (exists == 1)
|
|
{
|
|
numItems = br.ReadInt32();
|
|
results._nodeIdsLookUp = new Dictionary<int, int>();
|
|
for (int i = 0; i < numItems; i++) results._nodeIdsLookUp.Add(br.ReadInt32(), br.ReadInt32());
|
|
}
|
|
}
|
|
// Read the fields state
|
|
exists = Tools.ReadIntFromFileStream(fileStream);
|
|
if (exists == 1)
|
|
{
|
|
numItems = Tools.ReadIntFromFileStream(fileStream);
|
|
results._fields = new OrderedDictionary<FieldData, Field>("Fields");
|
|
results._fieldDataHashField = new OrderedDictionary<string, Field>("HashFieldPairs");
|
|
for (int i = 0; i < numItems; i++)
|
|
{
|
|
numOfBytes = Tools.ReadIntFromFileStream(fileStream);
|
|
compressedData = new byte[numOfBytes];
|
|
fileStream.Read(compressedData, 0, compressedData.Length);
|
|
//
|
|
using (MemoryStream memoryStream = new MemoryStream(compressedData))
|
|
using (BinaryReader br = new BinaryReader(Tools.Decompress(memoryStream)))
|
|
{
|
|
fieldData = FieldData.ReadFromBinaryReader(br, version);
|
|
field = Field.ReadFromBinaryReader(br, version);
|
|
}
|
|
//
|
|
if (field != null)
|
|
{
|
|
field.ComputeInvariants();
|
|
//
|
|
results.AddField(fieldData, field);
|
|
}
|
|
}
|
|
// Prepare complex
|
|
results.PrepareComplexResults();
|
|
// Compatibility v1.5.3
|
|
if (results._resultFieldOutputs == null)
|
|
results._resultFieldOutputs =
|
|
new OrderedDictionary<string, ResultFieldOutput>("ResultFieldOutputs",
|
|
StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
// Compatibility v2.3.5
|
|
if (version > 2_003_005)
|
|
{
|
|
// Read the history state
|
|
exists = Tools.ReadIntFromFileStream(fileStream);
|
|
if (exists == 1)
|
|
{
|
|
results._history = HistoryResults.ReadFromFileStream(fileStream, version);
|
|
}
|
|
}
|
|
}
|
|
// Compatibility v2.1.0
|
|
if (results._resultHistoryOutputs == null)
|
|
results._resultHistoryOutputs = new OrderedDictionary<string, ResultHistoryOutput>("ResultHistoryOutputs",
|
|
StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
// Uncompressed - old version
|
|
public static void ReadFromBinaryReader(FeResults results, BinaryReader br, int version)
|
|
{
|
|
int numItems;
|
|
FieldData fieldData;
|
|
Field field;
|
|
//
|
|
int exist = br.ReadInt32();
|
|
if (exist == 1)
|
|
{
|
|
// Mesh
|
|
FeMesh.ReadFromBinaryReader(results.Mesh, br, version);
|
|
results.InitializeUndeformedNodes();
|
|
// Node lookup
|
|
exist = br.ReadInt32();
|
|
if (exist == 1)
|
|
{
|
|
numItems = br.ReadInt32();
|
|
results._nodeIdsLookUp = new Dictionary<int, int>();
|
|
for (int i = 0; i < numItems; i++) results._nodeIdsLookUp.Add(br.ReadInt32(), br.ReadInt32());
|
|
}
|
|
// Fields
|
|
exist = br.ReadInt32();
|
|
if (exist == 1)
|
|
{
|
|
numItems = br.ReadInt32();
|
|
results._fields = new OrderedDictionary<FieldData, Field>("Fields");
|
|
results._fieldDataHashField = new OrderedDictionary<string, Field>("HashFieldPairs");
|
|
for (int i = 0; i < numItems; i++)
|
|
{
|
|
fieldData = FieldData.ReadFromBinaryReader(br, version);
|
|
field = Field.ReadFromBinaryReader(br, version);
|
|
if (field != null)
|
|
{
|
|
//
|
|
field.ComputeInvariants();
|
|
//
|
|
results.AddField(fieldData, field);
|
|
}
|
|
}
|
|
// Prepare complex
|
|
results.PrepareComplexResults();
|
|
// Compatibility v1.5.3
|
|
if (results._resultFieldOutputs == null)
|
|
results._resultFieldOutputs = new OrderedDictionary<string, ResultFieldOutput>("ResultFieldOutputs",
|
|
StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
}
|
|
// Compatibility v2.1.0
|
|
if (results._resultHistoryOutputs == null)
|
|
results._resultHistoryOutputs = new OrderedDictionary<string, ResultHistoryOutput>("ResultHistoryOutputs",
|
|
StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
|
|
|
|
// Methods
|
|
public string[] CheckValidity(List<Tuple<NamedClass, string>> items)
|
|
{
|
|
// Tuple<NamedClass, string> ... Tuple<invalidItem, stepName>
|
|
List<string> invalidItems = new List<string>();
|
|
bool valid;
|
|
// Result field outputs
|
|
HashSet<string> names;
|
|
ResultFieldOutput existingResultFieldOutput;
|
|
List<ResultFieldOutput> fieldIindependencySequence = GetResultFieldOutputIndependencySequence();
|
|
Dictionary<string, string[]> filedNameComponentNames = GetAllVisibleFiledNameComponentNames();
|
|
//
|
|
foreach (var resultFieldOutput in fieldIindependencySequence)
|
|
{
|
|
valid = true;
|
|
names = new HashSet<string>(filedNameComponentNames.Keys);
|
|
string[] parentNames = resultFieldOutput.GetParentNames();
|
|
names.IntersectWith(parentNames);
|
|
valid &= names.Count == parentNames.Length;
|
|
//
|
|
if (valid)
|
|
{
|
|
// Check parents for validity
|
|
foreach (var name in parentNames)
|
|
{
|
|
if (_resultFieldOutputs.TryGetValue(name, out existingResultFieldOutput))
|
|
valid &= existingResultFieldOutput.Valid;
|
|
}
|
|
//
|
|
if (valid)
|
|
{
|
|
if (resultFieldOutput is ResultFieldOutputLimit rfol)
|
|
{
|
|
// Parent components
|
|
names = new HashSet<string>(filedNameComponentNames[rfol.FieldName]);
|
|
valid &= names.Contains(rfol.ComponentName);
|
|
//
|
|
if (rfol.LimitPlotBasedOn == LimitPlotBasedOnEnum.Parts)
|
|
names = new HashSet<string>(_mesh.Parts.Keys);
|
|
else if (rfol.LimitPlotBasedOn == LimitPlotBasedOnEnum.ElementSets)
|
|
{
|
|
names = new HashSet<string>(_mesh.ElementSets.Keys);
|
|
names.Add(ResultFieldOutputLimit.AllElementsName);
|
|
}
|
|
else throw new NotSupportedException();
|
|
//
|
|
names.IntersectWith(rfol.ItemNameLimit.Keys);
|
|
valid &= names.Count == rfol.ItemNameLimit.Count;
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputEnvelope rfoen)
|
|
{
|
|
// Parent components
|
|
names = new HashSet<string>(filedNameComponentNames[rfoen.FieldName]);
|
|
valid &= names.Contains(rfoen.ComponentName);
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputEquation rfoeq)
|
|
{
|
|
names = new HashSet<string>(filedNameComponentNames.Keys);
|
|
names.IntersectWith(parentNames);
|
|
valid &= names.Count == parentNames.Length;
|
|
//
|
|
if (valid)
|
|
{
|
|
// Check parents for validity
|
|
}
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputCoordinateSystemTransform rfocst)
|
|
{
|
|
valid &= _mesh.CoordinateSystems.ContainsValidKey(rfocst.CoordinateSystemName);
|
|
DataTypeEnum dataType = GetFieldDataType(rfocst.FieldName);
|
|
valid &= dataType == DataTypeEnum.Vector || dataType == DataTypeEnum.Tensor;
|
|
valid &= DoesFieldContainsAllNecessaryComponents(rfocst.FieldName);
|
|
}
|
|
else throw new NotSupportedException();
|
|
}
|
|
}
|
|
//
|
|
SetItemValidity(resultFieldOutput, valid, items);
|
|
if (!valid && resultFieldOutput.Active) invalidItems.Add("Field output: " + resultFieldOutput.Name);
|
|
}
|
|
// Result history outputs
|
|
ResultHistoryOutput existingResultHistoryOutput;
|
|
List<ResultHistoryOutput> historyIndependencySequence = GetResultHistoryOutputIndependencySequence();
|
|
//
|
|
foreach (var resultHistoryOutput in historyIndependencySequence)
|
|
{
|
|
// Parent names
|
|
string[] parentNames = resultHistoryOutput.GetParentNames();
|
|
valid = true;
|
|
//
|
|
if (resultHistoryOutput is ResultHistoryOutputFromField rhoff)
|
|
{
|
|
names = new HashSet<string>(GetVisibleFieldNames());
|
|
valid &= names.Contains(rhoff.FieldName);
|
|
//
|
|
if (valid)
|
|
{
|
|
// Check if USER DEFINED FILED is used and if it is valid
|
|
if (_resultFieldOutputs.TryGetValue(rhoff.FieldName, out existingResultFieldOutput))
|
|
valid &= existingResultFieldOutput.Valid;
|
|
//
|
|
if (valid)
|
|
{
|
|
parentNames = rhoff.ComponentNames;
|
|
names = new HashSet<string>(filedNameComponentNames[rhoff.FieldName]);
|
|
}
|
|
}
|
|
}
|
|
else if (resultHistoryOutput is ResultHistoryOutputFromEquation)
|
|
{
|
|
names = new HashSet<string>(_history.Sets.Keys);
|
|
names.IntersectWith(parentNames);
|
|
valid &= names.Count == parentNames.Length;
|
|
//
|
|
if (valid)
|
|
{
|
|
// Check parents for validity
|
|
foreach (var name in parentNames)
|
|
{
|
|
if (_resultHistoryOutputs.TryGetValue(name, out existingResultHistoryOutput))
|
|
valid &= existingResultHistoryOutput.Valid;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
SetItemValidity(resultHistoryOutput, valid, items);
|
|
if (!valid && resultHistoryOutput.Active) invalidItems.Add("History output: " + resultHistoryOutput.Name);
|
|
}
|
|
return invalidItems.ToArray();
|
|
}
|
|
private void SetItemValidity(NamedClass item, bool validity, List<Tuple<NamedClass, string>> items)
|
|
{
|
|
// only changed items are added for the update
|
|
if (item.Valid != validity)
|
|
{
|
|
item.Valid = validity;
|
|
items.Add(new Tuple<NamedClass, string>(item, null));
|
|
}
|
|
}
|
|
public void Preprocess()
|
|
{
|
|
ComputeVisibleFieldInvariants();
|
|
PrepareComplexResults();
|
|
}
|
|
// Mesh
|
|
public void SetMesh(FeMesh mesh, Dictionary<int, int> nodeIdsLookUp)
|
|
{
|
|
_mesh = new FeMesh(mesh, mesh.Parts.Keys.ToArray());
|
|
//
|
|
List<BasePart> parts = new List<BasePart>();
|
|
foreach (var entry in _mesh.Parts)
|
|
{
|
|
if (!(entry.Value is ResultPart)) parts.Add(entry.Value);
|
|
}
|
|
//
|
|
foreach (var part in parts)
|
|
{
|
|
_mesh.Parts.Replace(part.Name, part.Name, new ResultPart(part));
|
|
}
|
|
//
|
|
InitializeUndeformedNodes();
|
|
//
|
|
_nodeIdsLookUp = nodeIdsLookUp;
|
|
}
|
|
public void ScaleAllParts(double scale)
|
|
{
|
|
_mesh.ScaleAllParts(scale);
|
|
//
|
|
InitializeUndeformedNodes();
|
|
}
|
|
public string[] AddPartsFromMesh(FeMesh mesh, string[] partNames)
|
|
{
|
|
_mesh.Nodes = _undeformedNodes;
|
|
string[] addedPartNames = _mesh.AddPartsFromMesh(mesh, partNames, null, null, false);
|
|
InitializeUndeformedNodes();
|
|
return addedPartNames;
|
|
}
|
|
public string[] RemoveParts(string[] partNames)
|
|
{
|
|
_mesh.Nodes = _undeformedNodes;
|
|
string[] removedPartNames;
|
|
_mesh.RemoveParts(partNames, out removedPartNames, false);
|
|
InitializeUndeformedNodes();
|
|
return removedPartNames;
|
|
}
|
|
private void InitializeUndeformedNodes()
|
|
{
|
|
_undeformedNodes = new Dictionary<int, FeNode>(_mesh.Nodes.Count());
|
|
foreach (var entry in _mesh.Nodes) _undeformedNodes.Add(entry.Key, new FeNode(entry.Value));
|
|
ResetScaleStepIncrement();
|
|
}
|
|
private void ResetScaleStepIncrement()
|
|
{
|
|
_scale = -1;
|
|
_stepId = -1;
|
|
_stepIncrementId = -1;
|
|
}
|
|
public void AddResults(FeResults results)
|
|
{
|
|
int[] stepIds = GetAllStepIds();
|
|
int lastStepId = stepIds.Last();
|
|
int[] stepIncrementIds = GetStepIncrementIds(lastStepId);
|
|
int lastStepIncrementId = stepIncrementIds.Last();
|
|
string[] fieldNames = GetAllFieldNames();
|
|
string[] componentNames;
|
|
//
|
|
float lastTime = 0;
|
|
FieldData fieldData;
|
|
foreach (var fieldName in fieldNames)
|
|
{
|
|
componentNames = GetFieldComponentNames(fieldName);
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
fieldData = GetFieldData(fieldName, componentName, lastStepId, lastStepIncrementId);
|
|
if (fieldData.Valid)
|
|
{
|
|
if (fieldData.Time > lastTime) lastTime = fieldData.Time;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
AddFieldOutputs(results, lastTime, lastStepId, lastStepIncrementId);
|
|
AddHistoryOutputs(results, lastTime);
|
|
//
|
|
ReplaceAllResultFieldOutputs();
|
|
}
|
|
private void AddFieldOutputs(FeResults results, float lastTime, int lastStepId, int lastStepIncrementId)
|
|
{
|
|
Field lastWearDepthField = GetField(new FieldData(FOFieldNames.WearDepth, "", lastStepId, lastStepIncrementId), false);
|
|
//if (lastWearDepthField == null) throw new NotSupportedException();
|
|
//
|
|
Field currentField;
|
|
FieldData fieldData;
|
|
FieldComponent fc1;
|
|
FieldComponent fc2;
|
|
FieldComponent fc3;
|
|
float[] values1;
|
|
float[] values2;
|
|
float[] values3;
|
|
float[] magnitude;
|
|
//float[][] vectors = GetLocalVectors(FOFieldNames.WearDepth);
|
|
float[][] vectors = SubtractMeshPositions(results, this);
|
|
float[][] vectorsWD = GetLocalVectors(FOFieldNames.WearDepth);
|
|
// Add mesh deformation
|
|
foreach (var entry in results._fields.ToArray()) // copy to modify
|
|
{
|
|
fieldData = entry.Key;
|
|
currentField = entry.Value;
|
|
//
|
|
if (fieldData.StepId == 0 && fieldData.StepIncrementId == 0) continue; // Zero increment - Find all occurrences!!!
|
|
//
|
|
if (fieldData.Name == FOFieldNames.WearDepth)
|
|
{
|
|
// H1
|
|
values1 = currentField.GetComponentValues(FOComponentNames.H1);
|
|
magnitude = new float[values1.Length];
|
|
for (int i = 0; i < values1.Length; i++)
|
|
{
|
|
values1[i] += vectorsWD[0][i];
|
|
magnitude[i] += values1[i] * values1[i];
|
|
}
|
|
fc1 = new FieldComponent(FOComponentNames.H1, values1);
|
|
// H2
|
|
values2 = currentField.GetComponentValues(FOComponentNames.H2);
|
|
for (int i = 0; i < values2.Length; i++)
|
|
{
|
|
values2[i] += vectorsWD[1][i];
|
|
magnitude[i] += values2[i] * values2[i];
|
|
}
|
|
fc2 = new FieldComponent(FOComponentNames.H2, values2);
|
|
// H3
|
|
values3 = currentField.GetComponentValues(FOComponentNames.H3);
|
|
for (int i = 0; i < values3.Length; i++)
|
|
{
|
|
values3[i] += vectorsWD[2][i];
|
|
magnitude[i] += values3[i] * values3[i];
|
|
}
|
|
fc3 = new FieldComponent(FOComponentNames.H3, values3);
|
|
// Magnitude
|
|
for (int i = 0; i < magnitude.Length; i++) magnitude[i] = (float)Math.Sqrt(magnitude[i]);
|
|
// Create field
|
|
currentField = new Field(fieldData.Name);
|
|
currentField.AddComponent(FOComponentNames.All, magnitude);
|
|
currentField.AddComponent(fc1);
|
|
currentField.AddComponent(fc2);
|
|
currentField.AddComponent(fc3);
|
|
// Replace field
|
|
results.ReplaceOrAddField(fieldData, currentField);
|
|
}
|
|
else if (fieldData.Name == FOFieldNames.MeshDeformation || fieldData.Name == FOFieldNames.DispDeformationDepth)
|
|
{
|
|
// U1
|
|
values1 = currentField.GetComponentValues(FOComponentNames.U1);
|
|
magnitude = new float[values1.Length];
|
|
for (int i = 0; i < values1.Length; i++)
|
|
{
|
|
values1[i] += vectors[0][i];
|
|
magnitude[i] += values1[i] * values1[i];
|
|
}
|
|
fc1 = new FieldComponent(FOComponentNames.U1, values1);
|
|
// U2
|
|
values2 = currentField.GetComponentValues(FOComponentNames.U2);
|
|
for (int i = 0; i < values2.Length; i++)
|
|
{
|
|
values2[i] += vectors[1][i];
|
|
magnitude[i] += values2[i] * values2[i];
|
|
}
|
|
fc2 = new FieldComponent(FOComponentNames.U2, values2);
|
|
// U3
|
|
values3 = currentField.GetComponentValues(FOComponentNames.U3);
|
|
for (int i = 0; i < values3.Length; i++)
|
|
{
|
|
values3[i] += vectors[2][i];
|
|
magnitude[i] += values3[i] * values3[i];
|
|
}
|
|
fc3 = new FieldComponent(FOComponentNames.U3, values3);
|
|
// Magnitude
|
|
for (int i = 0; i < magnitude.Length; i++) magnitude[i] = (float)Math.Sqrt(magnitude[i]);
|
|
// Create field
|
|
currentField = new Field(fieldData.Name);
|
|
currentField.AddComponent(FOComponentNames.All, magnitude);
|
|
currentField.AddComponent(fc1);
|
|
currentField.AddComponent(fc2);
|
|
currentField.AddComponent(fc3);
|
|
// Replace field
|
|
results.ReplaceOrAddField(fieldData, currentField);
|
|
}
|
|
}
|
|
// Copy all fields
|
|
foreach (var entry in results._fields)
|
|
{
|
|
fieldData = entry.Key;
|
|
currentField = entry.Value;
|
|
//
|
|
if (fieldData.StepId == 0 && fieldData.StepIncrementId == 0) continue; // Zero increment - Find all occurrences!!!
|
|
//
|
|
fieldData.Time += lastTime;
|
|
fieldData.StepId += lastStepId;
|
|
//
|
|
AddField(fieldData, currentField);
|
|
}
|
|
}
|
|
private void AddHistoryOutputs(FeResults results, float lastTime)
|
|
{
|
|
if (results._history == null) return;
|
|
// Append all entries
|
|
HistoryResultEntries historyResultEntry;
|
|
foreach (var setEntry in results._history.Sets)
|
|
{
|
|
foreach (var fieldEntry in setEntry.Value.Fields)
|
|
{
|
|
foreach (var componentEntry in fieldEntry.Value.Components)
|
|
{
|
|
foreach (var entry in componentEntry.Value.Entries)
|
|
{
|
|
entry.Value.ShiftTime(lastTime);
|
|
historyResultEntry = GetHistoryResultEntry(setEntry.Key, fieldEntry.Key, componentEntry.Key, entry.Key);
|
|
if (historyResultEntry != null)
|
|
{
|
|
historyResultEntry.Append(entry.Value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private static float[][] SubtractMeshPositions(FeResults results1, FeResults results2)
|
|
{
|
|
if (results1._undeformedNodes.Count == results2._undeformedNodes.Count)
|
|
{
|
|
int id;
|
|
FeNode node1;
|
|
FeNode node2;
|
|
float[][] diff = new float[3][];
|
|
diff[0] = new float[results1._undeformedNodes.Count];
|
|
diff[1] = new float[results1._undeformedNodes.Count];
|
|
diff[2] = new float[results1._undeformedNodes.Count];
|
|
//
|
|
foreach (var entry in results1._undeformedNodes)
|
|
{
|
|
node1 = entry.Value;
|
|
node2 = results2._undeformedNodes[node1.Id];
|
|
id = results1._nodeIdsLookUp[node1.Id];
|
|
//
|
|
diff[0][id] = (float)(node1.X - node2.X);
|
|
diff[1][id] = (float)(node1.Y - node2.Y);
|
|
diff[2][id] = (float)(node1.Z - node2.Z);
|
|
}
|
|
return diff;
|
|
}
|
|
else return null;
|
|
}
|
|
// Mesh deformation
|
|
private string GetInternalDeformationFieldOutputName(int stepId, int stepIncrementId)
|
|
{
|
|
if (_deformationFieldOutputName == FOFieldNames.Disp)
|
|
{
|
|
if (_complexResultType == ComplexResultTypeEnum.Imaginary ||
|
|
_complexResultType == ComplexResultTypeEnum.Magnitude ||
|
|
_complexResultType == ComplexResultTypeEnum.Phase ||
|
|
_complexResultType == ComplexResultTypeEnum.Max ||
|
|
_complexResultType == ComplexResultTypeEnum.AngleAtMax ||
|
|
_complexResultType == ComplexResultTypeEnum.Min ||
|
|
_complexResultType == ComplexResultTypeEnum.AngleAtMin)
|
|
{
|
|
FieldData fieldData = new FieldData(FOFieldNames.DispR, null, stepId, stepIncrementId);
|
|
Field field = GetField(fieldData, false);
|
|
if (field != null) return FOFieldNames.DispR;
|
|
}
|
|
}
|
|
return _deformationFieldOutputName;
|
|
}
|
|
public void SetMeshDeformation(float scale, int stepId, int stepIncrementId)
|
|
{
|
|
if (scale != _scale || stepId != _stepId || stepIncrementId != _stepIncrementId || _complexResultChanged)
|
|
{
|
|
_scale = scale;
|
|
_stepId = stepId;
|
|
_stepIncrementId = stepIncrementId;
|
|
_complexResultChanged = false;
|
|
//
|
|
int resultNodeId;
|
|
double[] offset;
|
|
FeNode node;
|
|
FeNode deformedNode;
|
|
Dictionary<int, FeNode> deformedNodes = null;
|
|
//
|
|
if (_scale != 0)
|
|
{
|
|
float[][] deformations = GetNodalMeshDeformations(_stepId, _stepIncrementId);
|
|
if (deformations != null)
|
|
{
|
|
deformedNodes = new Dictionary<int, FeNode>();
|
|
//
|
|
foreach (var entry in _mesh.Parts)
|
|
{
|
|
offset = entry.Value.Offset;
|
|
if (offset == null) offset = new double[3];
|
|
//
|
|
foreach (var nodeId in entry.Value.NodeLabels)
|
|
{
|
|
node = _undeformedNodes[nodeId];
|
|
// Result parts
|
|
if (_nodeIdsLookUp.TryGetValue(node.Id, out resultNodeId))
|
|
{
|
|
deformedNode = new FeNode(node.Id,
|
|
node.X + offset[0] + _scale * deformations[0][resultNodeId],
|
|
node.Y + offset[1] + _scale * deformations[1][resultNodeId],
|
|
node.Z + offset[2] + _scale * deformations[2][resultNodeId]);
|
|
}
|
|
// Geometry parts
|
|
else
|
|
{
|
|
if (offset[0] != 0 || offset[1] != 0 || offset[2] != 0)
|
|
{
|
|
deformedNode = new FeNode(node.Id,
|
|
node.X + offset[0],
|
|
node.Y + offset[1],
|
|
node.Z + offset[2]);
|
|
}
|
|
else deformedNode = node;
|
|
}
|
|
// Check for merged nodes as in compound parts
|
|
if (!deformedNodes.ContainsKey(deformedNode.Id))
|
|
deformedNodes.Add(deformedNode.Id, deformedNode);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (deformedNodes == null)
|
|
{
|
|
deformedNodes = new Dictionary<int, FeNode>();
|
|
foreach (var entry in _mesh.Parts)
|
|
{
|
|
offset = entry.Value.Offset;
|
|
//
|
|
foreach (var nodeId in entry.Value.NodeLabels)
|
|
{
|
|
node = _undeformedNodes[nodeId];
|
|
|
|
if (offset[0] != 0 || offset[1] != 0 || offset[2] != 0)
|
|
{
|
|
deformedNode = new FeNode(node.Id,
|
|
node.X + offset[0],
|
|
node.Y + offset[1],
|
|
node.Z + offset[2]);
|
|
}
|
|
else deformedNode = node;
|
|
|
|
// Result parts
|
|
//if (_nodeIdsLookUp.TryGetValue(node.Id, out resultNodeId))
|
|
// deformedNode = new FeNode(node.Id, node.X + offset[0], node.Y + offset[1], node.Z + offset[2]);
|
|
// Geometry parts
|
|
//else deformedNode = node;
|
|
|
|
|
|
// Check for merged nodes as in compound parts
|
|
if (!deformedNodes.ContainsKey(deformedNode.Id))
|
|
deformedNodes.Add(deformedNode.Id, deformedNode);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
_mesh.Nodes = deformedNodes;
|
|
}
|
|
}
|
|
public void SetPartDeformation(BasePart part, float scale, int stepId, int stepIncrementId)
|
|
{
|
|
// Reset global mesh deformation settings
|
|
ResetScaleStepIncrement();
|
|
//
|
|
bool scaled = false;
|
|
double[] offset;
|
|
FeNode node;
|
|
FeNode deformedNode;
|
|
//
|
|
if (scale != 0)
|
|
{
|
|
float[][] deformations = GetNodalMeshDeformations(stepId, stepIncrementId);
|
|
if (deformations != null)
|
|
{
|
|
scaled = true;
|
|
int resultNodeId;
|
|
offset = part.Offset;
|
|
//
|
|
foreach (var nodeId in part.NodeLabels)
|
|
{
|
|
resultNodeId = _nodeIdsLookUp[nodeId];
|
|
node = _undeformedNodes[nodeId];
|
|
//
|
|
deformedNode = new FeNode(node.Id,
|
|
node.X + offset[0] + scale * deformations[0][resultNodeId],
|
|
node.Y + offset[1] + scale * deformations[1][resultNodeId],
|
|
node.Z + offset[2] + scale * deformations[2][resultNodeId]);
|
|
_mesh.Nodes[deformedNode.Id] = deformedNode;
|
|
}
|
|
}
|
|
}
|
|
if (!scaled)
|
|
{
|
|
offset = part.Offset;
|
|
foreach (var nodeId in part.NodeLabels)
|
|
{
|
|
node = _undeformedNodes[nodeId];
|
|
deformedNode = new FeNode(node.Id, node.X + offset[0], node.Y + offset[1], node.Z + offset[2]);
|
|
_mesh.Nodes[node.Id] = deformedNode;
|
|
}
|
|
}
|
|
}
|
|
public float[][] GetNodalMeshDeformations(int stepId, int stepIncrementId)
|
|
{
|
|
string deformationFieldOutputName = GetInternalDeformationFieldOutputName(stepId, stepIncrementId);
|
|
return GetNodalMeshDeformations(deformationFieldOutputName, stepId, stepIncrementId);
|
|
}
|
|
public float[][] GetNodalMeshDeformations(string deformationFieldOutputName, int stepId, int stepIncrementId)
|
|
{
|
|
float[][] deformations = null;
|
|
string[] componentNames = GetDeformationFieldOutputComponentNames(deformationFieldOutputName);
|
|
string[] existingComponentNames = GetFieldComponentNames(deformationFieldOutputName);
|
|
//
|
|
if (existingComponentNames != null &&
|
|
existingComponentNames.Contains(componentNames[0]) &&
|
|
existingComponentNames.Contains(componentNames[1]) &&
|
|
existingComponentNames.Contains(componentNames[2]))
|
|
{
|
|
Field deformationField = GetField(new FieldData(deformationFieldOutputName, "", stepId, stepIncrementId), false);
|
|
if (deformationField == null) return null;
|
|
//
|
|
deformations = new float[3][];
|
|
deformations[0] = deformationField.GetComponentValues(componentNames[0]);
|
|
if (deformations[0] == null) return null;
|
|
deformations[1] = deformationField.GetComponentValues(componentNames[1]);
|
|
if (deformations[1] == null) return null;
|
|
deformations[2] = deformationField.GetComponentValues(componentNames[2]);
|
|
if (deformations[2] == null) return null;
|
|
}
|
|
return deformations;
|
|
}
|
|
public static OrderedDictionary<string, string> GetPossibleDeformationFieldOutputNamesMap()
|
|
{
|
|
OrderedDictionary<string, string> names =
|
|
new OrderedDictionary<string, string>("Deformation Names", StringComparer.OrdinalIgnoreCase);
|
|
names.Add("Displacements", FOFieldNames.Disp);
|
|
names.Add("Forces", FOFieldNames.Forc);
|
|
names.Add("Surface Normals", FOFieldNames.SurfaceNormal);
|
|
names.Add("Wear Depths", FOFieldNames.WearDepth);
|
|
names.Add("Mesh Deformation", FOFieldNames.MeshDeformation);
|
|
names.Add("Disp&Def&Depth", FOFieldNames.DispDeformationDepth);
|
|
return names;
|
|
}
|
|
public static string[] GetPossibleDeformationFieldOutputNames()
|
|
{
|
|
return GetPossibleDeformationFieldOutputNamesMap().Keys.ToArray();
|
|
}
|
|
public string[] GetExistingDeformationFieldOutputNames()
|
|
{
|
|
string[] fieldNames = GetAllFieldNames();
|
|
OrderedDictionary<string, string> possibleNames = GetPossibleDeformationFieldOutputNamesMap();
|
|
List<string> existingFieldNames = new List<string>();
|
|
foreach (var entry in possibleNames)
|
|
{
|
|
if (fieldNames.Contains(entry.Value)) existingFieldNames.Add(entry.Key);
|
|
}
|
|
return existingFieldNames.ToArray();
|
|
}
|
|
private string[] GetDeformationFieldOutputComponentNames(string deformationFieldOutputName)
|
|
{
|
|
string[] componentNames = null;
|
|
if (deformationFieldOutputName == FOFieldNames.Disp || deformationFieldOutputName == FOFieldNames.DispR)
|
|
{
|
|
componentNames = new string[] { FOComponentNames.U1, FOComponentNames.U2, FOComponentNames.U3 };
|
|
}
|
|
else if (deformationFieldOutputName == FOFieldNames.Forc)
|
|
{
|
|
componentNames = new string[] { FOComponentNames.F1, FOComponentNames.F2, FOComponentNames.F3 };
|
|
}
|
|
else if (deformationFieldOutputName == FOFieldNames.SurfaceNormal)
|
|
{
|
|
componentNames = new string[] { FOComponentNames.N1, FOComponentNames.N2, FOComponentNames.N3 };
|
|
}
|
|
else if (deformationFieldOutputName == FOFieldNames.WearDepth)
|
|
{
|
|
componentNames = new string[] { FOComponentNames.H1, FOComponentNames.H2, FOComponentNames.H3 };
|
|
}
|
|
else if (deformationFieldOutputName == FOFieldNames.MeshDeformation)
|
|
{
|
|
componentNames = new string[] { FOComponentNames.U1, FOComponentNames.U2, FOComponentNames.U3 };
|
|
}
|
|
else if (deformationFieldOutputName == FOFieldNames.DispDeformationDepth)
|
|
{
|
|
componentNames = new string[] { FOComponentNames.U1, FOComponentNames.U2, FOComponentNames.U3 };
|
|
}
|
|
return componentNames;
|
|
}
|
|
// Complex
|
|
public bool ContainsComplexResults()
|
|
{
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Value.Complex) return true;
|
|
}
|
|
return false;
|
|
}
|
|
public void SetComplexResultTypeAndAngle(ComplexResultTypeEnum complexResultType, float complexAngleDeg,
|
|
FieldData fieldData = null)
|
|
{
|
|
if (complexResultType != _complexResultType ||
|
|
(_complexResultType == ComplexResultTypeEnum.RealAtAngle && complexAngleDeg != _complexAngleDeg))
|
|
{
|
|
_complexResultType = complexResultType;
|
|
_complexAngleDeg = complexAngleDeg;
|
|
_complexResultChanged = true;
|
|
// Compute the complex result
|
|
SetComplexResult(fieldData);
|
|
// If onlyThisField is used (animation) then also compute the deformations
|
|
if (fieldData != null)
|
|
{
|
|
string defFieldName = GetInternalDeformationFieldOutputName(fieldData.StepId, fieldData.StepIncrementId);
|
|
if (defFieldName != fieldData.Name)
|
|
{
|
|
fieldData = GetFieldData(defFieldName, null, fieldData.StepId, fieldData.StepIncrementId);
|
|
SetComplexResult(fieldData);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private int GetComplexResultTypeId()
|
|
{
|
|
if (_complexResultType == ComplexResultTypeEnum.Real) return 1;
|
|
else if (_complexResultType == ComplexResultTypeEnum.Imaginary) return 2;
|
|
else if (_complexResultType == ComplexResultTypeEnum.Magnitude) return 3;
|
|
else if (_complexResultType == ComplexResultTypeEnum.Phase) return 4;
|
|
else if (_complexResultType == ComplexResultTypeEnum.RealAtAngle) return -1;
|
|
else if (_complexResultType == ComplexResultTypeEnum.Max) return 5;
|
|
else if (_complexResultType == ComplexResultTypeEnum.AngleAtMax) return 6;
|
|
else if (_complexResultType == ComplexResultTypeEnum.Min) return 7;
|
|
else if (_complexResultType == ComplexResultTypeEnum.AngleAtMin) return 8;
|
|
else throw new NotSupportedException();
|
|
}
|
|
public void PrepareComplexResults()
|
|
{
|
|
int stepId;
|
|
int incrementId;
|
|
int[] stepIds = GetAllStepIds();
|
|
int[] incrementIds;
|
|
float[] valuesR;
|
|
float[] valuesI;
|
|
float[] valuesMag;
|
|
float[] valuesPha;
|
|
FieldData fieldData;
|
|
FieldData fieldDataR;
|
|
FieldData fieldDataI;
|
|
FieldData fieldDataMag;
|
|
FieldData fieldDataPha;
|
|
FieldData fieldDataMax;
|
|
FieldData fieldDataMaxAng;
|
|
FieldData fieldDataMin;
|
|
FieldData fieldDataMinAng;
|
|
Field field;
|
|
Field fieldR;
|
|
Field fieldI;
|
|
Field fieldMag;
|
|
Field fieldPha;
|
|
Field fieldMax;
|
|
Field fieldMaxAng;
|
|
Field fieldMin;
|
|
Field fieldMinAng;
|
|
//
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
stepId = stepIds[i];
|
|
incrementIds = GetStepIncrementIds(stepId);
|
|
for (int j = 0; j < incrementIds.Length; j++)
|
|
{
|
|
incrementId = incrementIds[j];
|
|
//
|
|
foreach (var complexFieldNames in ComplexFieldNames)
|
|
{
|
|
fieldData = GetFieldData(complexFieldNames[0], null, stepId, incrementId);
|
|
field = GetField(fieldData, false);
|
|
fieldDataI = GetFieldData(complexFieldNames[2], null, stepId, incrementId);
|
|
fieldI = GetField(fieldDataI, false);
|
|
//
|
|
if (field != null && fieldI != null)
|
|
{
|
|
// Default
|
|
field.Complex = true;
|
|
ReplaceOrAddField(fieldData, field);
|
|
// Imaginary
|
|
fieldI.Complex = true;
|
|
fieldI.RemoveInvariants();
|
|
ReplaceOrAddField(fieldDataI, fieldI);
|
|
// Real
|
|
fieldDataR = new FieldData(fieldData); // copy
|
|
fieldDataR.Name = complexFieldNames[1];
|
|
//
|
|
fieldR = new Field(field); // copy
|
|
fieldR.Name = fieldDataR.Name;
|
|
//
|
|
ReplaceOrAddField(fieldDataR, fieldR);
|
|
// Magnitude
|
|
fieldDataMag = new FieldData(fieldDataR);
|
|
fieldDataMag.Name = complexFieldNames[3];
|
|
//
|
|
fieldMag = new Field(fieldR); // copy
|
|
fieldMag.Name = fieldDataMag.Name;
|
|
fieldMag.RemoveInvariants();
|
|
// Phase
|
|
fieldDataPha = new FieldData(fieldDataR);
|
|
fieldDataPha.Name = complexFieldNames[4];
|
|
//
|
|
fieldPha = new Field(fieldR); // copy
|
|
fieldPha.Name = fieldDataPha.Name;
|
|
fieldPha.RemoveInvariants();
|
|
// Max
|
|
fieldDataMax = new FieldData(fieldData); // copy
|
|
fieldDataMax.Name = complexFieldNames[5];
|
|
//
|
|
fieldMax = new Field(field); // copy
|
|
fieldMax.Name = fieldDataMax.Name;
|
|
fieldMax.DataState = DataStateEnum.UpdateComplexMinMax;
|
|
fieldMax.RemoveNonInvariants();
|
|
fieldMax.SetComponentValuesTo(-float.MaxValue);
|
|
//
|
|
ReplaceOrAddField(fieldDataMax, fieldMax);
|
|
// Max angle
|
|
fieldDataMaxAng = new FieldData(fieldDataMax); // copy
|
|
fieldDataMaxAng.Name = complexFieldNames[6];
|
|
//
|
|
fieldMaxAng = new Field(fieldMax); // copy
|
|
fieldMaxAng.Name = fieldDataMaxAng.Name;
|
|
fieldMaxAng.DataState = DataStateEnum.UpdateComplexMinMax;
|
|
fieldMaxAng.SetComponentValuesToZero();
|
|
//
|
|
ReplaceOrAddField(fieldDataMaxAng, fieldMaxAng);
|
|
// Min
|
|
fieldDataMin = new FieldData(fieldData); // copy
|
|
fieldDataMin.Name = complexFieldNames[7];
|
|
//
|
|
fieldMin = new Field(field); // copy
|
|
fieldMin.Name = fieldDataMin.Name;
|
|
fieldMin.DataState = DataStateEnum.UpdateComplexMinMax;
|
|
fieldMin.RemoveNonInvariants();
|
|
fieldMin.SetComponentValuesTo(float.MaxValue);
|
|
//
|
|
ReplaceOrAddField(fieldDataMin, fieldMin);
|
|
// Min angle
|
|
fieldDataMinAng = new FieldData(fieldDataMin); // copy
|
|
fieldDataMinAng.Name = complexFieldNames[8];
|
|
//
|
|
fieldMinAng = new Field(fieldMin); // copy
|
|
fieldMinAng.Name = fieldDataMinAng.Name;
|
|
fieldMinAng.DataState = DataStateEnum.UpdateComplexMinMax;
|
|
fieldMinAng.SetComponentValuesToZero();
|
|
//
|
|
ReplaceOrAddField(fieldDataMinAng, fieldMinAng);
|
|
// Compute magnitude and phase
|
|
string[] componentNames = fieldMag.GetComponentNames();
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
if (!field.IsComponentInvariant(componentName))
|
|
{
|
|
valuesR = fieldR.GetComponentValues(componentName);
|
|
valuesI = fieldI.GetComponentValues(componentName);
|
|
valuesMag = new float[valuesR.Length];
|
|
valuesPha = new float[valuesR.Length];
|
|
//
|
|
for (int k = 0; k < valuesR.Length; k++)
|
|
{
|
|
valuesMag[k] = Tools.GetComplexMagnitude(valuesR[k], valuesI[k]);
|
|
valuesPha[k] = Tools.GetComplexPhaseDeg(valuesR[k], valuesI[k]);
|
|
}
|
|
fieldMag.ReplaceComponent(componentName, new FieldComponent(componentName, valuesMag));
|
|
fieldPha.ReplaceComponent(componentName, new FieldComponent(componentName, valuesPha));
|
|
}
|
|
}
|
|
//
|
|
ReplaceOrAddField(fieldDataMag, fieldMag);
|
|
ReplaceOrAddField(fieldDataPha, fieldPha);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void RemoveComplexResults()
|
|
{
|
|
HashSet<string> fieldNamesToRemove = new HashSet<string>();
|
|
for (int i = 0; i < ComplexFieldNames.Length; i++)
|
|
{
|
|
for (int j = 0; j < ComplexFieldNames[i].Length; j++)
|
|
{
|
|
if (j != 0 && j != 2) fieldNamesToRemove.Add(ComplexFieldNames[i][j]);
|
|
}
|
|
}
|
|
RemoveResultFieldOutputs(fieldNamesToRemove.ToArray());
|
|
}
|
|
public void SetComplexResult(FieldData onlyThisField)
|
|
{
|
|
if (_complexResultType == ComplexResultTypeEnum.RealAtAngle) SetComplexResultToAngle(onlyThisField);
|
|
else SetToExistingComplexResult(onlyThisField);
|
|
//
|
|
SetResultFieldOutputLimitsToRecompute();
|
|
}
|
|
private void SetToExistingComplexResult(FieldData onlyThisField)
|
|
{
|
|
int stepId;
|
|
int incrementId;
|
|
int[] stepIds = GetAllStepIds();
|
|
int[] incrementIds;
|
|
FieldData fieldData;
|
|
FieldData fieldDataExisting;
|
|
Field field;
|
|
Field fieldExisting;
|
|
//
|
|
int fieldNameId = GetComplexResultTypeId();
|
|
//
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
stepId = stepIds[i];
|
|
if (onlyThisField != null && onlyThisField.StepId != stepId) continue;
|
|
//
|
|
incrementIds = GetStepIncrementIds(stepId);
|
|
for (int j = 0; j < incrementIds.Length; j++)
|
|
{
|
|
incrementId = incrementIds[j];
|
|
if (onlyThisField != null && onlyThisField.StepIncrementId != incrementId) continue;
|
|
//
|
|
foreach (var complexFieldNames in ComplexFieldNames)
|
|
{
|
|
if (onlyThisField != null && onlyThisField.Name != complexFieldNames[0]) continue;
|
|
//
|
|
fieldDataExisting = GetFieldData(complexFieldNames[fieldNameId], null, stepId, incrementId);
|
|
fieldExisting = GetField(fieldDataExisting, false);
|
|
//
|
|
if (fieldExisting != null)
|
|
{
|
|
fieldData = new FieldData(fieldDataExisting);
|
|
fieldData.Name = complexFieldNames[0];
|
|
//
|
|
field = new Field(fieldExisting);
|
|
field.Complex = true;
|
|
field.Name = complexFieldNames[0];
|
|
//
|
|
ReplaceOrAddField(fieldData, field);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void SetComplexResultToAngle(FieldData onlyThisField)
|
|
{
|
|
int stepId;
|
|
int incrementId;
|
|
int[] stepIds = GetAllStepIds();
|
|
int[] incrementIds;
|
|
FieldData fieldData;
|
|
FieldData fieldDataMag;
|
|
FieldData fieldDataPha;
|
|
Field field;
|
|
Field fieldMag;
|
|
Field fieldPha;
|
|
float[] valuesMag;
|
|
float[] valuesPha;
|
|
float[] valuesAngle;
|
|
//
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
stepId = stepIds[i];
|
|
if (onlyThisField != null && onlyThisField.StepId != stepId) continue;
|
|
//
|
|
incrementIds = GetStepIncrementIds(stepId);
|
|
for (int j = 0; j < incrementIds.Length; j++)
|
|
{
|
|
incrementId = incrementIds[j];
|
|
if (onlyThisField != null && onlyThisField.StepIncrementId != incrementId) continue;
|
|
//
|
|
foreach (var complexFieldNames in ComplexFieldNames)
|
|
{
|
|
if (onlyThisField != null && onlyThisField.Name != complexFieldNames[0]) continue;
|
|
//
|
|
fieldDataMag = GetFieldData(complexFieldNames[3], null, stepId, incrementId);
|
|
fieldMag = GetField(fieldDataMag, false);
|
|
fieldDataPha = GetFieldData(complexFieldNames[4], null, stepId, incrementId);
|
|
fieldPha = GetField(fieldDataPha, false);
|
|
//
|
|
if (fieldMag != null && fieldPha != null)
|
|
{
|
|
fieldData = new FieldData(fieldDataMag);
|
|
fieldData.Name = complexFieldNames[0];
|
|
//
|
|
field = new Field(fieldMag);
|
|
field.Name = complexFieldNames[0];
|
|
field.Complex = true;
|
|
//
|
|
string[] componentNames = field.GetComponentNames();
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
if (!field.IsComponentInvariant(componentName))
|
|
{
|
|
valuesMag = fieldMag.GetComponentValues(componentName);
|
|
valuesPha = fieldPha.GetComponentValues(componentName);
|
|
valuesAngle = new float[valuesMag.Length];
|
|
//
|
|
Parallel.For(0, valuesMag.Length, k =>
|
|
//for (int k = 0; k < valuesMag.Length; k++)
|
|
{
|
|
valuesAngle[k] =
|
|
Tools.GetComplexRealAtAngleFromMagAndPha(valuesMag[k], valuesPha[k], _complexAngleDeg);
|
|
}
|
|
);
|
|
field.ReplaceComponent(componentName, new FieldComponent(componentName, valuesAngle));
|
|
}
|
|
}
|
|
field.ComputeInvariants();
|
|
//
|
|
ReplaceOrAddField(fieldData, field);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void ComputeComplexMaxMin(FieldData onlyThisField)
|
|
{
|
|
if (onlyThisField == null) throw new NotSupportedException();
|
|
//
|
|
FieldData fieldData;
|
|
FieldData fieldDataMag;
|
|
FieldData fieldDataPha;
|
|
FieldData fieldDataMax;
|
|
FieldData fieldDataMaxAng;
|
|
FieldData fieldDataMin;
|
|
FieldData fieldDataMinAng;
|
|
Field field;
|
|
Field fieldMag;
|
|
Field fieldPha;
|
|
Field fieldMax;
|
|
Field fieldMaxAng;
|
|
Field fieldMin;
|
|
Field fieldMinAng;
|
|
//
|
|
int stepId = onlyThisField.StepId;
|
|
int incrementId = onlyThisField.StepIncrementId;
|
|
string[] complexFieldNames;
|
|
//
|
|
for (int i = 0; i < ComplexFieldNames.Length; i++)
|
|
{
|
|
complexFieldNames = ComplexFieldNames[i];
|
|
if (onlyThisField.Name == complexFieldNames[0])
|
|
{
|
|
fieldDataMag = GetFieldData(complexFieldNames[3], null, stepId, incrementId);
|
|
fieldMag = GetField(fieldDataMag, false);
|
|
fieldDataPha = GetFieldData(complexFieldNames[4], null, stepId, incrementId);
|
|
fieldPha = GetField(fieldDataPha, false);
|
|
//
|
|
fieldDataMax = GetFieldData(complexFieldNames[5], null, stepId, incrementId);
|
|
fieldMax = GetField(fieldDataMax, false);
|
|
fieldDataMaxAng = GetFieldData(complexFieldNames[6], null, stepId, incrementId);
|
|
fieldMaxAng = GetField(fieldDataMaxAng, false);
|
|
fieldDataMin = GetFieldData(complexFieldNames[7], null, stepId, incrementId);
|
|
fieldMin = GetField(fieldDataMin, false);
|
|
fieldDataMinAng = GetFieldData(complexFieldNames[8], null, stepId, incrementId);
|
|
fieldMinAng = GetField(fieldDataMinAng, false);
|
|
//
|
|
if (fieldMag != null && fieldPha != null &&
|
|
fieldMax != null && fieldMaxAng != null && fieldMin != null && fieldMinAng != null)
|
|
{
|
|
if (fieldMax.GetComponentNames().Length > 0)
|
|
{
|
|
// Use field date with all components!!!
|
|
fieldData = GetFieldData(complexFieldNames[1], null, stepId, incrementId); // take real
|
|
field = new Field(GetField(fieldData, false)); // copy real
|
|
//
|
|
object myLock = new object();
|
|
int numOfAngles = 360;
|
|
float delta = 360f / numOfAngles; // skip the final anlge which is the same as the first angle
|
|
Parallel.For(0, numOfAngles + 1, j =>
|
|
//for (int j = 0; j < numOfAngles; j++)
|
|
{
|
|
float[] valuesMag;
|
|
float[] valuesPha;
|
|
float[] valuesAngle;
|
|
//
|
|
float angle = j * delta;
|
|
Field fieldP = new Field(field);
|
|
//
|
|
string[] componentNames = fieldP.GetComponentNames();
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
if (!fieldP.IsComponentInvariant(componentName))
|
|
{
|
|
valuesMag = fieldMag.GetComponentValues(componentName);
|
|
valuesPha = fieldPha.GetComponentValues(componentName);
|
|
valuesAngle = new float[valuesMag.Length];
|
|
//
|
|
for (int k = 0; k < valuesMag.Length; k++)
|
|
{
|
|
valuesAngle[k] = Tools.GetComplexRealAtAngleFromMagAndPha(valuesMag[k],
|
|
valuesPha[k], angle);
|
|
}
|
|
fieldP.ReplaceComponent(componentName, new FieldComponent(componentName, valuesAngle));
|
|
}
|
|
}
|
|
fieldP.ComputeInvariants();
|
|
//
|
|
lock (myLock)
|
|
{
|
|
Field.FindMax(fieldMax, fieldMaxAng, fieldP, angle);
|
|
Field.FindMin(fieldMin, fieldMinAng, fieldP, angle);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
//
|
|
fieldMax.DataState = DataStateEnum.OK;
|
|
fieldMaxAng.DataState = DataStateEnum.OK;
|
|
fieldMin.DataState = DataStateEnum.OK;
|
|
fieldMinAng.DataState = DataStateEnum.OK;
|
|
//
|
|
ReplaceOrAddField(fieldDataMax, fieldMax);
|
|
ReplaceOrAddField(fieldDataMaxAng, fieldMaxAng);
|
|
ReplaceOrAddField(fieldDataMin, fieldMin);
|
|
ReplaceOrAddField(fieldDataMinAng, fieldMinAng);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
// Units
|
|
public string GetFieldUnitAbbreviation(FieldData fieldData)
|
|
{
|
|
if (fieldData.Unit != null && fieldData.Unit.Length > 0) return fieldData.Unit;
|
|
else
|
|
{
|
|
GetFieldUnitConverterAndAbbreviation(fieldData.Name, fieldData.Component, fieldData.StepId,
|
|
fieldData.StepIncrementId, out TypeConverter unitConverter,
|
|
out string unitAbbreviation);
|
|
return unitAbbreviation;
|
|
}
|
|
}
|
|
public string GetFieldUnitAbbreviation(string fieldDataName, string componentName, int stepId, int incrementId)
|
|
{
|
|
GetFieldUnitConverterAndAbbreviation(fieldDataName, componentName, stepId, incrementId,
|
|
out TypeConverter unitConverter, out string unitAbbreviation);
|
|
return unitAbbreviation;
|
|
}
|
|
public void GetFieldUnitConverterAndAbbreviation(string fieldDataName, string componentName,
|
|
int stepId, int incrementId,
|
|
out TypeConverter unitConverter,
|
|
out string unitAbbreviation)
|
|
{
|
|
if (_complexResultType == ComplexResultTypeEnum.Phase ||
|
|
_complexResultType == ComplexResultTypeEnum.AngleAtMax ||
|
|
_complexResultType == ComplexResultTypeEnum.AngleAtMin) // speed up
|
|
{
|
|
FieldData fieldData = GetFieldData(fieldDataName, componentName, stepId, incrementId);
|
|
if (fieldData.StepType == StepTypeEnum.SteadyStateDynamics)
|
|
{
|
|
Field field = GetField(fieldData, false);
|
|
if (field.Complex)
|
|
{
|
|
unitConverter = new StringAngleDegConverter();
|
|
unitAbbreviation = StringAngleDegConverter.GetUnitAbbreviation();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "?";
|
|
try
|
|
{
|
|
switch (fieldDataName.ToUpper())
|
|
{
|
|
case FOFieldNames.None:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "";
|
|
break;
|
|
case FOFieldNames.Disp:
|
|
case FOFieldNames.DispR:
|
|
case FOFieldNames.DispI:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.PDisp:
|
|
switch (componentName.ToUpper())
|
|
{
|
|
case FOComponentNames.MAG1:
|
|
case FOComponentNames.MAG2:
|
|
case FOComponentNames.MAG3:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
case FOComponentNames.PHA1:
|
|
case FOComponentNames.PHA2:
|
|
case FOComponentNames.PHA3:
|
|
unitConverter = new StringAngleDegConverter();
|
|
unitAbbreviation = StringAngleDegConverter.GetUnitAbbreviation();
|
|
break;
|
|
}
|
|
break;
|
|
case FOFieldNames.Velo:
|
|
unitConverter = new StringVelocityConverter();
|
|
unitAbbreviation = _unitSystem.VelocityUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.Stress:
|
|
case FOFieldNames.StressR:
|
|
case FOFieldNames.StressI:
|
|
case FOFieldNames.ZZStr:
|
|
case FOFieldNames.ZZStrR:
|
|
case FOFieldNames.ZZStrI:
|
|
case FOFieldNames.Imported: // Imported pressure
|
|
case FOFieldNames.Pressure: // Imported pressure
|
|
unitConverter = new StringPressureConverter();
|
|
unitAbbreviation = _unitSystem.PressureUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.PStress:
|
|
switch (componentName.ToUpper())
|
|
{
|
|
case FOComponentNames.MAGXX:
|
|
case FOComponentNames.MAGYY:
|
|
case FOComponentNames.MAGZZ:
|
|
case FOComponentNames.MAGXY:
|
|
case FOComponentNames.MAGYZ:
|
|
case FOComponentNames.MAGZX:
|
|
unitConverter = new StringPressureConverter();
|
|
unitAbbreviation = _unitSystem.PressureUnitAbbreviation;
|
|
break;
|
|
case FOComponentNames.PHAXX:
|
|
case FOComponentNames.PHAYY:
|
|
case FOComponentNames.PHAZZ:
|
|
case FOComponentNames.PHAXY:
|
|
case FOComponentNames.PHAYZ:
|
|
case FOComponentNames.PHAZX:
|
|
unitConverter = new StringAngleDegConverter();
|
|
unitAbbreviation = StringAngleDegConverter.GetUnitAbbreviation();
|
|
break;
|
|
}
|
|
break;
|
|
case FOFieldNames.ToStrain:
|
|
case FOFieldNames.ToStraiR:
|
|
case FOFieldNames.ToStraiI:
|
|
case FOFieldNames.MeStrain:
|
|
case FOFieldNames.MeStraiR:
|
|
case FOFieldNames.MeStraiI:
|
|
case FOFieldNames.Pe:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "/";
|
|
break;
|
|
case FOFieldNames.Forc:
|
|
case FOFieldNames.ForcR:
|
|
case FOFieldNames.ForcI:
|
|
unitConverter = new StringForceConverter();
|
|
unitAbbreviation = _unitSystem.ForceUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.Ener:
|
|
unitConverter = new StringEnergyPerVolumeConverter();
|
|
unitAbbreviation = _unitSystem.EnergyPerVolumeUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.Error:
|
|
case FOFieldNames.ErrorR:
|
|
case FOFieldNames.ErrorI:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "%";
|
|
break;
|
|
case FOFieldNames.Contact:
|
|
{
|
|
switch (componentName.ToUpper())
|
|
{
|
|
case FOComponentNames.COpen:
|
|
case FOComponentNames.CSlip1:
|
|
case FOComponentNames.CSlip2:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
case FOComponentNames.CPress:
|
|
case FOComponentNames.CShear1:
|
|
case FOComponentNames.CShear2:
|
|
unitConverter = new StringPressureConverter();
|
|
unitAbbreviation = _unitSystem.PressureUnitAbbreviation;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Thermal
|
|
case FOFieldNames.NdTemp:
|
|
unitConverter = new StringTemperatureConverter();
|
|
unitAbbreviation = _unitSystem.TemperatureUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.Flux:
|
|
unitConverter = new StringPowerPerAreaConverter();
|
|
unitAbbreviation = _unitSystem.PowerPerAreaUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.Rfl:
|
|
unitConverter = new StringPowerConverter();
|
|
unitAbbreviation = _unitSystem.PowerUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.HError:
|
|
case FOFieldNames.HErrorI:
|
|
case FOFieldNames.HErrorR:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "%";
|
|
break;
|
|
// Sensitivity
|
|
case FOFieldNames.Norm:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.SenFreq:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "/";
|
|
break;
|
|
// Wear
|
|
case FOFieldNames.SlidingDistance:
|
|
case FOFieldNames.SurfaceNormal:
|
|
case FOFieldNames.WearDepth:
|
|
case FOFieldNames.MeshDeformation:
|
|
case FOFieldNames.DispDeformationDepth:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
// Imported
|
|
case FOFieldNames.Distance:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
case FOFieldNames.ForcePerArea:
|
|
unitConverter = new StringPressureConverter();
|
|
unitAbbreviation = _unitSystem.PressureUnitAbbreviation;
|
|
break;
|
|
default:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "?";
|
|
// Limit
|
|
if (_resultFieldOutputs.TryGetValue(fieldDataName, out ResultFieldOutput rfo1) &&
|
|
rfo1 is ResultFieldOutputLimit rfol)
|
|
{
|
|
unitAbbreviation = "/";
|
|
break;
|
|
}
|
|
// Equation
|
|
else if (_resultFieldOutputs.TryGetValue(fieldDataName, out ResultFieldOutput rfo2) &&
|
|
rfo2 is ResultFieldOutputEquation rfoeq)
|
|
{
|
|
unitAbbreviation = rfoeq.Unit;
|
|
break;
|
|
}
|
|
// OpenFOAM
|
|
if (stepId == 1 && incrementId == 0) unitAbbreviation = "/"; // User field outputs at 0 increment
|
|
else if (componentName.ToUpper() == "ALL" || componentName.ToUpper().StartsWith("VAL")) { }
|
|
else if (_unitSystem.UnitSystemType == UnitSystemType.UNIT_LESS) unitAbbreviation = "";
|
|
else if (Debugger.IsAttached) throw new NotSupportedException();
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
//
|
|
public string GetHistoryUnitAbbreviation(string fieldName, string componentName, int stepId, int incrementId)
|
|
{
|
|
GetHistoryUnitConverterAndAbbreviation(fieldName, componentName, stepId, incrementId ,
|
|
out TypeConverter unitConverter, out string unitAbbreviation);
|
|
return unitAbbreviation;
|
|
}
|
|
public void GetHistoryUnitConverterAndAbbreviation(string fieldName, string componentName,
|
|
int stepId, int incrementId,
|
|
out TypeConverter unitConverter,
|
|
out string unitAbbreviation)
|
|
{
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "?";
|
|
string noSuffixName = HOFieldNames.GetNoSuffixName(fieldName);
|
|
//
|
|
try
|
|
{
|
|
switch (noSuffixName.ToUpper())
|
|
{
|
|
case HOFieldNames.Time:
|
|
unitConverter = new StringTimeConverter();
|
|
unitAbbreviation = _unitSystem.TimeUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.Frequency:
|
|
unitConverter = new StringFrequencyConverter();
|
|
unitAbbreviation = _unitSystem.FrequencyUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.Factor:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "/";
|
|
break;
|
|
case HOFieldNames.Rotation:
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.Buckling:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "/";
|
|
break;
|
|
case HOFieldNames.Displacements:
|
|
case HOFieldNames.RelativeContactDisplacement:
|
|
case HOFieldNames.CenterOgGravityCG:
|
|
case HOFieldNames.MeanSurfaceNormal:
|
|
if (componentName.ToUpper().StartsWith("UR"))
|
|
{
|
|
unitConverter = new StringAngleConverter();
|
|
unitAbbreviation = _unitSystem.AngleUnitAbbreviation;
|
|
}
|
|
else
|
|
{
|
|
unitConverter = new StringLengthConverter();
|
|
unitAbbreviation = _unitSystem.LengthUnitAbbreviation;
|
|
}
|
|
break;
|
|
case HOFieldNames.Velocities:
|
|
if (componentName.ToUpper().StartsWith("VR"))
|
|
{
|
|
unitConverter = new StringRotationalSpeedConverter();
|
|
unitAbbreviation = _unitSystem.RotationalSpeedUnitAbbreviation;
|
|
}
|
|
else
|
|
{
|
|
unitConverter = new StringVelocityConverter();
|
|
unitAbbreviation = _unitSystem.VelocityUnitAbbreviation;
|
|
}
|
|
break;
|
|
case HOFieldNames.SurfaceArea:
|
|
unitConverter = new StringAreaConverter();
|
|
unitAbbreviation = _unitSystem.AreaUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.Volume:
|
|
case HOFieldNames.TotalVolume:
|
|
unitConverter = new StringVolumeConverter();
|
|
unitAbbreviation = _unitSystem.VolumeUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.Forces:
|
|
case HOFieldNames.TotalForce:
|
|
case HOFieldNames.NormalSurfaceForce:
|
|
case HOFieldNames.ShearSurfaceForce:
|
|
case HOFieldNames.TotalSurfaceForce:
|
|
if (componentName.ToUpper().StartsWith("RM"))
|
|
{
|
|
unitConverter = new StringMomentConverter();
|
|
unitAbbreviation = _unitSystem.MomentUnitAbbreviation;
|
|
}
|
|
else
|
|
{
|
|
unitConverter = new StringForceConverter();
|
|
unitAbbreviation = _unitSystem.ForceUnitAbbreviation;
|
|
}
|
|
break;
|
|
case HOFieldNames.Stresses:
|
|
case HOFieldNames.ContactStress:
|
|
unitConverter = new StringPressureConverter();
|
|
unitAbbreviation = _unitSystem.PressureUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.Strains:
|
|
case HOFieldNames.MechanicalStrains:
|
|
case HOFieldNames.EquivalentPlasticStrains:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "/";
|
|
break;
|
|
case HOFieldNames.InternalEnergy:
|
|
case HOFieldNames.TotalInternalEnergy:
|
|
case HOFieldNames.ContactPrintEnergy:
|
|
case HOFieldNames.ContactSpringEnergy:
|
|
unitConverter = new StringEnergyConverter();
|
|
unitAbbreviation = _unitSystem.EnergyUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.InternalEnergyDensity:
|
|
unitConverter = new StringEnergyPerVolumeConverter();
|
|
unitAbbreviation = _unitSystem.EnergyPerVolumeUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.TotalNumberOfContactElements:
|
|
unitConverter = new DoubleConverter();
|
|
unitAbbreviation = "/";
|
|
break;
|
|
case HOFieldNames.MomentAboutOrigin:
|
|
case HOFieldNames.MomentAboutCG:
|
|
unitConverter = new StringMomentConverter();
|
|
unitAbbreviation = _unitSystem.MomentUnitAbbreviation;
|
|
break;
|
|
// Thermal
|
|
case HOFieldNames.Temperatures:
|
|
unitConverter = new StringTemperatureConverter();
|
|
unitAbbreviation = _unitSystem.TemperatureUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.HeatGeneration:
|
|
case HOFieldNames.TotalHeatGeneration:
|
|
case HOFieldNames.BodyHeating:
|
|
case HOFieldNames.TotalBodyHeating:
|
|
unitConverter = new StringPowerConverter();
|
|
unitAbbreviation = _unitSystem.PowerUnitAbbreviation;
|
|
break;
|
|
case HOFieldNames.HeatFlux:
|
|
unitConverter = new StringPowerPerAreaConverter();
|
|
unitAbbreviation = _unitSystem.PowerPerAreaUnitAbbreviation;
|
|
break;
|
|
// Error
|
|
case FOFieldNames.Error:
|
|
default:
|
|
string noSpacesName = noSuffixName.Replace(' ', '_');
|
|
GetFieldUnitConverterAndAbbreviation(noSpacesName.ToUpper(), componentName, stepId, incrementId,
|
|
out unitConverter, out unitAbbreviation);
|
|
if (unitAbbreviation == "?" && Debugger.IsAttached)
|
|
//throw new NotSupportedException();
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
//
|
|
public void CopyPartsFromMesh(FeMesh mesh)
|
|
{
|
|
_mesh.Parts.Clear();
|
|
//
|
|
ResultPart part;
|
|
foreach (var entry in mesh.Parts)
|
|
{
|
|
part = new ResultPart(entry.Value);
|
|
_mesh.Parts.Add(entry.Key, part);
|
|
//
|
|
foreach (var elementId in part.Labels) _mesh.Elements[elementId].PartId = part.PartId;
|
|
}
|
|
}
|
|
public void CopyMeshItemsFromMesh(FeMesh mesh)
|
|
{
|
|
foreach (var entry in mesh.NodeSets)
|
|
{
|
|
_mesh.NodeSets.Add(entry.Key, entry.Value.DeepClone());
|
|
}
|
|
//
|
|
string newName;
|
|
FeElementSet newElementSet;
|
|
foreach (var entry in mesh.ElementSets)
|
|
{
|
|
if (_mesh.ElementSets.ContainsKey(entry.Key))
|
|
newName = _mesh.ElementSets.GetNextNumberedKey(entry.Key);
|
|
else newName = entry.Key;
|
|
//
|
|
newElementSet = entry.Value.DeepClone();
|
|
newElementSet.Name = newName;
|
|
//
|
|
_mesh.ElementSets.Add(newElementSet.Name, newElementSet);
|
|
}
|
|
//
|
|
foreach (var entry in mesh.Surfaces)
|
|
{
|
|
_mesh.Surfaces.Add(entry.Key, entry.Value.DeepClone());
|
|
}
|
|
}
|
|
public void CopyFeatureItemsFromMesh(FeMesh mesh, int resultViewId)
|
|
{
|
|
FeReferencePoint referencePoint;
|
|
foreach (var entry in mesh.ReferencePoints)
|
|
{
|
|
referencePoint = entry.Value.DeepClone();
|
|
referencePoint.CreationData = null;
|
|
referencePoint.CreationIds = null;
|
|
referencePoint.CreatedFrom = FeReferencePointCreatedFrom.Coordinates;
|
|
//
|
|
_mesh.ReferencePoints.Add(entry.Key, referencePoint);
|
|
}
|
|
CoordinateSystem coordinateSystem;
|
|
foreach (var entry in mesh.CoordinateSystems)
|
|
{
|
|
coordinateSystem = entry.Value.DeepClone();
|
|
//
|
|
coordinateSystem.CenterCreationData = null;
|
|
coordinateSystem.CenterCreationIds = null;
|
|
coordinateSystem.CenterCreatedFrom = CsPointCreatedFromEnum.Coordinates;
|
|
coordinateSystem.PointXCreationData = null;
|
|
coordinateSystem.PointXCreationIds = null;
|
|
coordinateSystem.PointXCreatedFrom = CsPointCreatedFromEnum.Coordinates;
|
|
coordinateSystem.PointXYCreationData = null;
|
|
coordinateSystem.PointXYCreationIds = null;
|
|
coordinateSystem.PointXYCreatedFrom = CsPointCreatedFromEnum.Coordinates;
|
|
//
|
|
_mesh.CoordinateSystems.Add(entry.Key, coordinateSystem);
|
|
}
|
|
}
|
|
//
|
|
public void AddField(FieldData fieldData, Field field)
|
|
{
|
|
fieldData = new FieldData(fieldData); // copy
|
|
_fields.Add(fieldData, field);
|
|
_fieldDataHashField.Add(fieldData.GetHashKey(), field);
|
|
}
|
|
public Field GetField(FieldData fieldData, bool update = true)
|
|
{
|
|
Field field;
|
|
string hash = fieldData.GetHashKey();
|
|
if (_fieldDataHashField.TryGetValue(hash, out field))
|
|
{
|
|
if (update)
|
|
{
|
|
if (field.DataState == DataStateEnum.OK) { }
|
|
else if (field.DataState == DataStateEnum.UpdateComplexMinMax)
|
|
{
|
|
ComputeComplexMaxMin(fieldData); // compute max/min
|
|
SetComplexResult(fieldData); // set computed values to default field
|
|
//
|
|
if (_fieldDataHashField.TryGetValue(hash, out field))
|
|
{
|
|
return field;
|
|
}
|
|
}
|
|
else if (field.DataState == DataStateEnum.UpdateResultFieldOutput)
|
|
{
|
|
ComputeResultFieldOutput(fieldData);
|
|
//
|
|
if (_fieldDataHashField.TryGetValue(hash, out field))
|
|
{
|
|
return field;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return field;
|
|
}
|
|
public void ReplaceOrAddField(FieldData fieldData, Field field)
|
|
{
|
|
// Find the result
|
|
string hash = fieldData.GetHashKey();
|
|
if (_fieldDataHashField.ContainsKey(hash))
|
|
{
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.Name.ToUpper() == fieldData.Name.ToUpper() &&
|
|
entry.Key.StepId == fieldData.StepId &&
|
|
entry.Key.StepIncrementId == fieldData.StepIncrementId)
|
|
{
|
|
_fields.Replace(entry.Key, fieldData, field);
|
|
_fieldDataHashField[hash] = field;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
// New field
|
|
else AddField(fieldData, field);
|
|
}
|
|
private void RemoveFields(string[] fieldOutputNames)
|
|
{
|
|
if (_fields != null)
|
|
{
|
|
List<FieldData> fieldsToRemove = new List<FieldData>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (fieldOutputNames.Contains(entry.Key.Name)) fieldsToRemove.Add(entry.Key);
|
|
}
|
|
//
|
|
foreach (var fieldToRemove in fieldsToRemove)
|
|
{
|
|
_fields.Remove(fieldToRemove);
|
|
_fieldDataHashField.Remove(fieldToRemove.GetHashKey());
|
|
}
|
|
}
|
|
}
|
|
public void ComputeVisibleFieldInvariants()
|
|
{
|
|
Parallel.ForEach(_fields, entry =>
|
|
//foreach (var entry in _fields)
|
|
{
|
|
if (FOFieldNames.IsVisible(entry.Key.Name)) entry.Value.ComputeInvariants();
|
|
}
|
|
);
|
|
}
|
|
//
|
|
public string[] GetAllComponentNames()
|
|
{
|
|
HashSet<string> componentNames = new HashSet<string>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
componentNames.UnionWith(entry.Value.GetComponentNames());
|
|
}
|
|
return componentNames.ToArray();
|
|
}
|
|
public string[] GetFieldComponentNames(string fieldName)
|
|
{
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.Name.ToUpper() == fieldName.ToUpper())
|
|
{
|
|
return entry.Value.GetComponentNames();
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
public FieldData[] GetAllFieldData()
|
|
{
|
|
return _fields.Keys.ToArray();
|
|
}
|
|
public FieldData GetFieldData(string name, string component, int stepId, int stepIncrementId, bool exactComponent = false)
|
|
{
|
|
FieldData result;
|
|
// Empty results
|
|
if (stepId == -1 && stepIncrementId == -1)
|
|
{
|
|
result = new FieldData(name, component, stepId, stepIncrementId);
|
|
result.StepType = StepTypeEnum.Static;
|
|
result.Valid = false;
|
|
return result;
|
|
}
|
|
// Zero increment - Find all occurrences!!!
|
|
else if (stepId == 1 && stepIncrementId == 0)
|
|
{
|
|
result = new FieldData(name, component, stepId, stepIncrementId);
|
|
result.StepType = StepTypeEnum.Static;
|
|
//result.Time = 0; // unnecessary since this result does not exits
|
|
return result;
|
|
}
|
|
// Find the result
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.Name == name && entry.Key.StepId == stepId && entry.Key.StepIncrementId == stepIncrementId)
|
|
{
|
|
if (exactComponent)
|
|
{
|
|
if (entry.Value.ContainsComponent(component))
|
|
{
|
|
result = new FieldData(entry.Key);
|
|
result.Component = component;
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
result = new FieldData(entry.Key);
|
|
result.Component = component;
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
// Find other existing result
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.StepId == stepId && entry.Key.StepIncrementId == stepIncrementId)
|
|
{
|
|
result = new FieldData(entry.Key);
|
|
result.Name = name;
|
|
result.Component = component;
|
|
result.Valid = false;
|
|
return result;
|
|
}
|
|
}
|
|
// Nothing found
|
|
result = new FieldData(name, component, stepId, stepIncrementId);
|
|
result.StepType = StepTypeEnum.Static;
|
|
result.Valid = false;
|
|
return result;
|
|
}
|
|
public DataTypeEnum GetFieldDataType(string fieldName)
|
|
{
|
|
DataTypeEnum dataType = DataTypeEnum.None;
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Value.Name == fieldName)
|
|
{
|
|
if (dataType == DataTypeEnum.None) dataType = entry.Value.DataType;
|
|
else if (dataType != entry.Value.DataType) return DataTypeEnum.None;
|
|
}
|
|
}
|
|
return dataType;
|
|
}
|
|
public bool DoesFieldContainsAllNecessaryComponents(string fieldName)
|
|
{
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Value.Name == fieldName)
|
|
{
|
|
if (!entry.Value.ContainsAllNecessaryComponents()) return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
public FieldData GetFirstComponentOfTheFirstFieldAtLastIncrement()
|
|
{
|
|
string name = GetAllFieldNames()[0];
|
|
string component = GetFieldComponentNames(name)[0];
|
|
int stepId = GetAllStepIds().Last();
|
|
int stepIncrementId = GetStepIncrementIds(stepId).Last();
|
|
//
|
|
return GetFieldData(name, component, stepId, stepIncrementId);
|
|
}
|
|
public FieldData GetFirstComponentOfTheFirstFieldAtDefaultIncrement()
|
|
{
|
|
string[] names = GetAllFieldNames();
|
|
FieldData fieldData;
|
|
if (names.Length == 0)
|
|
{
|
|
// There is no data
|
|
fieldData = GetFieldData(FOFieldNames.None, FOComponentNames.None, -1, -1);
|
|
fieldData.Valid = false;
|
|
}
|
|
else
|
|
{
|
|
int stepId = GetAllStepIds().Last();
|
|
int stepIncrementId = GetStepIncrementIds(stepId).Last();
|
|
string name = GetStepFieldNames(stepId)[0];
|
|
string component = GetFieldComponentNames(name)[0];
|
|
//
|
|
fieldData = GetFieldData(name, component, stepId, stepIncrementId);
|
|
if (fieldData == null)
|
|
{
|
|
// There is no data
|
|
fieldData = GetFieldData(FOFieldNames.None, FOComponentNames.None, -1, -1);
|
|
}
|
|
else if (fieldData.StepType == StepTypeEnum.Frequency)
|
|
{
|
|
stepIncrementId = GetStepIncrementIds(stepId).First();
|
|
fieldData = GetFieldData(name, component, stepId, stepIncrementId);
|
|
}
|
|
}
|
|
return fieldData;
|
|
}
|
|
public string[] GetAllFieldNames()
|
|
{
|
|
// Use list for order
|
|
HashSet<string> names = new HashSet<string>();
|
|
foreach (var entry in _fields) names.Add(entry.Key.Name);
|
|
return names.ToArray();
|
|
}
|
|
public string[] GetVisibleFieldNames()
|
|
{
|
|
// Use list for order
|
|
HashSet<string> names = new HashSet<string>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (FOFieldNames.IsVisible(entry.Key.Name)) names.Add(entry.Key.Name);
|
|
}
|
|
return names.ToArray();
|
|
}
|
|
public NamedClass[] GetVisibleFieldsAsNamedItems()
|
|
{
|
|
string[] names = GetVisibleFieldNames();
|
|
NamedClass[] fields = new NamedClass[names.Length];
|
|
for (int i = 0; i < names.Length; i++)
|
|
{
|
|
fields[i] = new EmptyNamedClass(names[i]);
|
|
}
|
|
return fields;
|
|
}
|
|
public string[] GetStepFieldNames(int stepId)
|
|
{
|
|
List<string> names = new List<string>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.StepId == stepId && !names.Contains(entry.Key.Name))
|
|
names.Add(entry.Key.Name);
|
|
}
|
|
return names.ToArray();
|
|
}
|
|
public int[] GetAllStepIds()
|
|
{
|
|
HashSet<int> ids = new HashSet<int>();
|
|
foreach (var entry in _fields) ids.Add(entry.Key.StepId);
|
|
//
|
|
int[] sortedIds = ids.ToArray();
|
|
Array.Sort(sortedIds);
|
|
//
|
|
return sortedIds;
|
|
}
|
|
public int[] GetStepIncrementIds(int stepId)
|
|
{
|
|
HashSet<int> ids = new HashSet<int>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.StepId == stepId)
|
|
{
|
|
if (entry.Key.StepType == StepTypeEnum.Static && stepId == 1 && ids.Count == 0)
|
|
ids.Add(0); // Zero increment - Find all occurrences!!!
|
|
//
|
|
ids.Add(entry.Key.StepIncrementId);
|
|
}
|
|
}
|
|
//
|
|
int[] sortedIds = ids.ToArray();
|
|
Array.Sort(sortedIds);
|
|
//
|
|
return sortedIds;
|
|
}
|
|
public Dictionary<int, int[]> GetExistingIncrementIds(string fieldName, string component,
|
|
int limitToStepId = -1, int limitTostepIncrementId = -1)
|
|
{
|
|
int[] stepIds;
|
|
if (limitToStepId == -1) stepIds = GetAllStepIds();
|
|
else stepIds = new int[] { limitToStepId };
|
|
//
|
|
Dictionary<int, int[]> existingIncrementIds = new Dictionary<int, int[]>();
|
|
if (stepIds.Length == 0)
|
|
{
|
|
existingIncrementIds.Add(-1, new int[] { -1 });
|
|
}
|
|
else
|
|
{
|
|
List<int> stepIncrementIds;
|
|
string fieldHash;
|
|
HashSet<string> fieldHashes = GetAllFieldHashes();
|
|
//
|
|
foreach (int stepId in stepIds)
|
|
{
|
|
stepIncrementIds = new List<int>();
|
|
foreach (int incrementId in GetStepIncrementIds(stepId))
|
|
{
|
|
if (limitTostepIncrementId != -1 && limitTostepIncrementId != incrementId) continue;
|
|
//
|
|
fieldHash = GetFieldHash(fieldName, component, stepId, incrementId);
|
|
//if (FieldExists(fieldName, component, stepId, incrementId)) stepIncrementIds.Add(incrementId);
|
|
if (fieldHashes.Contains(fieldHash)) stepIncrementIds.Add(incrementId);
|
|
}
|
|
existingIncrementIds.Add(stepId, stepIncrementIds.ToArray());
|
|
}
|
|
}
|
|
return existingIncrementIds;
|
|
}
|
|
public Dictionary<int, int[]> GetAllExistingIncrementIds()
|
|
{
|
|
int[] stepIds = GetAllStepIds();
|
|
Dictionary<int, int[]> existingIncrementIds = new Dictionary<int, int[]>();
|
|
if (stepIds.Length == 0)
|
|
{
|
|
existingIncrementIds.Add(-1, new int[] { -1 });
|
|
}
|
|
else
|
|
{
|
|
if (!stepIds.Contains(1))
|
|
{
|
|
existingIncrementIds.Add(1, new int[] { 0 }); // Zero increment - Find all occurrences!!!
|
|
}
|
|
foreach (int stepId in stepIds)
|
|
{
|
|
existingIncrementIds.Add(stepId, GetStepIncrementIds(stepId));
|
|
}
|
|
}
|
|
return existingIncrementIds;
|
|
}
|
|
public Dictionary<int, float> GetMaxStepTime()
|
|
{
|
|
int[] stepIds = GetAllStepIds();
|
|
Dictionary<int, float> stepMaxTime = new Dictionary<int, float>();
|
|
//
|
|
if (stepIds.Length == 0)
|
|
{
|
|
stepMaxTime.Add(-1, -1);
|
|
}
|
|
else
|
|
{
|
|
foreach (var stepId in stepIds) stepMaxTime.Add(stepId, 0);
|
|
if (!stepMaxTime.ContainsKey(0)) stepMaxTime.Add(0, 0); // Zero increment - Find all occurrences!!!
|
|
//
|
|
float time;
|
|
foreach (var entry in _fields)
|
|
{
|
|
stepMaxTime.TryGetValue(entry.Key.StepId, out time);
|
|
if (entry.Key.Time > time) stepMaxTime[entry.Key.StepId] = entry.Key.Time;
|
|
}
|
|
}
|
|
return stepMaxTime;
|
|
}
|
|
public Dictionary<string, string[]> GetAllFiledNameComponentNames()
|
|
{
|
|
HashSet<string> componentNames;
|
|
Dictionary<string, HashSet<string>> filedNameComponentNames = new Dictionary<string, HashSet<string>>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (filedNameComponentNames.TryGetValue(entry.Key.Name, out componentNames))
|
|
componentNames.UnionWith(entry.Value.GetComponentNames());
|
|
else
|
|
filedNameComponentNames.Add(entry.Key.Name, new HashSet<string>(entry.Value.GetComponentNames()));
|
|
}
|
|
//
|
|
Dictionary<string, string[]> filedNameComponentNamesArr = new Dictionary<string, string[]>();
|
|
foreach (var entry in filedNameComponentNames)
|
|
{
|
|
filedNameComponentNamesArr.Add(entry.Key, entry.Value.ToArray());
|
|
}
|
|
return filedNameComponentNamesArr;
|
|
}
|
|
public Dictionary<string, string[]> GetAllVisibleFiledNameComponentNames()
|
|
{
|
|
HashSet<string> componentNames;
|
|
Dictionary<string, HashSet<string>> filedNameComponentNames = new Dictionary<string, HashSet<string>>();
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (!FOFieldNames.IsVisible(entry.Key.Name)) continue;
|
|
//
|
|
if (filedNameComponentNames.TryGetValue(entry.Key.Name, out componentNames))
|
|
componentNames.UnionWith(entry.Value.GetComponentNames());
|
|
else
|
|
filedNameComponentNames.Add(entry.Key.Name, new HashSet<string>(entry.Value.GetComponentNames()));
|
|
}
|
|
//
|
|
Dictionary<string, string[]> filedNameComponentNamesArr = new Dictionary<string, string[]>();
|
|
foreach (var entry in filedNameComponentNames)
|
|
{
|
|
filedNameComponentNamesArr.Add(entry.Key, entry.Value.ToArray());
|
|
}
|
|
return filedNameComponentNamesArr;
|
|
}
|
|
public bool FieldExists(string fieldName, string component, int stepId, int stepIncrementId)
|
|
{
|
|
foreach (var entry in _fields)
|
|
{
|
|
if ((entry.Key.Name.ToUpper() == fieldName.ToUpper() &&
|
|
entry.Value.ContainsComponent(component) &&
|
|
stepId == 1 && stepIncrementId == 0) // Zero increment - Find all occurrences!!!
|
|
||
|
|
(entry.Key.Name.ToUpper() == fieldName.ToUpper() &&
|
|
entry.Value.ContainsComponent(component) &&
|
|
entry.Key.StepId == stepId &&
|
|
entry.Key.StepIncrementId == stepIncrementId))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
private HashSet<string> GetAllFieldHashes()
|
|
{
|
|
HashSet<string> fieldHashes = new HashSet<string>();
|
|
foreach (var fieldEntry in _fields)
|
|
{
|
|
foreach (var componentName in fieldEntry.Value.GetComponentNames())
|
|
{
|
|
fieldHashes.Add(GetFieldHash(fieldEntry.Key.Name, componentName, 1, 0));
|
|
fieldHashes.Add(GetFieldHash(fieldEntry.Key.Name, componentName, fieldEntry.Key.StepId,
|
|
fieldEntry.Key.StepIncrementId));
|
|
}
|
|
}
|
|
return fieldHashes;
|
|
}
|
|
private string GetFieldHash(string fieldName, string component, int stepId, int stepIncrementId)
|
|
{
|
|
return fieldName.ToUpper() + "_" + component.ToUpper() + "_" + stepId.ToString() + "_" + stepIncrementId.ToString();
|
|
}
|
|
//
|
|
public float GetIncrementTime(int stepId, int stepIncrementId)
|
|
{
|
|
if (stepIncrementId == 0) return 0; // Zero increment - Find all occurrences!!!
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.StepId == stepId && entry.Key.StepIncrementId == stepIncrementId)
|
|
{
|
|
return entry.Key.Time;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
public float[] GetValues(FieldData fieldData, int[] globalNodeIds)
|
|
{
|
|
float[] values = null;
|
|
bool zeroIncrement = false;
|
|
//
|
|
if (fieldData.Valid)
|
|
{
|
|
if (fieldData.StepIncrementId == 0) // Zero increment - Find all occurrences!!!
|
|
{
|
|
if (fieldData.StepId == 1) // first step
|
|
{
|
|
values = new float[globalNodeIds.Length];
|
|
zeroIncrement = true;
|
|
}
|
|
}
|
|
//
|
|
if (!zeroIncrement)
|
|
{
|
|
Field field = GetField(fieldData);
|
|
//
|
|
float[] allValues = field.GetComponentValues(fieldData.Component);
|
|
if (allValues == null) return null; // the field became Valid = false during computation
|
|
//
|
|
values = new float[globalNodeIds.Length];
|
|
int globalId;
|
|
int localId;
|
|
for (int i = 0; i < globalNodeIds.Length; i++)
|
|
{
|
|
globalId = globalNodeIds[i];
|
|
if (_nodeIdsLookUp.TryGetValue(globalId, out localId) && localId >= 0 && localId < allValues.Length)
|
|
values[i] = allValues[localId];
|
|
else
|
|
return null;
|
|
}
|
|
|
|
//// Remove frst step
|
|
//fieldData.StepIncrementId = 1;
|
|
////
|
|
//foreach (var entry in _fields)
|
|
//{
|
|
// if (entry.Key.Name.ToUpper() == fieldData.Name.ToUpper() &&
|
|
// entry.Key.StepId == fieldData.StepId &&
|
|
// entry.Key.StepIncrementId == fieldData.StepIncrementId)
|
|
// {
|
|
// float[] allValues = entry.Value.GetComponentValues(fieldData.Component);
|
|
// int globalId;
|
|
// int localId;
|
|
// for (int i = 0; i < globalNodeIds.Length; i++)
|
|
// {
|
|
// globalId = globalNodeIds[i];
|
|
// if (_nodeIdsLookUp.TryGetValue(globalId, out localId) && localId >= 0 && localId < allValues.Length)
|
|
// values[i] -= allValues[localId];
|
|
// else
|
|
// return null;
|
|
// }
|
|
// break;
|
|
// }
|
|
//}
|
|
}
|
|
}
|
|
return values;
|
|
}
|
|
public bool IsComponentInvariant(FieldData fieldData)
|
|
{
|
|
if (fieldData.StepIncrementId == 0) // Zero increment - Find all occurrences!!!
|
|
{
|
|
if (fieldData.StepId == 1) // first step
|
|
return false;
|
|
}
|
|
//
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.Name.ToUpper() == fieldData.Name.ToUpper() &&
|
|
entry.Key.StepId == fieldData.StepId &&
|
|
entry.Key.StepIncrementId == fieldData.StepIncrementId)
|
|
{
|
|
return entry.Value.ContainsComponent(fieldData.Component) &&
|
|
entry.Value.IsComponentInvariant(fieldData.Component);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
public NodesExchangeData GetExtremeValues(string partName, FieldData fieldData)
|
|
{
|
|
return GetScaledExtremeValues(partName, fieldData, 0);
|
|
}
|
|
public NodesExchangeData GetScaledExtremeValues(string partName, FieldData fieldData, float relativeScale)
|
|
{
|
|
if (!fieldData.Valid) return null;
|
|
//
|
|
NodesExchangeData nodesData = new NodesExchangeData();
|
|
nodesData.Ids = new int[2];
|
|
nodesData.Coor = new double[2][];
|
|
nodesData.Values = new float[2];
|
|
int minId = -1;
|
|
int maxId = -1;
|
|
bool zeroIncrement = false;
|
|
FeNode node;
|
|
//
|
|
if (fieldData.StepIncrementId == 0) // Zero increment - Find all occurrences!!!
|
|
{
|
|
if (fieldData.StepId == 1) // first step / zero increment
|
|
{
|
|
minId = _nodeIdsLookUp.Keys.First();
|
|
maxId = minId;
|
|
nodesData.Ids[0] = minId;
|
|
nodesData.Ids[1] = maxId;
|
|
//
|
|
if (_mesh.Nodes.TryGetValue(minId, out node)) nodesData.Coor[0] = node.Coor;
|
|
else
|
|
nodesData.Coor[0] = new double[3]; // should not happen
|
|
//
|
|
if (_mesh.Nodes.TryGetValue(maxId, out node))nodesData.Coor[1] = node.Coor;
|
|
else nodesData.Coor[1] = new double[3]; // should not happen
|
|
//
|
|
nodesData.Values[0] = 0;
|
|
nodesData.Values[1] = 0;
|
|
//
|
|
zeroIncrement = true;
|
|
}
|
|
}
|
|
//
|
|
if (!zeroIncrement)
|
|
{
|
|
foreach (var fieldEntry in _fields)
|
|
{
|
|
if (fieldEntry.Key.Name == fieldData.Name && fieldEntry.Key.StepId == fieldData.StepId &&
|
|
fieldEntry.Key.StepIncrementId == fieldData.StepIncrementId)
|
|
{
|
|
int id;
|
|
float value;
|
|
BasePart basePart;
|
|
bool firstNaN = true;
|
|
float[] values = fieldEntry.Value.GetComponentValues(fieldData.Component);
|
|
if (values == null) return null; // the field became Valid = false during computation
|
|
//
|
|
basePart = _mesh.Parts[partName];
|
|
// Initialize
|
|
nodesData.Values[0] = float.MaxValue;
|
|
nodesData.Values[1] = -float.MaxValue;
|
|
// Get first value
|
|
if (_nodeIdsLookUp.TryGetValue(basePart.NodeLabels[0], out id) && id < values.Length)
|
|
{
|
|
value = values[id];
|
|
if (!float.IsNaN(value))
|
|
{
|
|
firstNaN = false;
|
|
nodesData.Values[0] = value;
|
|
nodesData.Values[1] = value;
|
|
}
|
|
minId = basePart.NodeLabels[0];
|
|
maxId = basePart.NodeLabels[0];
|
|
}
|
|
//
|
|
foreach (var nodeId in basePart.NodeLabels)
|
|
{
|
|
if (_nodeIdsLookUp.TryGetValue(nodeId, out id) && id < values.Length)
|
|
{
|
|
value = values[id];
|
|
if (!float.IsNaN(value))
|
|
{
|
|
if (value < nodesData.Values[0])
|
|
{
|
|
nodesData.Values[0] = value;
|
|
minId = nodeId;
|
|
}
|
|
else if (value > nodesData.Values[1])
|
|
{
|
|
nodesData.Values[1] = value;
|
|
maxId = nodeId;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (relativeScale < 0) // swap min and max
|
|
{
|
|
int tmp = minId;
|
|
minId = maxId;
|
|
maxId = tmp;
|
|
float tmpD = nodesData.Values[0];
|
|
nodesData.Values[0] = nodesData.Values[1];
|
|
nodesData.Values[1] = tmpD;
|
|
}
|
|
// Ids
|
|
nodesData.Ids[0] = minId;
|
|
nodesData.Ids[1] = maxId;
|
|
// Coordinates
|
|
nodesData.Coor[0] = _mesh.Nodes[minId].Coor;
|
|
nodesData.Coor[1] = _mesh.Nodes[maxId].Coor;
|
|
// Values
|
|
if (firstNaN && minId == maxId) // all values are NaN
|
|
{
|
|
nodesData.Values[0] = 0;
|
|
nodesData.Values[1] = 0;
|
|
}
|
|
else
|
|
{
|
|
nodesData.Values[0] *= relativeScale;
|
|
nodesData.Values[1] *= relativeScale;
|
|
}
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return nodesData;
|
|
}
|
|
// Equations
|
|
public void UpdateResultEquations()
|
|
{
|
|
FieldData sfFieldData;
|
|
Field sfField;
|
|
//
|
|
Dictionary<int, int[]> stepIdIncrementIds = GetAllExistingIncrementIds();
|
|
//
|
|
foreach (var stepEntry in stepIdIncrementIds)
|
|
{
|
|
foreach (var incrementId in stepEntry.Value)
|
|
{
|
|
foreach (var entry in _resultFieldOutputs)
|
|
{
|
|
if (entry.Value is ResultFieldOutputLimit rfol) { }
|
|
else if (entry.Value is ResultFieldOutputEnvelope rfoe) { }
|
|
else if (entry.Value is ResultFieldOutputCoordinateSystemTransform rfocst) { }
|
|
else if (entry.Value is ResultFieldOutputEquation rfoeq)
|
|
{
|
|
// Data
|
|
sfFieldData = GetFieldData(rfoeq.Name, ResultFieldOutputEquation.ComponentName,
|
|
stepEntry.Key, incrementId, true);
|
|
sfField = GetField(sfFieldData, false);
|
|
if (sfField != null) sfField.DataState = DataStateEnum.UpdateResultFieldOutput;
|
|
}
|
|
else if (Debugger.IsAttached)
|
|
throw new NotSupportedException();
|
|
}
|
|
}
|
|
}
|
|
//
|
|
foreach (var entry in _resultHistoryOutputs)
|
|
{
|
|
if (entry.Value is ResultHistoryOutputFromEquation rhofe)
|
|
{
|
|
HistoryResultSet historyResultSet = GetHistorySetFromEquation(rhofe);
|
|
if (historyResultSet != null)
|
|
{
|
|
_history.Sets.Replace(rhofe.HistoryResultSet.Name, historyResultSet.Name, historyResultSet);
|
|
rhofe.HistoryResultSet = historyResultSet;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Result field outputs
|
|
public void AddResultFieldOutput(ResultFieldOutput resultFieldOutput)
|
|
{
|
|
_resultFieldOutputs.Add(resultFieldOutput.Name, resultFieldOutput);
|
|
PrepareFieldsFromResultFieldOutput(resultFieldOutput);
|
|
}
|
|
private void PrepareFieldsFromResultFieldOutput(ResultFieldOutput resultFieldOutput)
|
|
{
|
|
FieldData fieldData;
|
|
FieldData newFieldData = null;
|
|
Field newField;
|
|
//
|
|
string newFieldName;
|
|
string[] newComponentNames;
|
|
string sourceFieldName;
|
|
string sourceComponentName;
|
|
string unit;
|
|
//
|
|
int numNodes = _mesh.Nodes.Count;
|
|
//
|
|
Dictionary<string, string[]> parameterNameFieldNameComponentName;
|
|
Dictionary<int, int[]> stepIdIncrementIds = GetAllExistingIncrementIds();
|
|
//
|
|
foreach (var entry in stepIdIncrementIds)
|
|
{
|
|
foreach (var incrementId in entry.Value)
|
|
{
|
|
if (entry.Key == 1 && incrementId == 0) continue; // Zero increment - Find all occurrences!!!
|
|
//
|
|
if (resultFieldOutput is ResultFieldOutputLimit rfol)
|
|
{
|
|
sourceFieldName = rfol.FieldName;
|
|
sourceComponentName = rfol.ComponentName;
|
|
newFieldName = rfol.Name;
|
|
newComponentNames = rfol.GetComponentNames();
|
|
fieldData = GetFieldData(resultFieldOutput.Name, newComponentNames[0], entry.Key, incrementId, true);
|
|
unit = GetFieldUnitAbbreviation(fieldData);
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputEnvelope rfoen)
|
|
{
|
|
// Get parent field
|
|
sourceFieldName = rfoen.FieldName;
|
|
sourceComponentName = rfoen.ComponentName;
|
|
newFieldName = rfoen.Name;
|
|
newComponentNames = rfoen.GetComponentNames();
|
|
fieldData = GetFieldData(sourceFieldName, sourceComponentName, entry.Key, incrementId, true);
|
|
unit = GetFieldUnitAbbreviation(fieldData);
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputEquation rfoeq)
|
|
{
|
|
// Get parent field
|
|
CheckResultFieldOutputEquation(rfoeq.Equation, out _, out parameterNameFieldNameComponentName);
|
|
sourceFieldName = parameterNameFieldNameComponentName.First().Value[0];
|
|
sourceComponentName = parameterNameFieldNameComponentName.First().Value[1];
|
|
newFieldName = rfoeq.Name;
|
|
newComponentNames = rfoeq.GetComponentNames();
|
|
unit = rfoeq.Unit;
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputCoordinateSystemTransform rfocst)
|
|
{
|
|
rfocst.SetComponentNames(GetFieldComponentNames(rfocst.FieldName));
|
|
//
|
|
sourceFieldName = rfocst.FieldName;
|
|
sourceComponentName = rfocst.GetComponentNames()[0];
|
|
newFieldName = rfocst.Name;
|
|
newComponentNames = rfocst.GetComponentNames();
|
|
fieldData = GetFieldData(sourceFieldName, sourceComponentName, entry.Key, incrementId, true);
|
|
unit = GetFieldUnitAbbreviation(fieldData);
|
|
}
|
|
else throw new NotSupportedException();
|
|
// Get parent field
|
|
fieldData = GetFieldData(sourceFieldName, sourceComponentName, entry.Key, incrementId, true);
|
|
// Prepare field
|
|
newField = new Field(newFieldName);
|
|
newField.DataState = DataStateEnum.UpdateResultFieldOutput;
|
|
//
|
|
foreach (var componentName in newComponentNames)
|
|
{
|
|
newFieldData = new FieldData(fieldData); // copy
|
|
newFieldData.Name = newFieldName;
|
|
newFieldData.Component = componentName;
|
|
newFieldData.Unit = unit;
|
|
newField.AddComponent(newFieldData.Component, new float[numNodes]);
|
|
}
|
|
AddField(newFieldData, newField);
|
|
}
|
|
}
|
|
}
|
|
public ResultFieldOutput GetResultFieldOutput(string resultFieldOutputName)
|
|
{
|
|
return _resultFieldOutputs[resultFieldOutputName];
|
|
}
|
|
public ResultFieldOutput[] GetResultFieldOutputs()
|
|
{
|
|
return _resultFieldOutputs.Values.ToArray();
|
|
}
|
|
public bool ContainsResultFieldOutput(string resultFieldOutputName)
|
|
{
|
|
return _resultFieldOutputs.ContainsKey(resultFieldOutputName);
|
|
}
|
|
public void ReplaceAllResultFieldOutputs()
|
|
{
|
|
foreach (var entry in _resultFieldOutputs.ToArray()) ReplaceResultFieldOutput(entry.Key, entry.Value);
|
|
}
|
|
public void ReplaceResultFieldOutput(string oldResultFieldOutputName, ResultFieldOutput resultFieldOutput)
|
|
{
|
|
RemoveFields(new string[] { oldResultFieldOutputName });
|
|
_resultFieldOutputs.Replace(oldResultFieldOutputName, resultFieldOutput.Name, resultFieldOutput);
|
|
PrepareFieldsFromResultFieldOutput(resultFieldOutput);
|
|
}
|
|
public void RemoveResultFieldOutputs(string[] fieldOutputNames)
|
|
{
|
|
RemoveFields(fieldOutputNames);
|
|
foreach (var fieldOutputName in fieldOutputNames) _resultFieldOutputs.Remove(fieldOutputName);
|
|
}
|
|
public void RemoveResultFieldOutputComponents(string fieldOutputName, string[] componentNames)
|
|
{
|
|
if (_fields != null)
|
|
{
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.Name == fieldOutputName)
|
|
{
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
entry.Value.RemoveComponent(componentName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
private void SetResultFieldOutputLimitsToRecompute()
|
|
{
|
|
FieldData sfFieldData;
|
|
Field sfField;
|
|
ResultFieldOutput resultFieldOutput;
|
|
//
|
|
Dictionary<int, int[]> stepIdIncrementIds = GetAllExistingIncrementIds();
|
|
//
|
|
foreach (var stepEntry in stepIdIncrementIds)
|
|
{
|
|
foreach (var incrementId in stepEntry.Value)
|
|
{
|
|
foreach (var entry in _resultFieldOutputs)
|
|
{
|
|
resultFieldOutput = entry.Value;
|
|
//
|
|
if (resultFieldOutput is ResultFieldOutputLimit rfol)
|
|
{
|
|
// Ratio
|
|
sfFieldData = GetFieldData(rfol.Name, FOComponentNames.Ratio, stepEntry.Key, incrementId, true);
|
|
sfField = GetField(sfFieldData, false);
|
|
if (sfField != null) sfField.DataState = DataStateEnum.UpdateResultFieldOutput;
|
|
// Safety factor
|
|
sfFieldData = GetFieldData(rfol.Name, FOComponentNames.SafetyFactor, stepEntry.Key,
|
|
incrementId, true);
|
|
sfField = GetField(sfFieldData, false);
|
|
if (sfField != null) sfField.DataState = DataStateEnum.UpdateResultFieldOutput;
|
|
}
|
|
else throw new NotSupportedException();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private void ComputeResultFieldOutput(FieldData fieldData)
|
|
{
|
|
List<ResultFieldOutput> independencyList = GetResultFieldOutputIndependencySequence();
|
|
//
|
|
foreach (var entry in _resultFieldOutputs)
|
|
{
|
|
if (fieldData.Name == entry.Value.Name && entry.Value.GetComponentNames().Contains(fieldData.Component))
|
|
{
|
|
foreach (var indResultFieldOutput in independencyList)
|
|
{
|
|
ComputeFieldFromResultFieldOutput(indResultFieldOutput, fieldData.StepId, fieldData.StepIncrementId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private void ComputeFieldFromResultFieldOutput(ResultFieldOutput resultFieldOutput, int stepId, int stepIncrementId)
|
|
{
|
|
FieldData sourceFieldData;
|
|
Field sourceField = null;
|
|
//
|
|
int numOfNodes = _undeformedNodes.Count;
|
|
string[] componentNames;
|
|
float[][] values;
|
|
//
|
|
if (resultFieldOutput is ResultFieldOutputLimit rfol)
|
|
{
|
|
sourceFieldData = GetFieldData(rfol.FieldName, rfol.ComponentName, stepId, stepIncrementId, true);
|
|
sourceField = GetField(sourceFieldData);
|
|
componentNames = rfol.GetComponentNames();
|
|
values = ComputeFieldFromResultFieldOutputLimit(rfol, sourceField);
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputEnvelope rfoen)
|
|
{
|
|
componentNames = rfoen.GetComponentNames();
|
|
values = ComputeFieldFromResultFieldOutputEnvelope(rfoen);
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputEquation rfoeq)
|
|
{
|
|
componentNames = rfoeq.GetComponentNames();
|
|
values = ComputeFieldFromResultFieldOutputEquation(rfoeq, stepId, stepIncrementId);
|
|
}
|
|
else if (resultFieldOutput is ResultFieldOutputCoordinateSystemTransform rfocst)
|
|
{
|
|
sourceFieldData = GetFieldData(rfocst.FieldName, rfocst.GetComponentNames()[0], stepId, stepIncrementId, true);
|
|
sourceField = GetField(sourceFieldData);
|
|
componentNames = rfocst.GetComponentNames();
|
|
values = ComputeFieldFromResultFieldOutputCoordinateSystemTransform(rfocst, sourceField);
|
|
}
|
|
else throw new NotSupportedException();
|
|
//
|
|
int count = 0;
|
|
FieldData newFieldData;
|
|
Field newField;
|
|
FieldComponent newComponent;
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
newFieldData = GetFieldData(resultFieldOutput.Name, componentName, stepId, stepIncrementId);
|
|
newField = GetField(newFieldData, false);
|
|
newComponent = new FieldComponent(newFieldData.Component, values[count++]);
|
|
newField.ReplaceComponent(newComponent.Name, newComponent);
|
|
newField.DataType = sourceField != null ? sourceField.DataType : DataTypeEnum.None;
|
|
newField.DataState = DataStateEnum.OK;
|
|
ReplaceOrAddField(newFieldData, newField);
|
|
}
|
|
}
|
|
private float[][] ComputeFieldFromResultFieldOutputLimit(ResultFieldOutputLimit resultFieldOutput, Field sourceField)
|
|
{
|
|
int resultsNodeId;
|
|
float itemLimit;
|
|
float[] valuesSafety = null;
|
|
float[] valuesRatio = null;
|
|
float[] limits = null;
|
|
//
|
|
if (sourceField != null)
|
|
{
|
|
valuesRatio = sourceField.GetComponentValues(resultFieldOutput.ComponentName);
|
|
if (valuesRatio != null)
|
|
{
|
|
limits = new float[valuesRatio.Length];
|
|
//
|
|
if (resultFieldOutput.LimitPlotBasedOn == LimitPlotBasedOnEnum.Parts)
|
|
{
|
|
// Collect limits for parts
|
|
BasePart part;
|
|
foreach (var itemEntry in resultFieldOutput.ItemNameLimit)
|
|
{
|
|
if (_mesh.Parts.TryGetValue(itemEntry.Key, out part))
|
|
{
|
|
itemLimit = (float)itemEntry.Value;
|
|
if (itemLimit == 0) throw new NotSupportedException();
|
|
//
|
|
foreach (var nodeId in part.NodeLabels)
|
|
{
|
|
resultsNodeId = _nodeIdsLookUp[nodeId];
|
|
if (limits[resultsNodeId] != 0)
|
|
limits[resultsNodeId] = Math.Min(limits[resultsNodeId], itemLimit);
|
|
else limits[resultsNodeId] = itemLimit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (resultFieldOutput.LimitPlotBasedOn == LimitPlotBasedOnEnum.ElementSets)
|
|
{
|
|
// Collect limits for element sets
|
|
FeElementSet elementSet;
|
|
foreach (var itemEntry in resultFieldOutput.ItemNameLimit)
|
|
{
|
|
if (_mesh.ElementSets.TryGetValue(itemEntry.Key, out elementSet) ||
|
|
itemEntry.Key == ResultFieldOutputLimit.AllElementsName)
|
|
{
|
|
if (itemEntry.Key == ResultFieldOutputLimit.AllElementsName)
|
|
elementSet = new FeElementSet("tmp", _mesh.Elements.Keys.ToArray());
|
|
//
|
|
itemLimit = (float)itemEntry.Value;
|
|
if (itemLimit == 0) throw new NotSupportedException();
|
|
//
|
|
foreach (var nodeId in _mesh.GetNodeIdsFromElementSet(elementSet))
|
|
{
|
|
resultsNodeId = _nodeIdsLookUp[nodeId];
|
|
if (limits[resultsNodeId] != 0)
|
|
limits[resultsNodeId] = Math.Min(limits[resultsNodeId], itemLimit);
|
|
else limits[resultsNodeId] = itemLimit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else throw new NotSupportedException();
|
|
}
|
|
}
|
|
//
|
|
if (valuesRatio != null)
|
|
{
|
|
valuesRatio = valuesRatio.ToArray(); // copy
|
|
valuesSafety = valuesRatio.ToArray();
|
|
// Compute values
|
|
for (int i = 0; i < limits.Length; i++)
|
|
{
|
|
// Ratio
|
|
valuesRatio[i] = valuesRatio[i] / limits[i];
|
|
// Safety factor
|
|
if (valuesSafety[i] == 0) valuesSafety[i] = float.NaN; // this can happen after some parts are renamed
|
|
else valuesSafety[i] = limits[i] / valuesSafety[i];
|
|
}
|
|
}
|
|
//
|
|
return new float[][] { valuesRatio, valuesSafety };
|
|
}
|
|
private float[][] ComputeFieldFromResultFieldOutputEnvelope(ResultFieldOutputEnvelope resultFieldOutput)
|
|
{
|
|
FieldData sourceFieldData;
|
|
Field sourceField;
|
|
//
|
|
int stepId;
|
|
int stepIncrementId;
|
|
float[] values = null;
|
|
float[] max = null;
|
|
float[] min = null;
|
|
float[] average = null;
|
|
List<float[]> allValues = new List<float[]>();
|
|
//
|
|
Dictionary<int, int[]> stepIdIncrementId = GetAllExistingIncrementIds();
|
|
foreach (var entry in stepIdIncrementId)
|
|
{
|
|
stepId = entry.Key;
|
|
for (int i = 0; i < entry.Value.Length; i++)
|
|
{
|
|
stepIncrementId = entry.Value[i];
|
|
sourceFieldData = GetFieldData(resultFieldOutput.FieldName, resultFieldOutput.ComponentName,
|
|
stepId, stepIncrementId, true);
|
|
sourceField = GetField(sourceFieldData);
|
|
//
|
|
if (sourceField != null)
|
|
{
|
|
values = sourceField.GetComponentValues(resultFieldOutput.ComponentName);
|
|
if (values != null) allValues.Add(values);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (values.Count() > 0)
|
|
{
|
|
max = new float[values.Length];
|
|
min = new float[values.Length];
|
|
average = new float[values.Length];
|
|
//
|
|
for (int i = 0; i < values.Length; i++)
|
|
{
|
|
max[i] = -float.MaxValue;
|
|
min[i] = float.MaxValue;
|
|
}
|
|
//
|
|
foreach (var resultValues in allValues)
|
|
{
|
|
for (int i = 0; i < resultValues.Length; i++)
|
|
{
|
|
if (resultValues[i] > max[i]) max[i] = resultValues[i];
|
|
if (resultValues[i] < min[i]) min[i] = resultValues[i];
|
|
average[i] += resultValues[i];
|
|
}
|
|
}
|
|
//
|
|
for (int i = 0; i < average.Length; i++) average[i] /= allValues.Count();
|
|
}
|
|
//
|
|
return new float[][] { max, min, average };
|
|
}
|
|
private float[][] ComputeFieldFromResultFieldOutputEquation(ResultFieldOutputEquation resultFieldOutput,
|
|
int stepId, int stepIncrementId)
|
|
{
|
|
OrderedDictionary<string, object> existingParameters = MyNCalc.ExistingParameters.DeepCopy();
|
|
try
|
|
{
|
|
FieldData sourceFieldData;
|
|
Field sourceField;
|
|
//
|
|
int numValues = -1;
|
|
float[] values = null;
|
|
List<float[]> allValues = new List<float[]>();
|
|
//
|
|
Dictionary<string, string[]> parameterNameFieldNameComponentName;
|
|
Dictionary<string, float[]> parameterNameValues = new Dictionary<string, float[]>();
|
|
//
|
|
CheckResultFieldOutputEquation(resultFieldOutput.Equation, out _, out parameterNameFieldNameComponentName);
|
|
//
|
|
string fieldName;
|
|
string componentName;
|
|
foreach (var parametreEntry in parameterNameFieldNameComponentName)
|
|
{
|
|
fieldName = parametreEntry.Value[0];
|
|
componentName = parametreEntry.Value[1];
|
|
//
|
|
sourceFieldData = GetFieldData(fieldName, componentName, stepId, stepIncrementId, true);
|
|
sourceField = GetField(sourceFieldData);
|
|
//
|
|
if (sourceField != null)
|
|
{
|
|
values = sourceField.GetComponentValues(parametreEntry.Value[1]);
|
|
if (values != null)
|
|
{
|
|
numValues = values.Length;
|
|
parameterNameValues.Add(parametreEntry.Key, values);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
if (numValues < 0) return null;
|
|
// Evaluate the equation
|
|
foreach (var entry in parameterNameValues) MyNCalc.ExistingParameters[entry.Key] = entry.Value;
|
|
values = MyNCalc.SolveArrayEquation(resultFieldOutput.Equation).ToFloat();
|
|
//
|
|
return new float[][] { values };
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
finally
|
|
{
|
|
MyNCalc.ExistingParameters = existingParameters;
|
|
}
|
|
|
|
}
|
|
private float[][] ComputeFieldFromResultFieldOutputCoordinateSystemTransform(
|
|
ResultFieldOutputCoordinateSystemTransform resultFieldOutput, Field sourceField)
|
|
{
|
|
float[][] values = null;
|
|
CoordinateSystem coordinateSystem;
|
|
_mesh.CoordinateSystems.TryGetValue(resultFieldOutput.CoordinateSystemName, out coordinateSystem);
|
|
//
|
|
if (sourceField != null && coordinateSystem != null)
|
|
{
|
|
int resultNodeId;
|
|
int numOfComponents;
|
|
string[] componentNames;
|
|
float[][] sourceValues;
|
|
double[] coor;
|
|
Vec3D dx;
|
|
Vec3D dy;
|
|
Vec3D dz;
|
|
Vec3D vector = new Vec3D();
|
|
double[][] tensor;
|
|
double[][] rotation;
|
|
//
|
|
FeNode node;
|
|
Field resultField = new Field(sourceField);
|
|
DataTypeEnum dataType = sourceField.DataType;
|
|
// Remove invariants
|
|
resultField.RemoveInvariants();
|
|
// Prepare arrays
|
|
componentNames = resultField.GetComponentNames();
|
|
numOfComponents = componentNames.Length;
|
|
values = new float[numOfComponents][];
|
|
sourceValues = new float[numOfComponents][];
|
|
// Get source values
|
|
for (int i = 0; i < numOfComponents; i++)
|
|
{
|
|
sourceValues[i] = resultField.GetComponentValues(componentNames[i]);
|
|
values[i] = new float[sourceValues[i].Length];
|
|
}
|
|
// Remove components
|
|
for (int i = 0; i < numOfComponents; i++) resultField.RemoveComponent(componentNames[i]);
|
|
// Scalar
|
|
if (dataType == DataTypeEnum.Scalar)
|
|
{
|
|
}
|
|
// Vector
|
|
else if (dataType == DataTypeEnum.Vector)
|
|
{
|
|
foreach (var entry in _undeformedNodes)
|
|
{
|
|
node = entry.Value;
|
|
resultNodeId = _nodeIdsLookUp[node.Id];
|
|
// Node coordinates
|
|
coor = node.Coor;
|
|
// Coordinate system directions at node
|
|
dx = coordinateSystem.DirectionX(coor);
|
|
dy = coordinateSystem.DirectionY(coor, dx); // using dx for speed
|
|
dz = coordinateSystem.DirectionZ(coor);
|
|
// Vector
|
|
vector.X = sourceValues[0][resultNodeId];
|
|
vector.Y = sourceValues[1][resultNodeId];
|
|
vector.Z = sourceValues[2][resultNodeId];
|
|
// Project vector on coordinate directions
|
|
values[0][resultNodeId] = (float)Vec3D.DotProduct(vector, dx);
|
|
values[1][resultNodeId] = (float)Vec3D.DotProduct(vector, dy);
|
|
values[2][resultNodeId] = (float)Vec3D.DotProduct(vector, dz);
|
|
}
|
|
// Add components
|
|
for (int i = 0; i < numOfComponents; i++) resultField.AddComponent(componentNames[i], values[i]);
|
|
}
|
|
// Tensor
|
|
else if (dataType == DataTypeEnum.Tensor)
|
|
{
|
|
tensor = Matrix.MatrixCreate(3, 3);
|
|
rotation = Matrix.MatrixCreate(3, 3);
|
|
foreach (var entry in _undeformedNodes)
|
|
{
|
|
node = entry.Value;
|
|
resultNodeId = _nodeIdsLookUp[node.Id];
|
|
// Node coordinates
|
|
coor = node.Coor;
|
|
// Coordinate system directions at node
|
|
dx = coordinateSystem.DirectionX(coor);
|
|
dy = coordinateSystem.DirectionY(coor, dx); // using dx for speed
|
|
dz = coordinateSystem.DirectionZ(coor);
|
|
// Tensor
|
|
tensor[0][0] = sourceValues[0][resultNodeId];
|
|
tensor[1][1] = sourceValues[1][resultNodeId];
|
|
tensor[2][2] = sourceValues[2][resultNodeId];
|
|
tensor[0][1] = sourceValues[3][resultNodeId];
|
|
tensor[1][0] = sourceValues[3][resultNodeId];
|
|
tensor[1][2] = sourceValues[4][resultNodeId];
|
|
tensor[2][1] = sourceValues[4][resultNodeId];
|
|
tensor[0][2] = sourceValues[5][resultNodeId];
|
|
tensor[2][0] = sourceValues[5][resultNodeId];
|
|
// Rotation matrix
|
|
rotation[0][0] = (float)dx.X;
|
|
rotation[0][1] = (float)dx.Y;
|
|
rotation[0][2] = (float)dx.Z;
|
|
rotation[1][0] = (float)dy.X;
|
|
rotation[1][1] = (float)dy.Y;
|
|
rotation[1][2] = (float)dy.Z;
|
|
rotation[2][0] = (float)dz.X;
|
|
rotation[2][1] = (float)dz.Y;
|
|
rotation[2][2] = (float)dz.Z;
|
|
// T' = R*T*RT - rotate tensor
|
|
tensor = Matrix.MatrixProduct(rotation, tensor);
|
|
rotation = Matrix.MatrixTranspose(rotation);
|
|
tensor = Matrix.MatrixProduct(tensor, rotation);
|
|
//
|
|
values[0][resultNodeId] = (float)tensor[0][0];
|
|
values[1][resultNodeId] = (float)tensor[1][1];
|
|
values[2][resultNodeId] = (float)tensor[2][2];
|
|
values[3][resultNodeId] = (float)tensor[0][1];
|
|
values[4][resultNodeId] = (float)tensor[1][2];
|
|
values[5][resultNodeId] = (float)tensor[2][0];
|
|
}
|
|
|
|
//Tensor - faster
|
|
//tensor = Matrix4x4.Identity;
|
|
//rotation = Matrix4x4.Identity;
|
|
//foreach (var entry in _undeformedNodes)
|
|
//{
|
|
// node = entry.Value;
|
|
// resultNodeId = _nodeIdsLookUp[node.Id];
|
|
// // Node coordinates
|
|
// coor = node.Coor;
|
|
// // Coordinate system directions at node
|
|
// dx = coordinateSystem.DirectionX(coor);
|
|
// dy = coordinateSystem.DirectionY(coor, dx); // using dx for speed
|
|
// dz = coordinateSystem.DirectionZ(coor);
|
|
// // Tensor
|
|
// tensor.M11 = sourceValues[0][resultNodeId];
|
|
// tensor.M22 = sourceValues[1][resultNodeId];
|
|
// tensor.M33 = sourceValues[2][resultNodeId];
|
|
// tensor.M12 = sourceValues[3][resultNodeId];
|
|
// tensor.M21 = sourceValues[3][resultNodeId];
|
|
// tensor.M23 = sourceValues[4][resultNodeId];
|
|
// tensor.M32 = sourceValues[4][resultNodeId];
|
|
// tensor.M13 = sourceValues[5][resultNodeId];
|
|
// tensor.M31 = sourceValues[5][resultNodeId];
|
|
// // Rotation matrix
|
|
// rotation.M11 = (float)dx.X;
|
|
// rotation.M12 = (float)dx.Y;
|
|
// rotation.M13 = (float)dx.Z;
|
|
// rotation.M21 = (float)dy.X;
|
|
// rotation.M22 = (float)dy.Y;
|
|
// rotation.M23 = (float)dy.Z;
|
|
// rotation.M31 = (float)dz.X;
|
|
// rotation.M32 = (float)dz.Y;
|
|
// rotation.M33 = (float)dz.Z;
|
|
// //
|
|
// //Matrix4x4.Invert(rotation, out rotationT);
|
|
// rotationT = Matrix4x4.Transpose(rotation);
|
|
// //
|
|
// //tensor = Matrix4x4.Multiply(rotation, rotationT);
|
|
// // T' = R*T*RT
|
|
// tensor = Matrix4x4.Multiply(rotation, tensor);
|
|
// tensor = Matrix4x4.Multiply(tensor, rotationT);
|
|
// // Project vector on coordinate directions
|
|
// values[0][resultNodeId] = tensor.M11;
|
|
// values[1][resultNodeId] = tensor.M22;
|
|
// values[2][resultNodeId] = tensor.M33;
|
|
// values[3][resultNodeId] = tensor.M12;
|
|
// values[4][resultNodeId] = tensor.M23;
|
|
// values[5][resultNodeId] = tensor.M31;
|
|
//}
|
|
|
|
|
|
// Add components
|
|
for (int i = 0; i < numOfComponents; i++) resultField.AddComponent(componentNames[i], values[i]);
|
|
}
|
|
else throw new NotSupportedException();
|
|
// Compute invariants
|
|
resultField.ComputeInvariants();
|
|
// Get all component values
|
|
componentNames = resultField.GetComponentNames();
|
|
numOfComponents = componentNames.Length;
|
|
values = new float[numOfComponents][];
|
|
for (int i = 0; i < numOfComponents; i++) values[i] = resultField.GetComponentValues(componentNames[i]);
|
|
}
|
|
//
|
|
return values;
|
|
}
|
|
private List<ResultFieldOutput> GetResultFieldOutputIndependencySequence()
|
|
{
|
|
string[] parentFieldNames;
|
|
HashSet<string> allNames = new HashSet<string>();
|
|
ResultFieldOutput rfo;
|
|
Node<string> node;
|
|
Graph<string> dependencyGraph = new Graph<string>();
|
|
Dictionary<string, Node<string>> nodes = new Dictionary<string, Node<string>>();
|
|
//
|
|
foreach (var entry in _resultFieldOutputs)
|
|
{
|
|
rfo = entry.Value;
|
|
//
|
|
allNames.Clear();
|
|
allNames.Add(rfo.Name);
|
|
parentFieldNames = rfo.GetParentNames();
|
|
allNames.UnionWith(parentFieldNames);
|
|
// Add nodes
|
|
foreach (var name in allNames)
|
|
{
|
|
if (!nodes.ContainsKey(name))
|
|
{
|
|
node = new Node<string>(name);
|
|
nodes.Add(name, node);
|
|
dependencyGraph.AddNode(node);
|
|
}
|
|
}
|
|
// Add connections
|
|
foreach (var parentFieldName in parentFieldNames)
|
|
{
|
|
dependencyGraph.AddDirectedEdge(nodes[rfo.Name], nodes[parentFieldName]);
|
|
}
|
|
}
|
|
// Use only one sub-graph - NOT WORKING FOR DIRECTED GRAPHS
|
|
//if (resultFieldOutput != null)
|
|
//{
|
|
// List<Graph<string>> subGraphs = dependencyGraph.GetConnectedSubgraphs();
|
|
// foreach (var subGraph in subGraphs)
|
|
// {
|
|
// if (subGraph.Contains(resultFieldOutput.Name))
|
|
// {
|
|
// dependencyGraph = subGraph;
|
|
// break;
|
|
// }
|
|
// }
|
|
//}
|
|
//
|
|
List<string> independencySequence = dependencyGraph.GetIndependencyList();
|
|
//
|
|
List<ResultFieldOutput> resultList = new List<ResultFieldOutput>();
|
|
foreach (var name in independencySequence)
|
|
{
|
|
if (_resultFieldOutputs.TryGetValue(name, out rfo)) resultList.Add(rfo);
|
|
}
|
|
//
|
|
return resultList;
|
|
}
|
|
// Equation
|
|
public string[] GetPossibleFieldEquationParameters()
|
|
{
|
|
string variable;
|
|
string separator = ResultFieldOutputEquation.EquationSeparator;
|
|
List<string> possibleEquationParameters = new List<string>();
|
|
//
|
|
foreach (var entry in GetAllFiledNameComponentNames())
|
|
{
|
|
foreach (var componentName in entry.Value)
|
|
{
|
|
variable = entry.Key + separator + componentName;
|
|
possibleEquationParameters.Add(variable);
|
|
}
|
|
}
|
|
//
|
|
return possibleEquationParameters.ToArray();
|
|
}
|
|
public string CheckResultFieldOutputEquation(string equation, out HashSet<string> parentNames,
|
|
out Dictionary<string, string[]> parameterNameFieldNameComponentName)
|
|
{
|
|
parentNames = new HashSet<string>();
|
|
parameterNameFieldNameComponentName = new Dictionary<string, string[]>();
|
|
OrderedDictionary<string, object> existingParameters = MyNCalc.ExistingParameters.DeepCopy();
|
|
//
|
|
try
|
|
{
|
|
int count = 1;
|
|
string[] possibleEquationParameters = GetPossibleFieldEquationParameters();
|
|
foreach (var possibleParameter in possibleEquationParameters)
|
|
{
|
|
MyNCalc.ExistingParameters[possibleParameter] = count++ * 0.111;
|
|
}
|
|
//
|
|
HashSet<string> parameterNames;
|
|
bool hasErrors = MyNCalc.HasErrors(equation, out parameterNames);
|
|
//
|
|
if (parameterNames == null || parameterNames.Count == 0 ||
|
|
parameterNames.Intersect(possibleEquationParameters).Count() == 0)
|
|
throw new CaeException("At least one filed output component must be used in the equation.");
|
|
//
|
|
string[] tmp;
|
|
string[] splitter = new string[] { ResultFieldOutputEquation.EquationSeparator };
|
|
//
|
|
foreach (var parameterName in parameterNames)
|
|
{
|
|
tmp = parameterName.Split(splitter, StringSplitOptions.None);
|
|
if (tmp.Length != 2) continue;
|
|
//
|
|
parentNames.Add(tmp[0]);
|
|
parameterNameFieldNameComponentName.Add(parameterName, new string[] { tmp[0], tmp[1] });
|
|
}
|
|
//
|
|
if (parentNames.Count == 0)
|
|
throw new CaeException("The equation must contain at least one field output reference.");
|
|
//
|
|
return null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
MyNCalc.ExistingParameters = existingParameters;
|
|
}
|
|
}
|
|
//
|
|
public bool AreResultFieldOutputsInCyclicDependance(string oldResultFieldOutputName, ResultFieldOutput resultFieldOutput)
|
|
{
|
|
Dictionary<string, ResultFieldOutput> resultFieldOutputs = new Dictionary<string, ResultFieldOutput>();
|
|
foreach (var entry in _resultFieldOutputs)
|
|
{
|
|
if (entry.Key != oldResultFieldOutputName)
|
|
resultFieldOutputs.Add(entry.Key, entry.Value);
|
|
}
|
|
resultFieldOutputs.Add(resultFieldOutput.Name, resultFieldOutput);
|
|
//
|
|
return AreResultFieldOutputsInCyclicDependance(resultFieldOutputs);
|
|
}
|
|
private bool AreResultFieldOutputsInCyclicDependance(Dictionary<string, ResultFieldOutput> resultFieldOutputs)
|
|
{
|
|
int count = 0;
|
|
bool result;
|
|
foreach (var entry in resultFieldOutputs)
|
|
{
|
|
result = RecursiveCheck(ref count, entry.Value.Name, entry.Value.Name, resultFieldOutputs);
|
|
if (result) return true;
|
|
}
|
|
return false;
|
|
}
|
|
private bool RecursiveCheck(ref int count, string firstName, string name,
|
|
Dictionary<string, ResultFieldOutput> resultFieldOutputs)
|
|
{
|
|
if (count > 1000) return true;
|
|
//
|
|
ResultFieldOutput resultFieldOutput;
|
|
if (resultFieldOutputs.TryGetValue(name, out resultFieldOutput))
|
|
{
|
|
string[] parents = resultFieldOutput.GetParentNames();
|
|
if (parents == null) return false;
|
|
//
|
|
bool result;
|
|
foreach (string parent in parents)
|
|
{
|
|
if (parent == firstName) return true;
|
|
//
|
|
count++;
|
|
result = RecursiveCheck(ref count, firstName, parent, resultFieldOutputs);
|
|
if (result) return true;
|
|
count--;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
// History
|
|
public HistoryResults GetHistory()
|
|
{
|
|
return _history;
|
|
}
|
|
public void SetHistory(HistoryResults historyResults)
|
|
{
|
|
_history = historyResults;
|
|
}
|
|
|
|
//
|
|
public void AddResultHistoryOutput(ResultHistoryOutput resultHistoryOutput)
|
|
{
|
|
// First try to create the historyResultSet to catch potential errors
|
|
HistoryResultSet historyResultSet = GetHistorySetFromResultHistoryOutput(resultHistoryOutput);
|
|
//
|
|
if (historyResultSet != null)
|
|
{
|
|
// Add result output
|
|
_resultHistoryOutputs.Add(resultHistoryOutput.Name, resultHistoryOutput);
|
|
// Add set
|
|
_history.Sets.Add(historyResultSet.Name, historyResultSet);
|
|
}
|
|
}
|
|
public HistoryResultSet GetHistorySetFromResultHistoryOutput(ResultHistoryOutput resultHistoryOutput)
|
|
{
|
|
// Compatibility for version v1.2.1
|
|
if (_history == null) _history = new HistoryResults("Tmp");
|
|
//
|
|
HistoryResultSet historyResultSet = null;
|
|
//
|
|
if (resultHistoryOutput is ResultHistoryOutputFromField rhoff)
|
|
{
|
|
historyResultSet = GetHistorySetFromField(rhoff);
|
|
}
|
|
else if (resultHistoryOutput is ResultHistoryOutputFromEquation rhofe)
|
|
{
|
|
historyResultSet = GetHistorySetFromEquation(rhofe);
|
|
}
|
|
//
|
|
resultHistoryOutput.HistoryResultSet = historyResultSet;
|
|
//
|
|
return historyResultSet;
|
|
}
|
|
private HistoryResultSet GetHistorySetFromField(ResultHistoryOutputFromField resultHistoryOutput)
|
|
{
|
|
// Collect node ids
|
|
int[] nodeIds = null;
|
|
HistoryResultSet historyResultSet = null;
|
|
//
|
|
if (resultHistoryOutput.RegionType == RegionTypeEnum.NodeSetName)
|
|
{
|
|
nodeIds = _mesh.NodeSets[resultHistoryOutput.RegionName].Labels;
|
|
}
|
|
else if (resultHistoryOutput.RegionType == RegionTypeEnum.SurfaceName)
|
|
{
|
|
string nodeSetName = _mesh.Surfaces[resultHistoryOutput.RegionName].NodeSetName;
|
|
nodeIds = _mesh.NodeSets[nodeSetName].Labels;
|
|
}
|
|
else if (resultHistoryOutput.RegionType == RegionTypeEnum.Selection)
|
|
{
|
|
nodeIds = resultHistoryOutput.CreationIds;
|
|
}
|
|
//
|
|
if (nodeIds != null)
|
|
{
|
|
HistoryResultField historyResultField = new HistoryResultField(resultHistoryOutput.FieldName);
|
|
// Create history result components
|
|
List<HistoryResultComponent> components = new List<HistoryResultComponent>();
|
|
foreach (var componentName in resultHistoryOutput.ComponentNames)
|
|
components.Add(new HistoryResultComponent(componentName));
|
|
// Prepare component entries
|
|
string name;
|
|
foreach (var newComponent in components)
|
|
{
|
|
newComponent.Entries.Clear();
|
|
for (int i = 0; i < nodeIds.Length; i++)
|
|
{
|
|
name = nodeIds[i].ToString();
|
|
newComponent.Entries.Add(name, new HistoryResultEntries(name, false));
|
|
}
|
|
}
|
|
// Get all existing increments
|
|
Dictionary<int, int[]> existingStepIncrementIds = GetExistingIncrementIds(resultHistoryOutput.FieldName,
|
|
components[0].Name, resultHistoryOutput.StepId, resultHistoryOutput.StepIncrementId);
|
|
//
|
|
string unit;
|
|
float[] values;
|
|
int resultNodeId;
|
|
Field field;
|
|
FieldData fieldData;
|
|
foreach (var component in components)
|
|
{
|
|
if (resultHistoryOutput.Harmonic) GetHarmonicFromHistoryOutput(nodeIds, resultHistoryOutput, component);
|
|
else
|
|
{
|
|
// Set complex
|
|
ComplexResultTypeEnum prevComplexResultType = _complexResultType;
|
|
float prevComplexAngleDeg = _complexAngleDeg;
|
|
SetComplexResultTypeAndAngle(resultHistoryOutput.ComplexResultType, (float)resultHistoryOutput.ComplexAngleDeg);
|
|
//
|
|
foreach (var existingStepEntry in existingStepIncrementIds)
|
|
{
|
|
foreach (var incrementId in existingStepEntry.Value)
|
|
{
|
|
fieldData = GetFieldData(resultHistoryOutput.FieldName, component.Name,
|
|
existingStepEntry.Key, incrementId);
|
|
field = GetField(fieldData);
|
|
// Filter complex components only to complex field outputs
|
|
if (resultHistoryOutput.ComplexResultType != ComplexResultTypeEnum.Real && !field.Complex) continue;
|
|
//
|
|
if (field != null)
|
|
{
|
|
values = field.GetComponentValues(component.Name);
|
|
if (values != null)
|
|
{
|
|
for (int i = 0; i < nodeIds.Length; i++)
|
|
{
|
|
name = nodeIds[i].ToString();
|
|
resultNodeId = _nodeIdsLookUp[nodeIds[i]];
|
|
component.Entries[name].Add(fieldData.Time, values[resultNodeId]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Reset complex
|
|
SetComplexResultTypeAndAngle(prevComplexResultType, prevComplexAngleDeg);
|
|
// Set phase unit
|
|
if (resultHistoryOutput.ComplexResultType == ComplexResultTypeEnum.Phase ||
|
|
resultHistoryOutput.ComplexResultType == ComplexResultTypeEnum.AngleAtMax ||
|
|
resultHistoryOutput.ComplexResultType == ComplexResultTypeEnum.AngleAtMin)
|
|
{
|
|
unit = StringAngleDegConverter.GetUnitAbbreviation();
|
|
}
|
|
else
|
|
{
|
|
GetHistoryUnitConverterAndAbbreviation(resultHistoryOutput.FieldName, component.Name, 0, 0,
|
|
out _, out unit);
|
|
}
|
|
component.Unit = unit;
|
|
}
|
|
// Filter
|
|
if (resultHistoryOutput.Filter1 != null) component.ApplyFilter(resultHistoryOutput.Filter1);
|
|
if (resultHistoryOutput.Filter2 != null) component.ApplyFilter(resultHistoryOutput.Filter2);
|
|
// Add component to field
|
|
historyResultField.Components.Add(component.Name, component);
|
|
}
|
|
//
|
|
historyResultSet = new HistoryResultSet(resultHistoryOutput.Name);
|
|
historyResultSet.Harmonic = resultHistoryOutput.Harmonic;
|
|
historyResultSet.Fields.Add(historyResultField.Name, historyResultField);
|
|
//
|
|
if (resultHistoryOutput.OutputNodeCoordinates != OutputNodeCoordinatesEnum.Off)
|
|
{
|
|
HistoryResultField coordinatesField = GetNodeCoordinatesHistoryResultField(nodeIds,
|
|
resultHistoryOutput.OutputNodeCoordinates, existingStepIncrementIds);
|
|
historyResultSet.Fields.Add(coordinatesField.Name, coordinatesField);
|
|
}
|
|
}
|
|
//
|
|
return historyResultSet;
|
|
}
|
|
private HistoryResultSet GetHistorySetFromEquation(ResultHistoryOutputFromEquation resultHistoryOutput)
|
|
{
|
|
OrderedDictionary<string, object> existingParameters = MyNCalc.ExistingParameters.DeepCopy();
|
|
//
|
|
try
|
|
{
|
|
HashSet<string> parentNames;
|
|
Dictionary<string, HistoryResultComponent> parameterNameHistoryComponent;
|
|
CheckResultHistoryOutputEquation(resultHistoryOutput.Equation, out parentNames, out parameterNameHistoryComponent);
|
|
resultHistoryOutput.SetParentNames(parentNames.ToArray());
|
|
//
|
|
int numCol;
|
|
int numRow;
|
|
List<double> time;
|
|
double[][] values;
|
|
Dictionary<string, double[]> parameterNameValues = new Dictionary<string, double[]>();
|
|
//
|
|
bool entryNamesEqual = true;
|
|
string[] entryNames = null;
|
|
string[] currentEntryNames = null;
|
|
//
|
|
if (parameterNameHistoryComponent.Count > 0)
|
|
{
|
|
numCol = parameterNameHistoryComponent.First().Value.Entries.Count();
|
|
numRow = parameterNameHistoryComponent.First().Value.Entries.First().Value.Values.Count();
|
|
time = parameterNameHistoryComponent.First().Value.Entries.First().Value.Time;
|
|
//
|
|
foreach (var componentEntry in parameterNameHistoryComponent)
|
|
{
|
|
values = componentEntry.Value.GetAllValues();
|
|
// Check if components contain data for the same entry names
|
|
if (entryNames == null) entryNames = componentEntry.Value.Entries.Keys.ToArray();
|
|
if (entryNamesEqual)
|
|
{
|
|
currentEntryNames = componentEntry.Value.Entries.Keys.ToArray();
|
|
if (entryNames.Length != currentEntryNames.Length) entryNamesEqual = false;
|
|
if (entryNamesEqual)
|
|
{
|
|
for (int i = 0; i < entryNames.Length; i++)
|
|
{
|
|
if (entryNames[i] != currentEntryNames[i]) { entryNamesEqual = false; break; }
|
|
}
|
|
}
|
|
}
|
|
//
|
|
parameterNameValues.Add(componentEntry.Key, values.ToFlatArray());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
numCol = 1;
|
|
numRow = 1;
|
|
time = new List<double>() { 1 };
|
|
entryNames = new string[] { "1" };
|
|
}
|
|
// Evaluate the array equation
|
|
foreach (var entry in parameterNameValues) MyNCalc.ExistingParameters[entry.Key] = entry.Value;
|
|
values = MyNCalc.SolveArrayEquation(resultHistoryOutput.Equation).ToJaggedArray(numRow);
|
|
// Create result history set
|
|
HistoryResultEntries historyResultEntries;
|
|
HistoryResultComponent historyResultComponent =
|
|
new HistoryResultComponent(ResultHistoryOutputFromEquation.ComponentName);
|
|
historyResultComponent.Unit = resultHistoryOutput.Unit;
|
|
// Entry names
|
|
if (!entryNamesEqual)
|
|
{
|
|
for (int i = 0; i < numCol; i++) entryNames[i] = (i + 1).ToString();
|
|
}
|
|
//
|
|
for (int j = 0; j < numCol; j++)
|
|
{
|
|
historyResultEntries = new HistoryResultEntries(entryNames[j], false);
|
|
// Set time
|
|
historyResultEntries.Time = time.ToList();
|
|
// Set values
|
|
for (int i = 0; i < numRow; i++) historyResultEntries.Values.Add(values[i][j]);
|
|
//
|
|
historyResultComponent.Entries.Add(historyResultEntries.Name, historyResultEntries);
|
|
}
|
|
// Filter
|
|
if (resultHistoryOutput.Filter1 != null) historyResultComponent.ApplyFilter(resultHistoryOutput.Filter1);
|
|
if (resultHistoryOutput.Filter2 != null) historyResultComponent.ApplyFilter(resultHistoryOutput.Filter2);
|
|
// Field
|
|
HistoryResultField historyResultField = new HistoryResultField(ResultHistoryOutputFromEquation.FieldName);
|
|
historyResultField.Components.Add(historyResultComponent.Name, historyResultComponent);
|
|
// Set
|
|
HistoryResultSet historyResultSet = new HistoryResultSet(resultHistoryOutput.Name);
|
|
historyResultSet.Fields.Add(historyResultField.Name, historyResultField);
|
|
//
|
|
return historyResultSet;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
throw ex;
|
|
}
|
|
finally
|
|
{
|
|
MyNCalc.ExistingParameters = existingParameters;
|
|
}
|
|
}
|
|
private HistoryResultField GetNodeCoordinatesHistoryResultField(int[] nodeIds, OutputNodeCoordinatesEnum nodeCoorType,
|
|
Dictionary<int, int[]> existingStepIncrementIds)
|
|
{
|
|
if (nodeIds != null && nodeCoorType != OutputNodeCoordinatesEnum.Off)
|
|
{
|
|
HistoryResultComponent componentX = new HistoryResultComponent(HOComponentNames.X);
|
|
HistoryResultComponent componentY = new HistoryResultComponent(HOComponentNames.Y);
|
|
HistoryResultComponent componentZ = new HistoryResultComponent(HOComponentNames.Z);
|
|
// Units
|
|
componentX.Unit = StringLengthConverter.GetUnitAbbreviation();
|
|
componentY.Unit = StringLengthConverter.GetUnitAbbreviation();
|
|
componentZ.Unit = StringLengthConverter.GetUnitAbbreviation();
|
|
// Add components for the node coordinates
|
|
List<HistoryResultComponent> allComponents = new List<HistoryResultComponent>();
|
|
allComponents.Add(componentX);
|
|
allComponents.Add(componentY);
|
|
allComponents.Add(componentZ);
|
|
// Add entries for each node id to the empty components
|
|
string name;
|
|
foreach (var newComponent in allComponents)
|
|
{
|
|
newComponent.Entries.Clear();
|
|
for (int i = 0; i < nodeIds.Length; i++)
|
|
{
|
|
name = nodeIds[i].ToString();
|
|
newComponent.Entries.Add(name, new HistoryResultEntries(name, false));
|
|
}
|
|
}
|
|
foreach (var existingStepEntry in existingStepIncrementIds)
|
|
{
|
|
foreach (var incrementId in existingStepEntry.Value)
|
|
{
|
|
// Get node coordinates
|
|
GetNodeCoordinates(nodeIds, existingStepEntry.Key, incrementId, nodeCoorType,
|
|
componentX, componentY, componentZ);
|
|
}
|
|
}
|
|
//
|
|
HistoryResultField historyResultFieldCoor = new HistoryResultField(HOFieldNames.Coordinates);
|
|
historyResultFieldCoor.Components.Add(componentX.Name, componentX);
|
|
historyResultFieldCoor.Components.Add(componentY.Name, componentY);
|
|
historyResultFieldCoor.Components.Add(componentZ.Name, componentZ);
|
|
//
|
|
return historyResultFieldCoor;
|
|
}
|
|
return null;
|
|
}
|
|
private void GetNodeCoordinates(int[] nodeIds, int stepId, int incrementId, OutputNodeCoordinatesEnum nodeCoorType,
|
|
HistoryResultComponent x, HistoryResultComponent y, HistoryResultComponent z)
|
|
{
|
|
int resultNodeId;
|
|
string name;
|
|
float[] valuesX;
|
|
float[] valuesY;
|
|
float[] valuesZ;
|
|
FeNode resultNode;
|
|
FieldData fieldData = GetFieldData(FOFieldNames.Disp, "", stepId, incrementId);
|
|
Field field = GetField(fieldData);
|
|
//
|
|
if (field != null)
|
|
{
|
|
valuesX = field.GetComponentValues(FOComponentNames.U1);
|
|
valuesY = field.GetComponentValues(FOComponentNames.U2);
|
|
valuesZ = field.GetComponentValues(FOComponentNames.U3);
|
|
if (valuesX != null && valuesY != null && valuesZ != null)
|
|
{
|
|
for (int i = 0; i < nodeIds.Length; i++)
|
|
{
|
|
name = nodeIds[i].ToString();
|
|
resultNodeId = _nodeIdsLookUp[nodeIds[i]];
|
|
resultNode = _undeformedNodes[nodeIds[i]];
|
|
//
|
|
if (nodeCoorType == OutputNodeCoordinatesEnum.Undeformed)
|
|
{
|
|
x.Entries[name].Add(fieldData.Time, resultNode.X);
|
|
y.Entries[name].Add(fieldData.Time, resultNode.Y);
|
|
z.Entries[name].Add(fieldData.Time, resultNode.Z);
|
|
}
|
|
else if (nodeCoorType == OutputNodeCoordinatesEnum.Deformed)
|
|
{
|
|
x.Entries[name].Add(fieldData.Time, valuesX[resultNodeId] + resultNode.X);
|
|
y.Entries[name].Add(fieldData.Time, valuesY[resultNodeId] + resultNode.Y);
|
|
z.Entries[name].Add(fieldData.Time, valuesZ[resultNodeId] + resultNode.Z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!(stepId == 1 && incrementId == 0)) // Zero increment - Find all occurrences!!!
|
|
{
|
|
// Return undeformed coordinates if no field is found
|
|
for (int i = 0; i < nodeIds.Length; i++)
|
|
{
|
|
name = nodeIds[i].ToString();
|
|
resultNode = _undeformedNodes[nodeIds[i]];
|
|
x.Entries[name].Add(fieldData.Time, resultNode.X);
|
|
y.Entries[name].Add(fieldData.Time, resultNode.Y);
|
|
z.Entries[name].Add(fieldData.Time, resultNode.Z);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
public void GetHarmonicFromHistoryOutput(int[] nodeIds, ResultHistoryOutputFromField rhoff,
|
|
HistoryResultComponent historyResultComponent)
|
|
{
|
|
int resultNodeId;
|
|
string name;
|
|
float[] values;
|
|
Field field;
|
|
FieldData fieldData = GetFieldData(rhoff.FieldName, historyResultComponent.Name, rhoff.StepId, rhoff.StepIncrementId);
|
|
// Set complex
|
|
ComplexResultTypeEnum prevComplexResultType = _complexResultType;
|
|
float prevComplexAngleDeg = _complexAngleDeg;
|
|
//
|
|
for (int i = 0; i <= 360; i++)
|
|
{
|
|
SetComplexResultTypeAndAngle(ComplexResultTypeEnum.RealAtAngle, i, fieldData);
|
|
//
|
|
field = GetField(fieldData);
|
|
// Filter complex components only to complex field outputs
|
|
if (rhoff.ComplexResultType != ComplexResultTypeEnum.Real && !field.Complex) continue;
|
|
//
|
|
if (field != null)
|
|
{
|
|
values = field.GetComponentValues(historyResultComponent.Name);
|
|
if (values != null)
|
|
{
|
|
for (int j = 0; j < nodeIds.Length; j++)
|
|
{
|
|
name = nodeIds[j].ToString();
|
|
resultNodeId = _nodeIdsLookUp[nodeIds[j]];
|
|
historyResultComponent.Entries[name].Add(i, values[resultNodeId]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Reset complex
|
|
SetComplexResultTypeAndAngle(prevComplexResultType, prevComplexAngleDeg);
|
|
}
|
|
//
|
|
public ResultHistoryOutput[] GetResultHistoryOutputs()
|
|
{
|
|
return _resultHistoryOutputs.Values.ToArray();
|
|
}
|
|
public ResultHistoryOutput GetResultHistoryOutput(string resultHistoryOutputName)
|
|
{
|
|
return _resultHistoryOutputs[resultHistoryOutputName];
|
|
}
|
|
public HistoryResultSet GetHistoryResultSet(string setName)
|
|
{
|
|
HistoryResultSet set = null;
|
|
//
|
|
foreach (var setEntry in _history.Sets)
|
|
{
|
|
if (setEntry.Key.ToUpper() == setName.ToUpper())
|
|
{
|
|
set = setEntry.Value;
|
|
break;
|
|
}
|
|
}
|
|
//
|
|
return set;
|
|
}
|
|
public HistoryResultField GetHistoryResultField(string setName, string fieldName)
|
|
{
|
|
HistoryResultSet set = GetHistoryResultSet(setName);
|
|
HistoryResultField field = null;
|
|
//
|
|
if (set != null)
|
|
{
|
|
foreach (var fieldEntry in set.Fields)
|
|
{
|
|
if (fieldEntry.Key.ToUpper() == fieldName.ToUpper())
|
|
{
|
|
field = fieldEntry.Value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return field;
|
|
}
|
|
public HistoryResultComponent GetHistoryResultComponent(string setName, string fieldName, string componentName)
|
|
{
|
|
HistoryResultField field = GetHistoryResultField(setName, fieldName);
|
|
HistoryResultComponent component = null;
|
|
//
|
|
if (field != null)
|
|
{
|
|
foreach (var componentEntry in field.Components)
|
|
{
|
|
if (componentEntry.Key.ToUpper() == componentName.ToUpper())
|
|
{
|
|
component = componentEntry.Value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return component;
|
|
}
|
|
public HistoryResultEntries GetHistoryResultEntry(string setName, string fieldName, string componentName, string entryName)
|
|
{
|
|
HistoryResultComponent component = GetHistoryResultComponent(setName, fieldName, componentName);
|
|
HistoryResultEntries historyResultEntry = null;
|
|
//
|
|
if (component != null)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key.ToUpper() == entryName.ToUpper())
|
|
{
|
|
historyResultEntry = entry.Value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return historyResultEntry;
|
|
}
|
|
public NamedClass[] GetHistoryOutputsAsNamedItems()
|
|
{
|
|
string[] names = _history.Sets.Keys.ToArray();
|
|
NamedClass[] historyOutputs = new NamedClass[names.Length];
|
|
for (int i = 0; i < names.Length; i++)
|
|
{
|
|
historyOutputs[i] = new EmptyNamedClass(names[i]);
|
|
}
|
|
return historyOutputs;
|
|
}
|
|
public void GetHistoryOutputData(HistoryResultData historyData, out string[] columnNames, out object[][] rowBasedData,
|
|
bool forCsv)
|
|
{
|
|
HistoryResultSet set = _history.Sets[historyData.SetName];
|
|
HistoryResultField field = set.Fields[historyData.FieldName];
|
|
HistoryResultComponent component = field.Components[historyData.ComponentName];
|
|
string unit;
|
|
if (component.Unit != null) unit = component.Unit;
|
|
else unit = GetHistoryUnitAbbreviation(field.Name, component.Name, -1, -1);
|
|
string frequencyColumnName = PrepareFrequencyUnits(component);
|
|
//
|
|
string timeUnit = "[" + GetHistoryUnitAbbreviation("Time", null, -1, -1) + "]";
|
|
string frequencyUnit = "[" + GetHistoryUnitAbbreviation("Frequency", null, -1, -1) + "]";
|
|
string angleUnit = "[" + StringAngleDegConverter.GetUnitAbbreviation() + "]";
|
|
string delimiter;
|
|
if (forCsv) delimiter = " ";
|
|
else delimiter = Environment.NewLine;
|
|
// Sorted time
|
|
double[] sortedTime;
|
|
Dictionary<double, int> timeRowId;
|
|
// Do not sort the time points
|
|
GetSortedTime(new HistoryResultComponent[] { component }, out sortedTime, out timeRowId, false);
|
|
// Create the data array
|
|
int numRow = sortedTime.Length;
|
|
int numCol = component.Entries.Count + 1; // +1 for the time column
|
|
columnNames = new string[numCol];
|
|
rowBasedData = new object[numRow][];
|
|
// Create rows
|
|
for (int i = 0; i < numRow; i++) rowBasedData[i] = new object[numCol];
|
|
// Add time column name
|
|
if (frequencyColumnName != null) columnNames[0] = frequencyColumnName;
|
|
else if (set.Harmonic) columnNames[0] = "Angle " + angleUnit;
|
|
else columnNames[0] = "Time " + timeUnit + delimiter + "Frequency " + frequencyUnit;
|
|
// Fill the data array
|
|
for (int i = 0; i < sortedTime.Length; i++) rowBasedData[i][0] = sortedTime[i];
|
|
// Add data column
|
|
int col = 1;
|
|
int row;
|
|
double[] timePoints;
|
|
double[] values;
|
|
string entryUnit;
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
columnNames[col] = entry.Key;
|
|
// Entry unit
|
|
if (entry.Value.Unit != null) entryUnit = entry.Value.Unit;
|
|
else entryUnit = unit;
|
|
columnNames[col] += delimiter + "[" + entryUnit + "]";
|
|
// Local
|
|
if (entry.Value.Local) columnNames[col] += delimiter + "Local";
|
|
//
|
|
row = 0;
|
|
timePoints = entry.Value.Time.ToArray();
|
|
values = entry.Value.Values.ToArray();
|
|
for (int i = 0; i < timePoints.Length; i++)
|
|
{
|
|
row = timeRowId[timePoints[i]];
|
|
rowBasedData[row][col] = values[i];
|
|
}
|
|
col++;
|
|
}
|
|
}
|
|
private string PrepareFrequencyUnits(HistoryResultComponent component)
|
|
{
|
|
string columnName = null;
|
|
// Frequency data units
|
|
if (component.Name == HOFieldNames.EigenvalueOutput)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.EIGENVALUE) entry.Value.Unit = _unitSystem.EigenvalueUnitAbbreviation;
|
|
else if (entry.Key == HOComponentNames.OMEGA) entry.Value.Unit = _unitSystem.RotationalSpeedUnitAbbreviation;
|
|
else if (entry.Key == HOComponentNames.FREQUENCY) entry.Value.Unit = _unitSystem.FrequencyUnitAbbreviation;
|
|
else if (entry.Key == HOComponentNames.FREQUENCY_IM) entry.Value.Unit = _unitSystem.RotationalSpeedUnitAbbreviation;
|
|
else throw new NotSupportedException();
|
|
}
|
|
columnName = "Mode";
|
|
}
|
|
else if (component.Name == HOFieldNames.ParticipationFactors)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.XCOMPONENT ||
|
|
entry.Key == HOComponentNames.YCOMPONENT ||
|
|
entry.Key == HOComponentNames.ZCOMPONENT)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
else if (entry.Key == HOComponentNames.XROTATION ||
|
|
entry.Key == HOComponentNames.YROTATION ||
|
|
entry.Key == HOComponentNames.ZROTATION)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
}
|
|
columnName = "Mode";
|
|
}
|
|
else if (component.Name == HOFieldNames.EffectiveModalMass)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.XCOMPONENT ||
|
|
entry.Key == HOComponentNames.YCOMPONENT ||
|
|
entry.Key == HOComponentNames.ZCOMPONENT)
|
|
{
|
|
entry.Value.Unit = _unitSystem.MassUnitAbbreviation;
|
|
}
|
|
else if (entry.Key == HOComponentNames.XROTATION ||
|
|
entry.Key == HOComponentNames.YROTATION ||
|
|
entry.Key == HOComponentNames.ZROTATION)
|
|
{
|
|
entry.Value.Unit = _unitSystem.MassUnitAbbreviation;
|
|
}
|
|
}
|
|
columnName = "Mode";
|
|
}
|
|
else if (component.Name == HOFieldNames.TotalEffectiveModalMass || component.Name == HOFieldNames.TotalEffectiveMass)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.XCOMPONENT ||
|
|
entry.Key == HOComponentNames.YCOMPONENT ||
|
|
entry.Key == HOComponentNames.ZCOMPONENT)
|
|
{
|
|
entry.Value.Unit = _unitSystem.MassUnitAbbreviation;
|
|
}
|
|
else if (entry.Key == HOComponentNames.XROTATION ||
|
|
entry.Key == HOComponentNames.YROTATION ||
|
|
entry.Key == HOComponentNames.ZROTATION)
|
|
{
|
|
entry.Value.Unit = _unitSystem.MassUnitAbbreviation;
|
|
}
|
|
}
|
|
columnName = "Total";
|
|
}
|
|
else if (component.Name == HOFieldNames.RelativeEffectiveModalMass)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.XCOMPONENT ||
|
|
entry.Key == HOComponentNames.YCOMPONENT ||
|
|
entry.Key == HOComponentNames.ZCOMPONENT)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
else if (entry.Key == HOComponentNames.XROTATION ||
|
|
entry.Key == HOComponentNames.YROTATION ||
|
|
entry.Key == HOComponentNames.ZROTATION)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
}
|
|
columnName = "Mode";
|
|
}
|
|
else if (component.Name == HOFieldNames.RelativeTotalEffectiveModalMass)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.XCOMPONENT ||
|
|
entry.Key == HOComponentNames.YCOMPONENT ||
|
|
entry.Key == HOComponentNames.ZCOMPONENT)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
else if (entry.Key == HOComponentNames.XROTATION ||
|
|
entry.Key == HOComponentNames.YROTATION ||
|
|
entry.Key == HOComponentNames.ZROTATION)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
}
|
|
columnName = "Total";
|
|
}
|
|
// Steady state
|
|
else if (component.Name.StartsWith(HOFieldNames.ParticipationFactorsForFrequency))
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.FREQUENCY)
|
|
{
|
|
entry.Value.Unit = UnitSystem.FrequencyUnitAbbreviation;
|
|
}
|
|
else if (entry.Key == HOComponentNames.PAR_FACTOR ||
|
|
entry.Key == HOComponentNames.PAR_FACTOR_IM)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
}
|
|
columnName = "Mode";
|
|
}
|
|
// Complex frequency data units
|
|
else if (component.Name.StartsWith(HOFieldNames.ParticipationFactorsForMode))
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.XCOMPONENT ||
|
|
entry.Key == HOComponentNames.YCOMPONENT ||
|
|
entry.Key == HOComponentNames.ZCOMPONENT)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
else if (entry.Key == HOComponentNames.XROTATION ||
|
|
entry.Key == HOComponentNames.YROTATION ||
|
|
entry.Key == HOComponentNames.ZROTATION)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
else if (entry.Key == HOComponentNames.PAR_FACTOR ||
|
|
entry.Key == HOComponentNames.PAR_FACTOR_IM)
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
}
|
|
columnName = "Base Mode";
|
|
}
|
|
else if (component.Name == HOFieldNames.ModalAssuranceCriterium)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key.StartsWith(HOComponentNames.MODE))
|
|
{
|
|
entry.Value.Unit = "/";
|
|
}
|
|
}
|
|
columnName = "Base Mode";
|
|
}
|
|
else if (component.Name == HOFieldNames.AxisDirection)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.X ||
|
|
entry.Key == HOComponentNames.Y ||
|
|
entry.Key == HOComponentNames.Z)
|
|
{
|
|
entry.Value.Unit = _unitSystem.LengthUnitAbbreviation;
|
|
}
|
|
}
|
|
columnName = "Axis";
|
|
}
|
|
else if (component.Name == HOFieldNames.TurningDirection)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
if (entry.Key == HOComponentNames.DIRECTION)
|
|
{
|
|
entry.Value.Unit = "1:F, -1:B";
|
|
}
|
|
}
|
|
columnName = "Mode";
|
|
}
|
|
return columnName;
|
|
}
|
|
public void GetSortedTime(HistoryResultComponent[] components, out double[] sortedTime,
|
|
out Dictionary<double, int> timeRowId, bool sort = true)
|
|
{
|
|
// Collect all time points
|
|
HashSet<double> timePointsHash = new HashSet<double>();
|
|
foreach (var component in components)
|
|
{
|
|
foreach (var entry in component.Entries)
|
|
{
|
|
foreach (var time in entry.Value.Time) timePointsHash.Add(time);
|
|
}
|
|
}
|
|
// Sort time points
|
|
sortedTime = timePointsHash.ToArray();
|
|
if (sort) Array.Sort(sortedTime);
|
|
// Create a map of time point vs row id
|
|
timeRowId = new Dictionary<double, int>();
|
|
for (int i = 0; i < sortedTime.Length; i++) timeRowId.Add(sortedTime[i], i);
|
|
}
|
|
public bool ContainsResultHistoryOutput(string resultHistoryOutputName)
|
|
{
|
|
return _resultHistoryOutputs.ContainsKey(resultHistoryOutputName);
|
|
}
|
|
public void ReplaceResultHistoryOutput(string oldResultHistoryOutputName, ResultHistoryOutput resultHistoryOutput)
|
|
{
|
|
// First try to create the historyResultSet to catch potential errors
|
|
HistoryResultSet historyResultSet = GetHistorySetFromResultHistoryOutput(resultHistoryOutput);
|
|
//
|
|
if (historyResultSet != null)
|
|
{
|
|
// Add result output
|
|
_resultHistoryOutputs.Replace(oldResultHistoryOutputName, resultHistoryOutput.Name, resultHistoryOutput);
|
|
// Add set
|
|
_history.Sets.Replace(oldResultHistoryOutputName, historyResultSet.Name, historyResultSet);
|
|
}
|
|
}
|
|
public void RemoveResultHistoryOutputs(string[] resultHistoryOutputNames)
|
|
{
|
|
RemoveResultHistoryResultSets(resultHistoryOutputNames);
|
|
foreach (var historyOutputName in resultHistoryOutputNames) _resultHistoryOutputs.Remove(historyOutputName);
|
|
}
|
|
public void RemoveResultHistoryResultSets(string[] historyResultSetNames)
|
|
{
|
|
if (_history != null)
|
|
{
|
|
List<string> setsToRemove = new List<string>();
|
|
foreach (var entry in _history.Sets)
|
|
{
|
|
if (historyResultSetNames.Contains(entry.Key)) setsToRemove.Add(entry.Key);
|
|
}
|
|
//
|
|
foreach (var setToRemove in setsToRemove)
|
|
{
|
|
_history.Sets.Remove(setToRemove);
|
|
}
|
|
}
|
|
}
|
|
public void RemoveResultHistoryResultFields(string historyResultSetName, string[] historyResultFieldNames)
|
|
{
|
|
if (_history != null)
|
|
{
|
|
List<string> fieldsToRemove = new List<string>();
|
|
foreach (var entry in _history.Sets[historyResultSetName].Fields)
|
|
{
|
|
if (historyResultFieldNames.Contains(entry.Key)) fieldsToRemove.Add(entry.Key);
|
|
}
|
|
//
|
|
foreach (var fieldToRemove in fieldsToRemove)
|
|
{
|
|
_history.Sets[historyResultSetName].Fields.Remove(fieldToRemove);
|
|
}
|
|
}
|
|
}
|
|
public void RemoveResultHistoryResultComponents(string historyResultSetName,
|
|
string historyResultFieldName,
|
|
string[] historyResultComponentNames)
|
|
{
|
|
if (_history != null)
|
|
{
|
|
List<string> componentsToRemove = new List<string>();
|
|
foreach (var entry in _history.Sets[historyResultSetName].Fields[historyResultFieldName].Components)
|
|
{
|
|
if (historyResultComponentNames.Contains(entry.Key)) componentsToRemove.Add(entry.Key);
|
|
}
|
|
//
|
|
foreach (var componentToRemove in componentsToRemove)
|
|
{
|
|
_history.Sets[historyResultSetName].Fields[historyResultFieldName].Components.Remove(componentToRemove);
|
|
}
|
|
}
|
|
}
|
|
private List<ResultHistoryOutput> GetResultHistoryOutputIndependencySequence()
|
|
{
|
|
string[] parentHistoryNames;
|
|
HashSet<string> allNames = new HashSet<string>();
|
|
ResultHistoryOutput rho;
|
|
Node<string> node;
|
|
Graph<string> dependencyGraph = new Graph<string>();
|
|
Dictionary<string, Node<string>> nodes = new Dictionary<string, Node<string>>();
|
|
//
|
|
foreach (var entry in _resultHistoryOutputs)
|
|
{
|
|
rho = entry.Value;
|
|
//
|
|
allNames.Clear();
|
|
allNames.Add(rho.Name);
|
|
parentHistoryNames = rho.GetParentNames();
|
|
allNames.UnionWith(parentHistoryNames);
|
|
// Add nodes
|
|
foreach (var name in allNames)
|
|
{
|
|
if (!nodes.ContainsKey(name))
|
|
{
|
|
node = new Node<string>(name);
|
|
nodes.Add(name, node);
|
|
dependencyGraph.AddNode(node);
|
|
}
|
|
}
|
|
// Add connections
|
|
foreach (var parentHistoryName in parentHistoryNames)
|
|
{
|
|
dependencyGraph.AddDirectedEdge(nodes[rho.Name], nodes[parentHistoryName]);
|
|
}
|
|
}
|
|
// Use only one sub-graph - NOT WORKING FOR DIRECTED GRAPHS
|
|
//if (resultHistoryOutput != null)
|
|
//{
|
|
// List<Graph<string>> subGraphs = dependencyGraph.GetConnectedSubgraphs();
|
|
// foreach (var subGraph in subGraphs)
|
|
// {
|
|
// if (subGraph.Contains(resultHistoryOutput.Name))
|
|
// {
|
|
// dependencyGraph = subGraph;
|
|
// break;
|
|
// }
|
|
// }
|
|
//}
|
|
//
|
|
List<string> independencySequence = dependencyGraph.GetIndependencyList();
|
|
//
|
|
List<ResultHistoryOutput> resultList = new List<ResultHistoryOutput>();
|
|
foreach (var name in independencySequence)
|
|
{
|
|
if (_resultHistoryOutputs.TryGetValue(name, out rho)) resultList.Add(rho);
|
|
}
|
|
//
|
|
return resultList;
|
|
}
|
|
// Equation
|
|
public string[] GetPossibleHistoryEquationParameters()
|
|
{
|
|
string variable;
|
|
string separator = ResultHistoryOutputFromEquation.EquationSeparator;
|
|
List<string> possibleEquationParameters = new List<string>();
|
|
//
|
|
foreach (var setEntry in _history.Sets)
|
|
{
|
|
foreach (var fieldEntry in setEntry.Value.Fields)
|
|
{
|
|
foreach (var componentEntry in fieldEntry.Value.Components)
|
|
{
|
|
variable = setEntry.Key + separator + fieldEntry.Key + separator + componentEntry.Key;
|
|
possibleEquationParameters.Add(variable);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return possibleEquationParameters.ToArray();
|
|
}
|
|
public string CheckResultHistoryOutputEquation(string equation, out HashSet<string> parentNames,
|
|
out Dictionary<string, HistoryResultComponent> parameterNameHistoryComponent)
|
|
{
|
|
parentNames = new HashSet<string>();
|
|
parameterNameHistoryComponent = new Dictionary<string, HistoryResultComponent>();
|
|
OrderedDictionary<string, object> existingParameters = MyNCalc.ExistingParameters.DeepCopy();
|
|
//
|
|
try
|
|
{
|
|
int count = 1;
|
|
string[] possibleEquationParameters = GetPossibleHistoryEquationParameters();
|
|
foreach (var possibleParameter in possibleEquationParameters)
|
|
{
|
|
MyNCalc.ExistingParameters[possibleParameter] = count++ * 0.111;
|
|
}
|
|
//
|
|
HashSet<string> parameterNames;
|
|
bool hasErrors = MyNCalc.HasErrors(equation, out parameterNames);
|
|
//
|
|
//if (parameterNames == null || parameterNames.Count == 0 ||
|
|
// parameterNames.Intersect(possibleEquationParameters).Count() == 0)
|
|
// throw new CaeException("At least one history output component must be used in the equation.");
|
|
//
|
|
string[] tmp;
|
|
string[] splitter = new string[] { ResultHistoryOutputFromEquation.EquationSeparator };
|
|
HistoryResultSet historyResultSet;
|
|
HistoryResultField historyResultField;
|
|
HistoryResultComponent historyResultComponent;
|
|
HistoryResultEntries historyResultEntry;
|
|
//
|
|
int numRows = -1;
|
|
int numColumns = -1;
|
|
//int numIncrements = -1;
|
|
double[][] values;
|
|
//HashSet<string> entryNames = null;
|
|
foreach (var parameterName in parameterNames)
|
|
{
|
|
if (possibleEquationParameters.Contains(parameterName))
|
|
{
|
|
tmp = parameterName.Split(splitter, StringSplitOptions.None);
|
|
if (tmp.Length != 3) continue;
|
|
//
|
|
if (!_history.Sets.TryGetValue(tmp[0], out historyResultSet))
|
|
throw new CaeException("The history output " + tmp[0] + " does not exist.");
|
|
if (!historyResultSet.Fields.TryGetValue(tmp[1], out historyResultField))
|
|
throw new CaeException("The field " + tmp[1] + " of the history output " + tmp[0] + " does not exist.");
|
|
if (!historyResultField.Components.TryGetValue(tmp[2], out historyResultComponent))
|
|
throw new CaeException("The component " + tmp[2] + " of the history output " + tmp[0] + " does not exist.");
|
|
//
|
|
values = historyResultComponent.GetAllValues();
|
|
if (numRows == -1) numRows = values.Length;
|
|
if (numColumns == -1) numColumns = values[0].Length;
|
|
//
|
|
if (numRows != values.Length)
|
|
throw new CaeException("All history output components used in the equation must contain the same number of " +
|
|
"time increments (rows).");
|
|
//
|
|
if (numColumns != values[0].Length)
|
|
throw new CaeException("All history output components used in the equation must contain the same number of " +
|
|
"items (columns).");
|
|
//
|
|
//if (entryNames == null) entryNames = new HashSet<string>(historyResultComponent.Entries.Keys);
|
|
//else if (entryNames.Union(historyResultComponent.Entries.Keys).Count() != entryNames.Count)
|
|
// throw new CaeException("All selected history output components must contain the same items.");
|
|
//
|
|
//historyResultEntry = historyResultComponent.Entries.First().Value;
|
|
////
|
|
//if (numIncrements == -1) numIncrements = historyResultEntry.Values.Count();
|
|
//else if (numIncrements != historyResultEntry.Values.Count())
|
|
// throw new CaeException("All selected history output components must contain the same number " +
|
|
// "of time increments.");
|
|
//
|
|
parentNames.Add(tmp[0]);
|
|
parameterNameHistoryComponent.Add(parameterName, historyResultComponent);
|
|
}
|
|
}
|
|
//
|
|
return null;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return ex.Message;
|
|
}
|
|
finally
|
|
{
|
|
MyNCalc.ExistingParameters = existingParameters;
|
|
}
|
|
}
|
|
//
|
|
public bool AreResultHistoryOutputsInCyclicDependance(string oldResultHistoryOutputName,
|
|
ResultHistoryOutput resultHistoryOutput)
|
|
{
|
|
Dictionary<string, ResultHistoryOutput> resultHistoryOutputs = new Dictionary<string, ResultHistoryOutput>();
|
|
foreach (var entry in _resultHistoryOutputs)
|
|
{
|
|
if (entry.Key != oldResultHistoryOutputName)
|
|
resultHistoryOutputs.Add(entry.Key, entry.Value);
|
|
}
|
|
resultHistoryOutputs.Add(resultHistoryOutput.Name, resultHistoryOutput);
|
|
//
|
|
return AreResultHistoryOutputsInCyclicDependance(resultHistoryOutputs);
|
|
}
|
|
private bool AreResultHistoryOutputsInCyclicDependance(Dictionary<string, ResultHistoryOutput> resultHistoryOutputs)
|
|
{
|
|
int count = 0;
|
|
bool result;
|
|
foreach (var entry in resultHistoryOutputs)
|
|
{
|
|
result = RecursiveCheck(ref count, entry.Value.Name, entry.Value.Name, resultHistoryOutputs);
|
|
if (result) return true;
|
|
}
|
|
return false;
|
|
}
|
|
private bool RecursiveCheck(ref int count, string firstName, string name,
|
|
Dictionary<string, ResultHistoryOutput> resultHistoryOutputs)
|
|
{
|
|
if (count > 1000) return true;
|
|
//
|
|
ResultHistoryOutput resultHistoryOutput;
|
|
if (resultHistoryOutputs.TryGetValue(name, out resultHistoryOutput))
|
|
{
|
|
string[] parents = resultHistoryOutput.GetParentNames();
|
|
if (parents == null) return false;
|
|
//
|
|
bool result;
|
|
foreach (string parent in parents)
|
|
{
|
|
if (parent == firstName) return true;
|
|
//
|
|
count++;
|
|
result = RecursiveCheck(ref count, firstName, parent, resultHistoryOutputs);
|
|
if (result) return true;
|
|
count--;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Scaled results values
|
|
public void GetNodesAndValues(FieldData fieldData, int[] nodeIds, out double[][] nodeCoor, out float[] values)
|
|
{
|
|
nodeCoor = new double[nodeIds.Length][];
|
|
for (int i = 0; i < nodeIds.Length; i++)
|
|
{
|
|
nodeCoor[i] = Mesh.Nodes[nodeIds[i]].Coor;
|
|
}
|
|
values = GetValues(fieldData, nodeIds);
|
|
}
|
|
//
|
|
public PartExchangeData GetAllNodesCellsAndValues(FieldData fData)
|
|
{
|
|
PartExchangeData pData = new PartExchangeData();
|
|
_mesh.GetAllNodesAndCells(out pData.Nodes.Ids, out pData.Nodes.Coor, out pData.Cells.Ids,
|
|
out pData.Cells.CellNodeIds, out pData.Cells.Types);
|
|
if (!fData.Valid) pData.Nodes.Values = null;
|
|
else pData.Nodes.Values = GetValues(fData, pData.Nodes.Ids);
|
|
return pData;
|
|
}
|
|
public PartExchangeData GetSetNodesCellsAndValues(FeGroup elementSet, FieldData fData)
|
|
{
|
|
PartExchangeData pData = new PartExchangeData();
|
|
_mesh.GetSetNodesAndCells(elementSet, out pData.Nodes.Ids, out pData.Nodes.Coor, out pData.Cells.Ids,
|
|
out pData.Cells.CellNodeIds, out pData.Cells.Types);
|
|
if (!fData.Valid) pData.Nodes.Values = null;
|
|
else pData.Nodes.Values = GetValues(fData, pData.Nodes.Ids);
|
|
return pData;
|
|
}
|
|
public PartExchangeData GetVisualizationNodesCellsAndValues(BasePart part, FieldData fData)
|
|
{
|
|
PartExchangeData pData = new PartExchangeData();
|
|
_mesh.GetVisualizationNodesAndCells(part, out pData.Nodes.Ids, out pData.Nodes.Coor, out pData.Cells.Ids,
|
|
out pData.Cells.CellNodeIds, out pData.Cells.Types);
|
|
if (!fData.Valid) pData.Nodes.Values = null;
|
|
else
|
|
{
|
|
pData.Nodes.Values = GetValues(fData, pData.Nodes.Ids);
|
|
pData.ExtremeNodes = GetScaledExtremeValues(part.Name, fData, 1);
|
|
}
|
|
return pData;
|
|
}
|
|
public PartExchangeData GetEdgesNodesAndCells(FeGroup elementSet, FieldData fData) // must use fData
|
|
{
|
|
PartExchangeData resultData = new PartExchangeData();
|
|
_mesh.GetNodesAndCellsForModelEdges(elementSet, out resultData.Nodes.Ids, out resultData.Nodes.Coor,
|
|
out resultData.Cells.CellNodeIds, out resultData.Cells.Types);
|
|
return resultData;
|
|
}
|
|
public void GetUndeformedNodesAndCells(BasePart part, out double[][] nodeCoor, out int[][] cells, out int[] cellTypes)
|
|
{
|
|
int[] nodeIds, cellIds;
|
|
Dictionary<int, FeNode> tmp = _mesh.Nodes;
|
|
_mesh.Nodes = _undeformedNodes;
|
|
_mesh.GetVisualizationNodesAndCells(part, out nodeIds, out nodeCoor, out cellIds, out cells, out cellTypes);
|
|
// Add exploded view
|
|
if (part.Offset != null && (part.Offset[0] != 0 || part.Offset[1] != 0 || part.Offset[2] != 0))
|
|
{
|
|
for (int i = 0; i < nodeCoor.Length; i++)
|
|
{
|
|
nodeCoor[i][0] += part.Offset[0];
|
|
nodeCoor[i][1] += part.Offset[1];
|
|
nodeCoor[i][2] += part.Offset[2];
|
|
}
|
|
}
|
|
//
|
|
_mesh.Nodes = tmp;
|
|
}
|
|
public void GetUndeformedModelEdges(BasePart part, out double[][] nodeCoor, out int[][] cells, out int[] cellTypes)
|
|
{
|
|
int[] nodeIds;
|
|
Dictionary<int, FeNode> tmp = _mesh.Nodes;
|
|
_mesh.Nodes = _undeformedNodes;
|
|
_mesh.GetNodesAndCellsForModelEdges(part, out nodeIds, out nodeCoor, out cells, out cellTypes);
|
|
// Add exploded view
|
|
if (part.Offset != null && (part.Offset[0] != 0 || part.Offset[1] != 0 || part.Offset[2] != 0))
|
|
{
|
|
for (int i = 0; i < nodeCoor.Length; i++)
|
|
{
|
|
nodeCoor[i][0] += part.Offset[0];
|
|
nodeCoor[i][1] += part.Offset[1];
|
|
nodeCoor[i][2] += part.Offset[2];
|
|
}
|
|
}
|
|
//
|
|
_mesh.Nodes = tmp;
|
|
}
|
|
// Animation
|
|
public void GetScaleFactorAnimationData(BasePart part, FieldData fData, float scale, int numFrames,
|
|
out PartExchangeData modelResultData,
|
|
out PartExchangeData modelEdgesResultData,
|
|
out PartExchangeData locatorResultData)
|
|
{
|
|
modelEdgesResultData = null;
|
|
bool modelEdges = part.PartType.HasEdges() && part.Visualization.EdgeCells != null;
|
|
// Undeforme part
|
|
SetPartDeformation(part, 0, 0, 0);
|
|
// Model
|
|
modelResultData = new PartExchangeData();
|
|
_mesh.GetVisualizationNodesAndCells(part, out modelResultData.Nodes.Ids, out modelResultData.Nodes.Coor,
|
|
out modelResultData.Cells.Ids, out modelResultData.Cells.CellNodeIds,
|
|
out modelResultData.Cells.Types);
|
|
// Edges
|
|
if (modelEdges)
|
|
{
|
|
modelEdgesResultData = new PartExchangeData();
|
|
_mesh.GetNodesAndCellsForModelEdges(part, out modelEdgesResultData.Nodes.Ids,
|
|
out modelEdgesResultData.Nodes.Coor,
|
|
out modelEdgesResultData.Cells.CellNodeIds,
|
|
out modelEdgesResultData.Cells.Types);
|
|
}
|
|
// Locator
|
|
locatorResultData = new PartExchangeData();
|
|
_mesh.GetSetNodesAndCells(part, out locatorResultData.Nodes.Ids, out locatorResultData.Nodes.Coor,
|
|
out locatorResultData.Cells.Ids, out locatorResultData.Cells.CellNodeIds,
|
|
out locatorResultData.Cells.Types);
|
|
// Values
|
|
if (!fData.Valid)
|
|
{
|
|
modelResultData.Nodes.Values = null;
|
|
locatorResultData.Nodes.Values = null;
|
|
}
|
|
else
|
|
{
|
|
modelResultData.Nodes.Values = GetValues(fData, modelResultData.Nodes.Ids);
|
|
modelResultData.ExtremeNodes = GetExtremeValues(part.Name, fData);
|
|
locatorResultData.Nodes.Values = GetValues(fData, locatorResultData.Nodes.Ids);
|
|
}
|
|
// Aniumation
|
|
modelResultData.NodesAnimation = new NodesExchangeData[numFrames];
|
|
modelResultData.ExtremeNodesAnimation = new NodesExchangeData[numFrames];
|
|
if (modelEdges) modelEdgesResultData.NodesAnimation = new NodesExchangeData[numFrames];
|
|
locatorResultData.NodesAnimation = new NodesExchangeData[numFrames];
|
|
//
|
|
float[] ratios;
|
|
if (fData.StepType == StepTypeEnum.Frequency || fData.StepType == StepTypeEnum.Buckling) ratios = GetRelativeModalScales(numFrames);
|
|
else ratios = GetRelativeScales(numFrames);
|
|
//
|
|
float absoluteScale;
|
|
float relativeScale;
|
|
bool invariant = IsComponentInvariant(fData);
|
|
//
|
|
for (int i = 0; i < numFrames; i++)
|
|
{
|
|
relativeScale = ratios[i];
|
|
absoluteScale = relativeScale * scale;
|
|
// Deform mesh
|
|
SetPartDeformation(part, absoluteScale, fData.StepId, fData.StepIncrementId);
|
|
// Get scaled model
|
|
modelResultData.NodesAnimation[i] = new NodesExchangeData();
|
|
modelResultData.NodesAnimation[i].Coor = _mesh.GetNodeSetCoor(modelResultData.Nodes.Ids);
|
|
// Get scaled edges
|
|
if (modelEdges)
|
|
{
|
|
modelEdgesResultData.NodesAnimation[i] = new NodesExchangeData();
|
|
modelEdgesResultData.NodesAnimation[i].Coor = _mesh.GetNodeSetCoor(modelEdgesResultData.Nodes.Ids);
|
|
}
|
|
// Get scaled locator
|
|
locatorResultData.NodesAnimation[i] = new NodesExchangeData();
|
|
locatorResultData.NodesAnimation[i].Coor = _mesh.GetNodeSetCoor(locatorResultData.Nodes.Ids);
|
|
// Scale values
|
|
if (invariant) relativeScale = Math.Abs(relativeScale);
|
|
// Model
|
|
ScaleValues(relativeScale, modelResultData.Nodes.Values, out modelResultData.NodesAnimation[i].Values);
|
|
modelResultData.ExtremeNodesAnimation[i] = GetScaledExtremeValues(part.Name, fData, relativeScale);
|
|
// Locator
|
|
ScaleValues(relativeScale, locatorResultData.Nodes.Values, out locatorResultData.NodesAnimation[i].Values);
|
|
}
|
|
}
|
|
public void GetTimeIncrementAnimationData(BasePart part, FieldData fData, float scale,
|
|
out PartExchangeData modelResultData,
|
|
out PartExchangeData modelEdgesResultData,
|
|
out PartExchangeData locatorResultData)
|
|
{
|
|
modelEdgesResultData = null;
|
|
bool modelEdges = part.PartType.HasEdges() && part.Visualization.EdgeCells != null;
|
|
// Undeforme part
|
|
SetPartDeformation(part, 0, 0, 0);
|
|
// Model
|
|
modelResultData = GetVisualizationNodesCellsAndValues(part, fData);
|
|
// Edges
|
|
if (modelEdges) modelEdgesResultData = GetEdgesNodesAndCells(part, fData);
|
|
// Locator
|
|
locatorResultData = GetSetNodesCellsAndValues(part, fData);
|
|
// Get all existing increments
|
|
Dictionary<int, int[]> existingStepIncrementIds = GetExistingIncrementIds(fData.Name, fData.Component);
|
|
// Count all existing increments
|
|
int numFrames = 0;
|
|
foreach (var entry in existingStepIncrementIds) numFrames += entry.Value.Length;
|
|
// Create animation frames
|
|
modelResultData.NodesAnimation = new NodesExchangeData[numFrames];
|
|
modelResultData.ExtremeNodesAnimation = new NodesExchangeData[numFrames];
|
|
if (modelEdges) modelEdgesResultData.NodesAnimation = new NodesExchangeData[numFrames];
|
|
locatorResultData.NodesAnimation = new NodesExchangeData[numFrames];
|
|
//
|
|
PartExchangeData data;
|
|
FieldData tmpFieldData = new FieldData(fData); // create a copy
|
|
int count = 0;
|
|
foreach (var entry in existingStepIncrementIds)
|
|
{
|
|
tmpFieldData.StepId = entry.Key;
|
|
foreach (var incrementId in entry.Value)
|
|
{
|
|
tmpFieldData.StepIncrementId = incrementId;
|
|
// Deform part
|
|
SetPartDeformation(part, scale, tmpFieldData.StepId, tmpFieldData.StepIncrementId);
|
|
// Model
|
|
data = GetVisualizationNodesCellsAndValues(part, tmpFieldData);
|
|
modelResultData.NodesAnimation[count] = data.Nodes;
|
|
modelResultData.ExtremeNodesAnimation[count] = data.ExtremeNodes;
|
|
// Edges
|
|
if (modelEdges)
|
|
{
|
|
data = GetEdgesNodesAndCells(part, tmpFieldData);
|
|
modelEdgesResultData.NodesAnimation[count] = data.Nodes;
|
|
}
|
|
// Locator
|
|
data = GetSetNodesCellsAndValues(part, tmpFieldData);
|
|
locatorResultData.NodesAnimation[count] = data.Nodes;
|
|
//
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
private float[] GetRelativeScales(int numFrames)
|
|
{
|
|
float ratio = 1f / (numFrames - 1);
|
|
float[] ratios = new float[numFrames];
|
|
for (int i = 0; i < numFrames; i++) ratios[i] = i * ratio;
|
|
return ratios;
|
|
}
|
|
private float[] GetRelativeModalScales(int numFrames)
|
|
{
|
|
float ratio = 2f / (numFrames - 1);
|
|
float[] ratios = new float[numFrames];
|
|
for (int i = 0; i < numFrames; i++)
|
|
{
|
|
ratios[i] = (float)Math.Sin((-1 + i * ratio) * Math.PI / 2); // end with 1
|
|
}
|
|
return ratios;
|
|
}
|
|
//
|
|
public void ScaleNodeCoordinates(string deformationFieldOutputName, float scale, int stepId, int stepIncrementId,
|
|
int[] globalNodeIds, ref double[][] nodes)
|
|
{
|
|
if (deformationFieldOutputName == FOFieldNames.Default)
|
|
deformationFieldOutputName = GetInternalDeformationFieldOutputName(stepId, stepIncrementId);
|
|
//
|
|
if (scale != 0)
|
|
{
|
|
float[][] deformations = GetNodalMeshDeformations(deformationFieldOutputName, stepId, stepIncrementId);
|
|
if (deformations != null)
|
|
{
|
|
for (int i = 0; i < nodes.Length; i++)
|
|
{
|
|
int resultNodeId;
|
|
// Scale only result parts
|
|
if (_nodeIdsLookUp.TryGetValue(globalNodeIds[i], out resultNodeId))
|
|
{
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
nodes[i][j] += scale * deformations[j][resultNodeId];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
public void ScaleValues(float scale, float[] values, out float[] scaledValues)
|
|
{
|
|
if (values == null) scaledValues = null;
|
|
else
|
|
{
|
|
scaledValues = new float[values.Length];
|
|
if (scale != 0)
|
|
{
|
|
for (int i = 0; i < values.Length; i++)
|
|
{
|
|
scaledValues[i] = values[i] * scale;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
public float GetMaxDeformation()
|
|
{
|
|
double fieldMax;
|
|
double max = -double.MaxValue;
|
|
double value;
|
|
string deformationFieldOutputName;
|
|
string[] componentNames = GetFieldComponentNames(_deformationFieldOutputName);
|
|
//
|
|
foreach (var entry in _fields)
|
|
{
|
|
deformationFieldOutputName = GetInternalDeformationFieldOutputName(entry.Key.StepId, entry.Key.StepIncrementId);
|
|
if (entry.Key.Name == deformationFieldOutputName)
|
|
{
|
|
fieldMax = 0;
|
|
//
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
value = Math.Pow(entry.Value.GetComponentAbsMax(componentName), 2);
|
|
if (!double.IsNaN(value)) fieldMax += value;
|
|
}
|
|
//
|
|
if (fieldMax > 0) fieldMax = Math.Sqrt(fieldMax);
|
|
//
|
|
if (fieldMax > max) max = fieldMax;
|
|
}
|
|
}
|
|
return (float)max;
|
|
}
|
|
public float GetMaxDeformation(int stepId, int stepIncrementId)
|
|
{
|
|
double max = -double.MaxValue;
|
|
double value;
|
|
string deformationFieldOutputName;
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (entry.Key.StepId == stepId && entry.Key.StepIncrementId == stepIncrementId)
|
|
{
|
|
deformationFieldOutputName = GetInternalDeformationFieldOutputName(entry.Key.StepId, entry.Key.StepIncrementId);
|
|
//
|
|
if (entry.Key.Name == deformationFieldOutputName)
|
|
{
|
|
max = 0;
|
|
string[] componentNames = GetFieldComponentNames(deformationFieldOutputName);
|
|
//
|
|
foreach (var componentName in componentNames)
|
|
{
|
|
value = Math.Pow(entry.Value.GetComponentAbsMax(componentName), 2);
|
|
if (!double.IsNaN(value)) max += value;
|
|
}
|
|
//
|
|
if (max > 0) max = Math.Sqrt(max);
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return (float)max;
|
|
}
|
|
//
|
|
public double GetEdgeLength(int geometryEdgeId)
|
|
{
|
|
int[] itemTypePartIds = FeMesh.GetItemTypePartIdsFromGeometryId(geometryEdgeId);
|
|
BasePart part = _mesh.GetPartFromId(itemTypePartIds[2]);
|
|
int[] nodeIds = part.Visualization.GetOrderedNodeIdsForEdgeId(itemTypePartIds[0]);
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
// Wear
|
|
public bool ComputeWear(int[] slipStepIds, Dictionary<int, double> nodeIdCoefficient,
|
|
int numOfSmoothingSteps, Dictionary<int, bool[]> nodeIdZeroDisplacements)
|
|
{
|
|
if (slipStepIds != null && slipStepIds.Length > 0 && CheckFieldAndHistoryTimes())
|
|
{
|
|
ComputeHistoryWearSlidingDistance();
|
|
//
|
|
HistoryResultComponent slidingDistanceAll =
|
|
GetHistoryResultComponent(HOSetNames.ContactWear, HOFieldNames.SlidingDistance, HOComponentNames.All);
|
|
if (slidingDistanceAll != null)
|
|
{
|
|
CreateAveragedFieldFromElementFaceHistory(FOFieldNames.SlidingDistance, slidingDistanceAll, true);
|
|
}
|
|
//
|
|
HistoryResultField surfaceNormalField = GetHistoryResultField(HOSetNames.ContactWear, HOFieldNames.SurfaceNormal);
|
|
if (surfaceNormalField != null)
|
|
{
|
|
HistoryResultComponent all = surfaceNormalField.Components[HOComponentNames.All];
|
|
HistoryResultComponent n1 = surfaceNormalField.Components[HOComponentNames.N1];
|
|
HistoryResultComponent n2 = surfaceNormalField.Components[HOComponentNames.N2];
|
|
HistoryResultComponent n3 = surfaceNormalField.Components[HOComponentNames.N3];
|
|
//
|
|
CreateAveragedFieldFromElementFaceHistory(FOFieldNames.SurfaceNormal, all, false);
|
|
CreateAveragedFieldFromElementFaceHistory(FOFieldNames.SurfaceNormal, n1, false);
|
|
CreateAveragedFieldFromElementFaceHistory(FOFieldNames.SurfaceNormal, n2, false);
|
|
CreateAveragedFieldFromElementFaceHistory(FOFieldNames.SurfaceNormal, n3, false);
|
|
}
|
|
//
|
|
return ComputeSlidingWearFields(slipStepIds, nodeIdCoefficient, numOfSmoothingSteps, nodeIdZeroDisplacements);
|
|
}
|
|
else return false;
|
|
}
|
|
private bool CheckFieldAndHistoryTimes()
|
|
{
|
|
HistoryResultField relativeContactDisplacement =
|
|
GetHistoryResultField(HOSetNames.AllContactElements, HOFieldNames.RelativeContactDisplacement);
|
|
if (relativeContactDisplacement != null)
|
|
{
|
|
HistoryResultComponent tang1 = relativeContactDisplacement.Components[HOComponentNames.Tang1];
|
|
if (tang1 != null)
|
|
{
|
|
// Sorted time
|
|
double[] historySortedTime;
|
|
Dictionary<double, int> timeRowId;
|
|
GetSortedTime(new HistoryResultComponent[] { tang1 }, out historySortedTime, out timeRowId);
|
|
//
|
|
int fieldIncrementsCount = 0;
|
|
int[] stepIds = GetAllStepIds();
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
int[] stepIncrementIds = GetStepIncrementIds(stepIds[i]);
|
|
fieldIncrementsCount += stepIncrementIds.Length;
|
|
}
|
|
//
|
|
if (historySortedTime.Length == fieldIncrementsCount - 1) // -1 for Zero increment - Find all occurrences!!!
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
private void ComputeHistoryWearSlidingDistance()
|
|
{
|
|
HistoryResultField relativeContactDisplacement =
|
|
GetHistoryResultField(HOSetNames.AllContactElements, HOFieldNames.RelativeContactDisplacement);
|
|
//
|
|
if (relativeContactDisplacement != null)
|
|
{
|
|
HistoryResultComponent tang1 = relativeContactDisplacement.Components[HOComponentNames.Tang1];
|
|
HistoryResultComponent s1 = ComputeRelativeDisplacement(HOComponentNames.S1, tang1);
|
|
//
|
|
HistoryResultComponent tang2 = relativeContactDisplacement.Components[HOComponentNames.Tang2];
|
|
HistoryResultComponent s2 = ComputeRelativeDisplacement(HOComponentNames.S2, tang2);
|
|
//
|
|
HistoryResultComponent all =
|
|
ComputeVectorMagnitude(HOComponentNames.All, new HistoryResultComponent[] { s1, s2 });
|
|
//
|
|
relativeContactDisplacement = new HistoryResultField(HOFieldNames.SlidingDistance);
|
|
relativeContactDisplacement.Components.Add(all.Name, all);
|
|
relativeContactDisplacement.Components.Add(s1.Name, s1);
|
|
relativeContactDisplacement.Components.Add(s2.Name, s2);
|
|
|
|
// Use tang1 since it contains only values != 0
|
|
HistoryResultComponent[] normalComponents = GetNormalsFromElementFaceHistory(tang1);
|
|
//
|
|
HistoryResultField surfaceNormalsField = new HistoryResultField(HOFieldNames.SurfaceNormal);
|
|
surfaceNormalsField.Components.Add(normalComponents[0].Name, normalComponents[0]); // All
|
|
surfaceNormalsField.Components.Add(normalComponents[1].Name, normalComponents[1]); // N1
|
|
surfaceNormalsField.Components.Add(normalComponents[2].Name, normalComponents[2]); // N2
|
|
surfaceNormalsField.Components.Add(normalComponents[3].Name, normalComponents[3]); // N3
|
|
//
|
|
HistoryResultSet contactWear = new HistoryResultSet(HOSetNames.ContactWear);
|
|
contactWear.Fields.Add(relativeContactDisplacement.Name, relativeContactDisplacement);
|
|
contactWear.Fields.Add(surfaceNormalsField.Name, surfaceNormalsField);
|
|
//
|
|
_history.Sets.Add(contactWear.Name, contactWear);
|
|
}
|
|
}
|
|
public bool ComputeSlidingWearFields(int[] slipStepIds, Dictionary<int, double> nodeIdCoefficient,
|
|
int numOfSmoothingSteps, Dictionary<int, bool[]> nodeIdZeroDisplacements)
|
|
{
|
|
HistoryResultComponent slidingDistanceAll =
|
|
GetHistoryResultComponent(HOSetNames.ContactWear, HOFieldNames.SlidingDistance, HOComponentNames.All);
|
|
//
|
|
if (slidingDistanceAll != null)
|
|
{
|
|
float[] coefficients = new float[_nodeIdsLookUp.Count()];
|
|
if (nodeIdCoefficient != null)
|
|
{
|
|
foreach (var entry in _nodeIdsLookUp) coefficients[entry.Value] = (float)nodeIdCoefficient[entry.Key];
|
|
}
|
|
else
|
|
{
|
|
foreach (var entry in _nodeIdsLookUp) coefficients[entry.Value] = 0;
|
|
}
|
|
//
|
|
float dh;
|
|
float[] pressureValues;
|
|
float[] slidingDistanceValues;
|
|
float[] normalN1Values;
|
|
float[] normalN2Values;
|
|
float[] normalN3Values;
|
|
float[] depthValuesMag;
|
|
float[] depthValuesH1;
|
|
float[] depthValuesH2;
|
|
float[] depthValuesH3;
|
|
float[] prevDepthValuesMag = null;
|
|
float[] prevDepthValuesH1 = null;
|
|
float[] prevDepthValuesH2 = null;
|
|
float[] prevDepthValuesH3 = null;
|
|
float[] dispValuesMag;
|
|
float[] dispValuesU1;
|
|
float[] dispValuesU2;
|
|
float[] dispValuesU3;
|
|
//
|
|
Field pressureField;
|
|
Field slidingDistanceField;
|
|
Field depthField;
|
|
Field normalField;
|
|
Field dispField;
|
|
Field meshUpdateField;
|
|
//
|
|
FieldData pressureData;
|
|
FieldData slidingDistanceData;
|
|
FieldData depthData;
|
|
FieldData normalData;
|
|
FieldData dispData;
|
|
FieldData meshUpdateData;
|
|
//
|
|
int id;
|
|
Vec3D normal = new Vec3D();
|
|
//
|
|
for (int i = 0; i < slipStepIds.Length; i++)
|
|
{
|
|
int[] stepIncrementIds = GetStepIncrementIds(slipStepIds[i]);
|
|
//
|
|
for (int j = 0; j < stepIncrementIds.Length; j++)
|
|
{
|
|
if (slipStepIds[i] == 0 && stepIncrementIds[j] == 0) continue;
|
|
// Pressure
|
|
pressureData = GetFieldData(FOFieldNames.Contact, "", slipStepIds[i], stepIncrementIds[j]);
|
|
pressureField = GetField(pressureData);
|
|
if (pressureField != null)
|
|
{
|
|
pressureValues = pressureField.GetComponentValues(FOComponentNames.CPress);
|
|
// Disp
|
|
dispData = GetFieldData(FOFieldNames.Disp, "", slipStepIds[i], stepIncrementIds[j]);
|
|
dispField = GetField(dispData);
|
|
dispValuesMag = new float[pressureValues.Length];
|
|
dispValuesU1 = dispField.GetComponentValues(FOComponentNames.U1).ToArray(); // copy
|
|
dispValuesU2 = dispField.GetComponentValues(FOComponentNames.U2).ToArray(); // copy
|
|
dispValuesU3 = dispField.GetComponentValues(FOComponentNames.U3).ToArray(); // copy
|
|
// Sliding distance
|
|
slidingDistanceData = GetFieldData(FOFieldNames.SlidingDistance, "",
|
|
slipStepIds[i], stepIncrementIds[j]);
|
|
slidingDistanceField = GetField(slidingDistanceData);
|
|
slidingDistanceValues = slidingDistanceField.GetComponentValues(FOComponentNames.All);
|
|
// Normal
|
|
normalData = GetFieldData(FOFieldNames.SurfaceNormal, "", slipStepIds[i], stepIncrementIds[j]);
|
|
normalField = GetField(normalData);
|
|
normalN1Values = normalField.GetComponentValues(FOComponentNames.N1).ToArray();
|
|
normalN2Values = normalField.GetComponentValues(FOComponentNames.N2).ToArray();
|
|
normalN3Values = normalField.GetComponentValues(FOComponentNames.N3).ToArray();
|
|
// Adjust normals based on zero BCs inside the wear step
|
|
if (nodeIdZeroDisplacements != null)
|
|
{
|
|
foreach (var entry in nodeIdZeroDisplacements)
|
|
{
|
|
id = _nodeIdsLookUp[entry.Key];
|
|
if (entry.Value[0]) normal.X = 0;
|
|
else normal.X = normalN1Values[id];
|
|
if (entry.Value[1]) normal.Y = 0;
|
|
else normal.Y = normalN2Values[id];
|
|
if (entry.Value[2]) normal.Z = 0;
|
|
else normal.Z = normalN3Values[id];
|
|
//
|
|
normal.Normalize();
|
|
//
|
|
normalN1Values[id] = (float)normal.X;
|
|
normalN2Values[id] = (float)normal.Y;
|
|
normalN3Values[id] = (float)normal.Z;
|
|
}
|
|
}
|
|
// Wear depth
|
|
depthValuesMag = new float[pressureValues.Length];
|
|
depthValuesH1 = new float[pressureValues.Length];
|
|
depthValuesH2 = new float[pressureValues.Length];
|
|
depthValuesH3 = new float[pressureValues.Length];
|
|
if (prevDepthValuesMag == null)
|
|
{
|
|
prevDepthValuesMag = new float[pressureValues.Length];
|
|
prevDepthValuesH1 = new float[pressureValues.Length];
|
|
prevDepthValuesH2 = new float[pressureValues.Length];
|
|
prevDepthValuesH3 = new float[pressureValues.Length];
|
|
}
|
|
//
|
|
for (int k = 0; k < depthValuesMag.Length; k++)
|
|
{
|
|
dh = coefficients[k] * pressureValues[k] * slidingDistanceValues[k];
|
|
depthValuesMag[k] = dh + prevDepthValuesMag[k];
|
|
depthValuesH1[k] = dh * normalN1Values[k] + prevDepthValuesH1[k];
|
|
depthValuesH2[k] = dh * normalN2Values[k] + prevDepthValuesH2[k];
|
|
depthValuesH3[k] = dh * normalN3Values[k] + prevDepthValuesH3[k];
|
|
// Disp with wear depth
|
|
dispValuesU1[k] += depthValuesH1[k];
|
|
dispValuesU2[k] += depthValuesH2[k];
|
|
dispValuesU3[k] += depthValuesH3[k];
|
|
dispValuesMag[k] = (float)Math.Sqrt(Math.Pow(dispValuesU1[k], 2) +
|
|
Math.Pow(dispValuesU2[k], 2) +
|
|
Math.Pow(dispValuesU3[k], 2));
|
|
}
|
|
//
|
|
prevDepthValuesMag = depthValuesMag.ToArray(); // must copy due to smoothing
|
|
prevDepthValuesH1 = depthValuesH1.ToArray();
|
|
prevDepthValuesH2 = depthValuesH2.ToArray();
|
|
prevDepthValuesH3 = depthValuesH3.ToArray();
|
|
// Smoothing
|
|
SmoothVectorField(ref depthValuesH1, ref depthValuesH2, ref depthValuesH3, ref depthValuesMag,
|
|
numOfSmoothingSteps);
|
|
// Wear depth
|
|
depthData = new FieldData(FOFieldNames.WearDepth);
|
|
depthData.StepId = slipStepIds[i];
|
|
depthData.StepIncrementId = stepIncrementIds[j];
|
|
depthData.Time = dispData.Time;
|
|
depthData.StepType = StepTypeEnum.Static;
|
|
depthField = new Field(depthData.Name);
|
|
depthField.AddComponent(FOComponentNames.All, depthValuesMag);
|
|
depthField.AddComponent(FOComponentNames.H1, depthValuesH1);
|
|
depthField.AddComponent(FOComponentNames.H2, depthValuesH2);
|
|
depthField.AddComponent(FOComponentNames.H3, depthValuesH3);
|
|
AddField(depthData, depthField);
|
|
// Mesh update
|
|
meshUpdateData = new FieldData(FOFieldNames.MeshDeformation);
|
|
meshUpdateData.StepId = slipStepIds[i];
|
|
meshUpdateData.StepIncrementId = stepIncrementIds[j];
|
|
meshUpdateData.Time = dispData.Time;
|
|
meshUpdateData.StepType = StepTypeEnum.Static;
|
|
meshUpdateField = new Field(meshUpdateData.Name);
|
|
meshUpdateField.AddComponent(FOComponentNames.All, new float[pressureValues.Length]);
|
|
meshUpdateField.AddComponent(FOComponentNames.U1, new float[pressureValues.Length]);
|
|
meshUpdateField.AddComponent(FOComponentNames.U2, new float[pressureValues.Length]);
|
|
meshUpdateField.AddComponent(FOComponentNames.U3, new float[pressureValues.Length]);
|
|
AddField(meshUpdateData, meshUpdateField);
|
|
// Disp with wear depth
|
|
dispData.Name = FOFieldNames.DispDeformationDepth;
|
|
dispField = new Field(dispData.Name);
|
|
dispField.AddComponent(FOComponentNames.All, dispValuesMag);
|
|
dispField.AddComponent(FOComponentNames.U1, dispValuesU1);
|
|
dispField.AddComponent(FOComponentNames.U2, dispValuesU2);
|
|
dispField.AddComponent(FOComponentNames.U3, dispValuesU3);
|
|
AddField(dispData, dispField);
|
|
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
private void SmoothVectorField(ref float[] component1, ref float[] component2, ref float[] component3,
|
|
ref float[] componentMag, int numOfSmoothingSteps)
|
|
{
|
|
if (component1.Length != component2.Length && component2.Length != component3.Length &&
|
|
component3.Length != componentMag.Length) throw new NotSupportedException();
|
|
//
|
|
if (numOfSmoothingSteps == 0) return;
|
|
//
|
|
double[] xyz = new double[3];
|
|
HashSet<int> nodeIds = new HashSet<int>();
|
|
Dictionary<int, double[]> globalVectors = new Dictionary<int, double[]>();
|
|
//
|
|
foreach (var entry in _nodeIdsLookUp)
|
|
{
|
|
xyz[0] = component1[entry.Value];
|
|
xyz[1] = component2[entry.Value];
|
|
xyz[2] = component3[entry.Value];
|
|
//
|
|
if (xyz[0] != 0 || xyz[1] != 0 || xyz[2] != 0)
|
|
{
|
|
globalVectors.Add(entry.Key, new double[] { xyz[0], xyz[1], xyz[2] });
|
|
nodeIds.Add(entry.Key);
|
|
}
|
|
}
|
|
// Smooth
|
|
bool contains;
|
|
int surfaceId;
|
|
int cellId;
|
|
int[] cell;
|
|
VisualizationData vis;
|
|
List<int> surfaceIds;
|
|
Dictionary<VisualizationData, List<int>> visualizationSurfaceIds = new Dictionary<VisualizationData, List<int>>();
|
|
// Find surfaces that have deformed entire element faces
|
|
foreach (var entry in _mesh.Parts)
|
|
{
|
|
vis = entry.Value.Visualization;
|
|
for (int i = 0; i < vis.CellIdsByFace.Length; i++)
|
|
{
|
|
surfaceId = i;
|
|
for (int j = 0; j < vis.CellIdsByFace[surfaceId].Length; j++)
|
|
{
|
|
cellId = vis.CellIdsByFace[surfaceId][j];
|
|
cell = vis.Cells[cellId];
|
|
//
|
|
contains = true;
|
|
for (int k = 0; k < cell.Length; k++)
|
|
{
|
|
if (!nodeIds.Contains(cell[k])) { contains = false; break; }
|
|
}
|
|
if (contains)
|
|
{
|
|
if (visualizationSurfaceIds.TryGetValue(vis, out surfaceIds)) surfaceIds.Add(surfaceId);
|
|
else visualizationSurfaceIds.Add(vis, new List<int> { surfaceId });
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//
|
|
int numOfNodes;
|
|
double[] vector;
|
|
HashSet<int> neighboursHash;
|
|
Dictionary<int, HashSet<int>> nodeIdNeighbours = new Dictionary<int, HashSet<int>>();
|
|
// Find node neighbours
|
|
foreach (var entry in visualizationSurfaceIds)
|
|
{
|
|
vis = entry.Key;
|
|
foreach (var visSurfaceId in entry.Value)
|
|
{
|
|
foreach (var visCellId in vis.CellIdsByFace[visSurfaceId])
|
|
{
|
|
cell = vis.Cells[visCellId];
|
|
numOfNodes = cell.Length;
|
|
// Find node neighbours by element
|
|
for (int i = 0; i < numOfNodes; i++)
|
|
{
|
|
if (nodeIdNeighbours.TryGetValue(cell[i], out neighboursHash))
|
|
neighboursHash.UnionWith(cell);
|
|
else
|
|
{
|
|
neighboursHash = new HashSet<int>(cell);
|
|
nodeIdNeighbours.Add(cell[i], neighboursHash);
|
|
}
|
|
neighboursHash.Remove(cell[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Smoothing loops
|
|
Dictionary<int, double[]> smoothedVectors;
|
|
for (int i = 0; i < numOfSmoothingSteps; i++)
|
|
{
|
|
smoothedVectors = new Dictionary<int, double[]>(); // must be here
|
|
//
|
|
foreach (var entry in nodeIdNeighbours)
|
|
{
|
|
xyz = new double[3];
|
|
foreach (var nodeId in entry.Value)
|
|
{
|
|
if (globalVectors.TryGetValue(nodeId, out vector))
|
|
{
|
|
xyz[0] += vector[0];
|
|
xyz[1] += vector[1];
|
|
xyz[2] += vector[2];
|
|
}
|
|
}
|
|
if (xyz[0] != 0 || xyz[1] != 0 || xyz[2] != 0)
|
|
{
|
|
xyz[0] /= entry.Value.Count;
|
|
xyz[1] /= entry.Value.Count;
|
|
xyz[2] /= entry.Value.Count;
|
|
//
|
|
smoothedVectors.Add(entry.Key, xyz);
|
|
}
|
|
}
|
|
//
|
|
globalVectors = smoothedVectors;
|
|
}
|
|
// Move midside nodes to to central positions
|
|
Dictionary<int, int[]> midNodeIdNeighbours = new Dictionary<int, int[]>();
|
|
foreach (var entry in _mesh.Elements)
|
|
{
|
|
if (entry.Value is LinearTetraElement ||
|
|
entry.Value is LinearWedgeElement ||
|
|
entry.Value is LinearHexaElement) { }
|
|
else if (entry.Value is ParabolicTetraElement pte)
|
|
{
|
|
if (!midNodeIdNeighbours.ContainsKey(pte.NodeIds[4]))
|
|
midNodeIdNeighbours.Add(pte.NodeIds[4], new int[] { pte.NodeIds[0], pte.NodeIds[1] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pte.NodeIds[5]))
|
|
midNodeIdNeighbours.Add(pte.NodeIds[5], new int[] { pte.NodeIds[1], pte.NodeIds[2] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pte.NodeIds[6]))
|
|
midNodeIdNeighbours.Add(pte.NodeIds[6], new int[] { pte.NodeIds[2], pte.NodeIds[0] });
|
|
//
|
|
if (!midNodeIdNeighbours.ContainsKey(pte.NodeIds[7]))
|
|
midNodeIdNeighbours.Add(pte.NodeIds[7], new int[] { pte.NodeIds[0], pte.NodeIds[3] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pte.NodeIds[8]))
|
|
midNodeIdNeighbours.Add(pte.NodeIds[8], new int[] { pte.NodeIds[1], pte.NodeIds[3] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pte.NodeIds[9]))
|
|
midNodeIdNeighbours.Add(pte.NodeIds[9], new int[] { pte.NodeIds[2], pte.NodeIds[3] });
|
|
}
|
|
else if (entry.Value is ParabolicWedgeElement pwe)
|
|
{
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[6]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[6], new int[] { pwe.NodeIds[0], pwe.NodeIds[1] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[7]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[7], new int[] { pwe.NodeIds[1], pwe.NodeIds[2] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[8]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[8], new int[] { pwe.NodeIds[2], pwe.NodeIds[0] });
|
|
//
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[9]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[9], new int[] { pwe.NodeIds[3], pwe.NodeIds[4] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[10]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[10], new int[] { pwe.NodeIds[4], pwe.NodeIds[5] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[11]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[11], new int[] { pwe.NodeIds[5], pwe.NodeIds[3] });
|
|
//
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[12]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[12], new int[] { pwe.NodeIds[0], pwe.NodeIds[3] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[13]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[13], new int[] { pwe.NodeIds[1], pwe.NodeIds[4] });
|
|
if (!midNodeIdNeighbours.ContainsKey(pwe.NodeIds[14]))
|
|
midNodeIdNeighbours.Add(pwe.NodeIds[14], new int[] { pwe.NodeIds[2], pwe.NodeIds[5] });
|
|
}
|
|
else if (entry.Value is ParabolicHexaElement phe)
|
|
{
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[8]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[8], new int[] { phe.NodeIds[0], phe.NodeIds[1] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[9]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[9], new int[] { phe.NodeIds[1], phe.NodeIds[2] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[10]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[10], new int[] { phe.NodeIds[2], phe.NodeIds[3] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[11]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[11], new int[] { phe.NodeIds[3], phe.NodeIds[0] });
|
|
//
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[12]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[12], new int[] { phe.NodeIds[4], phe.NodeIds[5] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[13]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[13], new int[] { phe.NodeIds[5], phe.NodeIds[6] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[14]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[14], new int[] { phe.NodeIds[6], phe.NodeIds[7] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[15]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[15], new int[] { phe.NodeIds[7], phe.NodeIds[4] });
|
|
//
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[16]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[16], new int[] { phe.NodeIds[0], phe.NodeIds[4] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[17]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[17], new int[] { phe.NodeIds[1], phe.NodeIds[5] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[18]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[18], new int[] { phe.NodeIds[2], phe.NodeIds[6] });
|
|
if (!midNodeIdNeighbours.ContainsKey(phe.NodeIds[19]))
|
|
midNodeIdNeighbours.Add(phe.NodeIds[19], new int[] { phe.NodeIds[3], phe.NodeIds[7] });
|
|
}
|
|
else throw new NotSupportedException();
|
|
}
|
|
//
|
|
double[] vector1;
|
|
double[] vector2;
|
|
double[] coor1;
|
|
double[] coor2;
|
|
double[] coorMid;
|
|
double[] coorAvg = new double[3];
|
|
int[] neighbours;
|
|
foreach (var entry in globalVectors)
|
|
{
|
|
if (midNodeIdNeighbours.TryGetValue(entry.Key, out neighbours))
|
|
{
|
|
if (!globalVectors.TryGetValue(neighbours[0], out vector1)) vector1 = new double[3];
|
|
if (!globalVectors.TryGetValue(neighbours[1], out vector2)) vector2 = new double[3];
|
|
//
|
|
coor1 = _mesh.Nodes[neighbours[0]].Coor.ToArray();
|
|
coor1[0] += vector1[0];
|
|
coor1[1] += vector1[1];
|
|
coor1[2] += vector1[2];
|
|
//
|
|
coor2 = _mesh.Nodes[neighbours[1]].Coor.ToArray();
|
|
coor2[0] += vector2[0];
|
|
coor2[1] += vector2[1];
|
|
coor2[2] += vector2[2];
|
|
//
|
|
coorAvg[0] = (coor1[0] + coor2[0]) / 2;
|
|
coorAvg[1] = (coor1[1] + coor2[1]) / 2;
|
|
coorAvg[2] = (coor1[2] + coor2[2]) / 2;
|
|
//
|
|
|
|
if (entry.Key == 1169)
|
|
coorAvg[2] = coorAvg[2];
|
|
|
|
coorMid = _mesh.Nodes[entry.Key].Coor.ToArray();
|
|
xyz = entry.Value;
|
|
xyz[0] = coorAvg[0] - coorMid[0];
|
|
xyz[1] = coorAvg[1] - coorMid[1];
|
|
xyz[2] = coorAvg[2] - coorMid[2];
|
|
}
|
|
}
|
|
// Copy data back to components
|
|
for (int i = 0; i < component1.Length; i++)
|
|
{
|
|
component1[i] = 0; component2[i] = 0; component3[i] = 0; componentMag[i] = 0;
|
|
}
|
|
int locNodeId;
|
|
foreach (var entry in globalVectors)
|
|
{
|
|
locNodeId = _nodeIdsLookUp[entry.Key];
|
|
component1[locNodeId] = (float)entry.Value[0];
|
|
component2[locNodeId] = (float)entry.Value[1];
|
|
component3[locNodeId] = (float)entry.Value[2];
|
|
componentMag[locNodeId] = (float)Math.Sqrt(entry.Value[0] * entry.Value[0] + entry.Value[1] * entry.Value[1] +
|
|
entry.Value[2] * entry.Value[2]);
|
|
}
|
|
}
|
|
private float[][] GetLocalVectors(string fieldName)
|
|
{
|
|
string prevFieldOutputName = _deformationFieldOutputName;
|
|
_deformationFieldOutputName = fieldName;
|
|
//
|
|
int[] stepIds = GetAllStepIds();
|
|
int stepId = stepIds.Last();
|
|
int[] stepIncrementIds = GetStepIncrementIds(stepId);
|
|
int stepIncrementId = stepIncrementIds.Last();
|
|
//
|
|
float[][] vectors = GetNodalMeshDeformations(stepId, stepIncrementId);
|
|
//
|
|
_deformationFieldOutputName = prevFieldOutputName;
|
|
//
|
|
return vectors;
|
|
}
|
|
public Dictionary<int, double[]> GetGlobalNonZeroVectors(string fieldName)
|
|
{
|
|
double[] xyz = new double[3];
|
|
float[][] vectors = GetLocalVectors(fieldName);
|
|
HashSet<int> nodeIds = new HashSet<int>();
|
|
Dictionary<int, double[]> globalVectors = new Dictionary<int, double[]>();
|
|
//
|
|
if (vectors != null)
|
|
{
|
|
foreach (var entry in _nodeIdsLookUp)
|
|
{
|
|
xyz[0] = vectors[0][entry.Value];
|
|
xyz[1] = vectors[1][entry.Value];
|
|
xyz[2] = vectors[2][entry.Value];
|
|
//
|
|
if (xyz[0] != 0 || xyz[1] != 0 || xyz[2] != 0)
|
|
{
|
|
globalVectors.Add(entry.Key, new double[] { xyz[0], xyz[1], xyz[2] });
|
|
nodeIds.Add(entry.Key);
|
|
}
|
|
}
|
|
}
|
|
//
|
|
return globalVectors;
|
|
}
|
|
//
|
|
private HistoryResultComponent ComputeRelativeDisplacement(string componentName, HistoryResultComponent tang1)
|
|
{
|
|
double[] time;
|
|
double[] values;
|
|
HistoryResultEntries itemData;
|
|
HistoryResultComponent component = new HistoryResultComponent(componentName);
|
|
//
|
|
foreach (var entry in tang1.Entries)
|
|
{
|
|
time = entry.Value.Time.ToArray();
|
|
values = entry.Value.Values.ToArray();
|
|
itemData = new HistoryResultEntries(entry.Key, false);
|
|
//
|
|
itemData.Add(time[0], 0); // must be here to keep the time in the component
|
|
for (int i = 1; i < values.Length; i++)
|
|
{
|
|
// Add only values != 0
|
|
if (values[i - 1] != 0 && values[i] != 0) itemData.Add(time[i], values[i] - values[i - 1]);
|
|
}
|
|
if (itemData.Time.Count > 0) component.Entries.Add(itemData.Name, itemData);
|
|
}
|
|
//
|
|
return component;
|
|
}
|
|
private HistoryResultComponent ComputeVectorMagnitude(string componentName, HistoryResultComponent[] components)
|
|
{
|
|
// Sorted time
|
|
double[] sortedTime;
|
|
Dictionary<double, int> timeRowId;
|
|
GetSortedTime(components, out sortedTime, out timeRowId);
|
|
// Get all entry names
|
|
HashSet<string> entryNamesHash = new HashSet<string>();
|
|
foreach (var component in components)
|
|
{
|
|
if (entryNamesHash.Count == 0) entryNamesHash.UnionWith(component.Entries.Keys);
|
|
else entryNamesHash.IntersectWith(component.Entries.Keys);
|
|
}
|
|
//
|
|
double value;
|
|
double[][] values = new double[components.Length][];
|
|
HistoryResultEntries historyEntry;
|
|
HistoryResultComponent magnitudeComponent = new HistoryResultComponent(componentName);
|
|
foreach (var entryName in entryNamesHash)
|
|
{
|
|
// Get all entry values from all components
|
|
for (int i = 0; i < components.Length; i++)
|
|
{
|
|
if (components[i].Entries.TryGetValue(entryName, out historyEntry))
|
|
values[i] = GetAllEntryValues(historyEntry, timeRowId);
|
|
else values[i] = new double[timeRowId.Count];
|
|
}
|
|
// Compute the magnitude
|
|
historyEntry = new HistoryResultEntries(entryName, false);
|
|
for (int i = 0; i < sortedTime.Length; i++)
|
|
{
|
|
value = 0;
|
|
for (int j = 0; j < components.Length; j++)
|
|
{
|
|
value += Math.Pow(values[j][i], 2);
|
|
}
|
|
historyEntry.Add(sortedTime[i], Math.Sqrt(value));
|
|
}
|
|
//
|
|
if (historyEntry.Time.Count > 0) magnitudeComponent.Entries.Add(historyEntry.Name, historyEntry);
|
|
}
|
|
//
|
|
return magnitudeComponent;
|
|
}
|
|
private HistoryResultComponent[] GetNormalsFromElementFaceHistory(HistoryResultComponent historyResultComponent)
|
|
{
|
|
HistoryResultComponent[] normalComponents = new HistoryResultComponent[4];
|
|
normalComponents[0] = new HistoryResultComponent(HOComponentNames.All);
|
|
normalComponents[1] = new HistoryResultComponent(HOComponentNames.N1);
|
|
normalComponents[2] = new HistoryResultComponent(HOComponentNames.N2);
|
|
normalComponents[3] = new HistoryResultComponent(HOComponentNames.N3);
|
|
// Sorted time
|
|
double[] sortedTime;
|
|
Dictionary<double, int> timeRowId;
|
|
GetSortedTime(new HistoryResultComponent[] { historyResultComponent }, out sortedTime, out timeRowId);
|
|
// Get all values data for each node
|
|
int faceId;
|
|
int elementId;
|
|
int count = 0;
|
|
string[] tmp;
|
|
double faceArea;
|
|
double[] faceNormal;
|
|
FeElement element;
|
|
FeFaceName faceName;
|
|
HistoryResultEntries normalAllEntry;
|
|
HistoryResultEntries normal1Entry;
|
|
HistoryResultEntries normal2Entry;
|
|
HistoryResultEntries normal3Entry;
|
|
//
|
|
foreach (var entry in historyResultComponent.Entries)
|
|
{
|
|
tmp = entry.Key.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
|
|
if (tmp.Length == 2 && int.TryParse(tmp[0], out elementId) && int.TryParse(tmp[1], out faceId))
|
|
{
|
|
switch (faceId)
|
|
{
|
|
case 1: faceName = FeFaceName.S1; break;
|
|
case 2: faceName = FeFaceName.S2; break;
|
|
case 3: faceName = FeFaceName.S3; break;
|
|
case 4: faceName = FeFaceName.S4; break;
|
|
case 5: faceName = FeFaceName.S5; break;
|
|
case 6: faceName = FeFaceName.S6; break;
|
|
default: throw new NotSupportedException();
|
|
}
|
|
//
|
|
if (_mesh.Elements.TryGetValue(elementId, out element))
|
|
{
|
|
_mesh.GetElementFaceNormalAndArea(elementId, faceName, out faceNormal, out faceArea);
|
|
}
|
|
else if (elementId == -1) // fix for when no history output exists - Find all occurrences!!!
|
|
{
|
|
faceName = FeFaceName.S1;
|
|
faceNormal = new double[] { 1, 0, 0 };
|
|
faceArea = 0;
|
|
}
|
|
else throw new NotSupportedException();
|
|
//
|
|
normalAllEntry = new HistoryResultEntries(entry.Key, false);
|
|
normal1Entry = new HistoryResultEntries(entry.Key, false);
|
|
normal2Entry = new HistoryResultEntries(entry.Key, false);
|
|
normal3Entry = new HistoryResultEntries(entry.Key, false);
|
|
//
|
|
foreach (var time in entry.Value.Time)
|
|
{
|
|
normalAllEntry.Add(time, 1);
|
|
normal1Entry.Add(time, faceNormal[0]);
|
|
normal2Entry.Add(time, faceNormal[1]);
|
|
normal3Entry.Add(time, faceNormal[2]);
|
|
}
|
|
//
|
|
normalComponents[0].Entries.Add(normalAllEntry.Name, normalAllEntry);
|
|
normalComponents[1].Entries.Add(normal1Entry.Name, normal1Entry);
|
|
normalComponents[2].Entries.Add(normal2Entry.Name, normal2Entry);
|
|
normalComponents[3].Entries.Add(normal3Entry.Name, normal3Entry);
|
|
|
|
}
|
|
count++;
|
|
}
|
|
//
|
|
return normalComponents;
|
|
}
|
|
private void CreateAveragedFieldFromElementFaceHistory(string fieldName,
|
|
HistoryResultComponent historyResultComponent,
|
|
bool areaAverage)
|
|
{
|
|
if (historyResultComponent != null)
|
|
{
|
|
// Sorted time
|
|
double[] sortedTime;
|
|
Dictionary<double, int> timeRowId;
|
|
GetSortedTime(new HistoryResultComponent[] { historyResultComponent }, out sortedTime, out timeRowId);
|
|
Dictionary<double, float[]> timeAvgValues =
|
|
GetNodalValuesFromElementFaceHistory(historyResultComponent, areaAverage);
|
|
//
|
|
bool newField;
|
|
float[] values;
|
|
Field field;
|
|
FieldData fieldData = new FieldData(fieldName, historyResultComponent.Name, 0, 0);
|
|
int count = 0;
|
|
int[] stepIds = GetAllStepIds();
|
|
int[] stepIncrementIds;
|
|
//
|
|
fieldData.StepType = StepTypeEnum.Static;
|
|
//
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
stepIncrementIds = GetStepIncrementIds(stepIds[i]);
|
|
//
|
|
for (int j = 0; j < stepIncrementIds.Length; j++)
|
|
{
|
|
if (i == 0 && j == 0) continue; // Zero increment - Find all occurrences!!!
|
|
// Field
|
|
values = timeAvgValues[sortedTime[count]];
|
|
fieldData.StepId = stepIds[i];
|
|
fieldData.StepIncrementId = stepIncrementIds[j];
|
|
fieldData.Time = (float)sortedTime[count];
|
|
//
|
|
newField = false;
|
|
field = GetField(fieldData);
|
|
if (field == null)
|
|
{
|
|
field = new Field(fieldData.Name);
|
|
newField = true;
|
|
}
|
|
field.AddComponent(new FieldComponent(fieldData.Component, values));
|
|
if (newField) AddField(fieldData, field);
|
|
//
|
|
count++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
private double[] GetAllEntryValues(HistoryResultEntries historyEntry, Dictionary<double, int> timeRowId)
|
|
{
|
|
int id;
|
|
double[] values;
|
|
double[] timePoints;
|
|
double[] allValues = new double[timeRowId.Count];
|
|
//
|
|
timePoints = historyEntry.Time.ToArray();
|
|
values = historyEntry.Values.ToArray();
|
|
for (int i = 0; i < timePoints.Length; i++)
|
|
{
|
|
id = timeRowId[timePoints[i]];
|
|
allValues[id] = values[i];
|
|
}
|
|
return allValues;
|
|
}
|
|
private Dictionary<double, float[]> GetNodalValuesFromElementFaceHistory(HistoryResultComponent historyResultComponent,
|
|
bool areaAverage)
|
|
{
|
|
// Sorted time
|
|
double[] sortedTime;
|
|
Dictionary<double, int> timeRowId;
|
|
GetSortedTime(new HistoryResultComponent[] { historyResultComponent }, out sortedTime, out timeRowId);
|
|
// Average data structure
|
|
AvgData avgData = new AvgData();
|
|
foreach (var entry in _mesh.Parts)
|
|
{
|
|
avgData.AddRange(entry.Value.Visualization.GetAvgData().Nodes);
|
|
}
|
|
// Get all values data for each node
|
|
int faceId;
|
|
int elementId;
|
|
int count = 0;
|
|
string[] tmp;
|
|
double faceArea;
|
|
double[] faceNormal;
|
|
double[][] historyValues = new double[historyResultComponent.Entries.Count][];
|
|
FeElement element;
|
|
FeFaceName faceName;
|
|
AvgEntryData avgEntryData;
|
|
Dictionary<int, AvgEntryData> valueIdAvgEntryData = new Dictionary<int, AvgEntryData>();
|
|
//
|
|
foreach (var entry in historyResultComponent.Entries)
|
|
{
|
|
tmp = entry.Key.Split(new string[] { "_" }, StringSplitOptions.RemoveEmptyEntries);
|
|
if (tmp.Length == 2 && int.TryParse(tmp[0], out elementId) && int.TryParse(tmp[1], out faceId))
|
|
{
|
|
switch (faceId)
|
|
{
|
|
case 1: faceName = FeFaceName.S1; break;
|
|
case 2: faceName = FeFaceName.S2; break;
|
|
case 3: faceName = FeFaceName.S3; break;
|
|
case 4: faceName = FeFaceName.S4; break;
|
|
case 5: faceName = FeFaceName.S5; break;
|
|
case 6: faceName = FeFaceName.S6; break;
|
|
default: throw new NotSupportedException();
|
|
}
|
|
//
|
|
if (_mesh.Elements.TryGetValue(elementId, out element))
|
|
{
|
|
_mesh.GetElementFaceNormalAndArea(elementId, faceName, out faceNormal, out faceArea);
|
|
//
|
|
avgEntryData = new AvgEntryData();
|
|
avgEntryData.NodeIds = element.GetNodeIdsFromFaceName(faceName);
|
|
avgEntryData.SurfaceId = 0;
|
|
avgEntryData.ElementId = elementId;
|
|
avgEntryData.Area = faceArea;
|
|
//
|
|
valueIdAvgEntryData.Add(count, avgEntryData);
|
|
historyValues[count] = GetAllEntryValues(entry.Value, timeRowId);
|
|
}
|
|
else if (elementId == -1) // fix for when no history output exists - Find all occurrences!!!
|
|
{
|
|
avgEntryData = new AvgEntryData();
|
|
avgEntryData.NodeIds = new int[0];
|
|
avgEntryData.SurfaceId = 0;
|
|
avgEntryData.ElementId = elementId;
|
|
avgEntryData.Area = 0;
|
|
//
|
|
valueIdAvgEntryData.Add(count, avgEntryData);
|
|
historyValues[count] = GetAllEntryValues(entry.Value, timeRowId);
|
|
}
|
|
else throw new NotSupportedException();
|
|
}
|
|
count++;
|
|
}
|
|
// Average
|
|
float[] averagedValues;
|
|
AvgData avgDataClone;
|
|
Dictionary<int, double> averagedNodalValues;
|
|
Dictionary<double, float[]> timeValues = new Dictionary<double, float[]>();
|
|
for (int i = 0; i < sortedTime.Length; i++)
|
|
{
|
|
avgDataClone = new AvgData(avgData);
|
|
//
|
|
for (int j = 0; j < historyValues.Length; j++)
|
|
{
|
|
avgEntryData = valueIdAvgEntryData[j];
|
|
for (int k = 0; k < avgEntryData.NodeIds.Length; k++)
|
|
{
|
|
avgDataClone.Nodes[avgEntryData.NodeIds[k]].Elements[avgEntryData.ElementId].Data.Add(
|
|
new Tuple<double, double>(historyValues[j][i], avgEntryData.Area));
|
|
}
|
|
}
|
|
//
|
|
averagedValues = new float[_nodeIdsLookUp.Count];
|
|
averagedNodalValues = avgDataClone.GetAveragedValues(areaAverage);
|
|
foreach (var entry in averagedNodalValues)
|
|
{
|
|
averagedValues[_nodeIdsLookUp[entry.Key]] = (float)entry.Value;
|
|
}
|
|
timeValues.Add(sortedTime[i], averagedValues);
|
|
}
|
|
//
|
|
return timeValues;
|
|
}
|
|
// Select slip wear results
|
|
public void KeepOnlySelectedSlipWearResults(OrderedDictionary<int, double> stepIdDuration, int[] slipStepIds,
|
|
SlipWearResultsEnum slipWearResultsToKeep)
|
|
{
|
|
Dictionary<int, float> stepIdMaxTime = GetMaxStepTime();
|
|
//
|
|
KeepOnlySelectedFieldSlipWearResults(slipStepIds, slipWearResultsToKeep);
|
|
KeepOnlySelectedHistorySlipWearResults(stepIdDuration, slipStepIds, slipWearResultsToKeep);
|
|
}
|
|
private void KeepOnlySelectedFieldSlipWearResults(int[] slipStepIds, SlipWearResultsEnum slipWearResultsToKeep)
|
|
{
|
|
HashSet<int> slipStepIdsHash = new HashSet<int>(slipStepIds);
|
|
//
|
|
if (slipWearResultsToKeep == SlipWearResultsEnum.All) { }
|
|
else if (slipWearResultsToKeep == SlipWearResultsEnum.SlipWearSteps)
|
|
{
|
|
OrderedDictionary<FieldData, Field> fields = new OrderedDictionary<FieldData, Field>("Fields");
|
|
//
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (slipStepIdsHash.Contains(entry.Key.StepId))
|
|
{
|
|
fields.Add(entry.Key, entry.Value);
|
|
}
|
|
}
|
|
_fields = fields;
|
|
}
|
|
else if (slipWearResultsToKeep == SlipWearResultsEnum.LastIncrementOfSlipWearSteps)
|
|
{
|
|
int lastIncrementId;
|
|
OrderedDictionary<FieldData, Field> fields = new OrderedDictionary<FieldData, Field>("Fields");
|
|
//
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (slipStepIdsHash.Contains(entry.Key.StepId))
|
|
{
|
|
lastIncrementId = GetStepIncrementIds(entry.Key.StepId).Last();
|
|
//
|
|
if (entry.Key.StepIncrementId == lastIncrementId)
|
|
fields.Add(entry.Key, entry.Value);
|
|
}
|
|
}
|
|
_fields = fields;
|
|
}
|
|
else if (slipWearResultsToKeep == SlipWearResultsEnum.LastIncrementOfLastSlipWearStep)
|
|
{
|
|
int lastIncrementId;
|
|
int lastStepId = slipStepIds.Last();
|
|
OrderedDictionary<FieldData, Field> fields = new OrderedDictionary<FieldData, Field>("Fields");
|
|
//
|
|
foreach (var entry in _fields)
|
|
{
|
|
if (slipStepIdsHash.Contains(entry.Key.StepId))
|
|
{
|
|
if (entry.Key.StepId == lastStepId)
|
|
{
|
|
lastIncrementId = GetStepIncrementIds(entry.Key.StepId).Last();
|
|
//
|
|
if (entry.Key.StepIncrementId == lastIncrementId)
|
|
fields.Add(entry.Key, entry.Value);
|
|
}
|
|
}
|
|
}
|
|
_fields = fields;
|
|
}
|
|
else throw new NotSupportedException();
|
|
}
|
|
private void KeepOnlySelectedHistorySlipWearResults(OrderedDictionary<int, double> stepIdDuration, int[] slipStepIds,
|
|
SlipWearResultsEnum slipWearResultsToKeep)
|
|
{
|
|
HashSet<int> slipStepIdsHash = new HashSet<int>(slipStepIds);
|
|
//
|
|
double sumTime = 0;
|
|
OrderedDictionary<int, double> stepIdStartTime = new OrderedDictionary<int, double>("Step id - step time");
|
|
foreach (var entry in stepIdDuration)
|
|
{
|
|
stepIdStartTime.Add(entry.Key, sumTime);
|
|
sumTime += entry.Value;
|
|
}
|
|
//
|
|
int stepId;
|
|
double startTime;
|
|
double endTime;
|
|
List<double[]> minMaxTimeList = new List<double[]>();
|
|
//
|
|
if (slipWearResultsToKeep == SlipWearResultsEnum.All)
|
|
{
|
|
minMaxTimeList.Add(new double[] { 0, sumTime });
|
|
}
|
|
else if (slipWearResultsToKeep == SlipWearResultsEnum.SlipWearSteps)
|
|
{
|
|
foreach (var entry in stepIdDuration)
|
|
{
|
|
stepId = entry.Key;
|
|
//
|
|
if (slipStepIdsHash.Contains(stepId))
|
|
{
|
|
startTime = stepIdStartTime[stepId];
|
|
endTime = startTime + entry.Value;
|
|
minMaxTimeList.Add(new double[] { startTime, endTime });
|
|
}
|
|
}
|
|
}
|
|
else if (slipWearResultsToKeep == SlipWearResultsEnum.LastIncrementOfSlipWearSteps)
|
|
{
|
|
foreach (var entry in stepIdDuration)
|
|
{
|
|
stepId = entry.Key;
|
|
//
|
|
if (slipStepIdsHash.Contains(stepId))
|
|
{
|
|
startTime = stepIdStartTime[stepId];
|
|
endTime = startTime + entry.Value;
|
|
minMaxTimeList.Add(new double[] { endTime, endTime });
|
|
}
|
|
}
|
|
}
|
|
else if (slipWearResultsToKeep == SlipWearResultsEnum.LastIncrementOfLastSlipWearStep)
|
|
{
|
|
stepId = slipStepIds.Last();
|
|
//
|
|
if (slipStepIdsHash.Contains(stepId))
|
|
{
|
|
startTime = stepIdStartTime[stepId];
|
|
endTime = startTime + stepIdDuration[stepId];
|
|
minMaxTimeList.Add(new double[] { endTime, endTime });
|
|
}
|
|
}
|
|
else throw new NotSupportedException();
|
|
//
|
|
double[][] minMaxTime = minMaxTimeList.ToArray();
|
|
//
|
|
List<string> entryNamesToRemove = new List<string>();
|
|
foreach (var setEntry in _history.Sets)
|
|
{
|
|
foreach (var fieldEntry in setEntry.Value.Fields)
|
|
{
|
|
foreach (var componentEntry in fieldEntry.Value.Components)
|
|
{
|
|
entryNamesToRemove.Clear();
|
|
//
|
|
foreach (var entry in componentEntry.Value.Entries)
|
|
{
|
|
entry.Value.KeepOnly(minMaxTime);
|
|
if (entry.Value.Time.Count == 0) entryNamesToRemove.Add(entry.Key);
|
|
}
|
|
// Remove empty
|
|
foreach (var entryName in entryNamesToRemove) componentEntry.Value.Entries.Remove(entryName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Superposition
|
|
public void TestSuperposition()
|
|
{
|
|
FeNodeSet nodeSet;
|
|
int[] nodeIds = null;
|
|
if (_mesh.NodeSets.TryGetValue("Node_Set-1", out nodeSet))
|
|
{
|
|
nodeIds = new int[nodeSet.Labels.Length];
|
|
for (int i = 0; i < nodeSet.Labels.Length; i++) nodeIds[i] = _nodeIdsLookUp[nodeSet.Labels[i]];
|
|
Array.Sort(nodeIds);
|
|
}
|
|
//
|
|
string[] componentNames = new string[] { FOComponentNames.S11,
|
|
FOComponentNames.S22,
|
|
FOComponentNames.S33,
|
|
FOComponentNames.S12,
|
|
FOComponentNames.S23,
|
|
FOComponentNames.S13 };
|
|
//
|
|
FieldData fieldData;
|
|
Field field;
|
|
int[] stepIds = GetAllStepIds();
|
|
float[] componentValues;
|
|
float[] filteredValues;
|
|
float[][][] scv = new float[stepIds.Length][][];
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
fieldData = new FieldData(FOFieldNames.Stress, "", stepIds[i], 1);
|
|
field = GetField(fieldData);
|
|
scv[i] = new float[componentNames.Length][];
|
|
//
|
|
for (int j = 0; j < componentNames.Length; j++)
|
|
{
|
|
componentValues = field.GetComponentValues(componentNames[j]);
|
|
// Filter to node set
|
|
if (nodeIds != null)
|
|
{
|
|
filteredValues = new float[nodeIds.Length];
|
|
for (int k = 0; k < nodeIds.Length; k++)
|
|
{
|
|
filteredValues[k] = componentValues[nodeIds[k]];
|
|
}
|
|
componentValues = filteredValues;
|
|
}
|
|
//
|
|
scv[i][j] = componentValues;
|
|
}
|
|
}
|
|
//
|
|
float[][] weights = GetWeightsLC2(stepIds.Length);
|
|
// Generate all possible combinations using efficient list manipulation
|
|
List<List<float>> combinations = new List<List<float>>();
|
|
combinations.Add(new List<float>());
|
|
foreach (float[] list in weights)
|
|
{
|
|
List<List<float>> tempCombinations = new List<List<float>>();
|
|
|
|
foreach (List<float> combination in combinations)
|
|
{
|
|
foreach (float value in list)
|
|
{
|
|
List<float> newCombination = new List<float>(combination);
|
|
newCombination.Add(value);
|
|
tempCombinations.Add(newCombination);
|
|
}
|
|
}
|
|
combinations = tempCombinations;
|
|
}
|
|
//
|
|
int count = 0;
|
|
List<float> maxCombination;
|
|
//
|
|
Field resultField;
|
|
object myLock = new object();
|
|
//
|
|
List<float>[] combinationsArray = combinations.ToArray();
|
|
float[] maxMisses = new float[combinationsArray.Length];
|
|
int[] indices = new int[combinationsArray.Length];
|
|
Parallel.For(0, combinationsArray.Length, new ParallelOptions { MaxDegreeOfParallelism = 16 }, combNum =>
|
|
//foreach (var combination in combinations)
|
|
{
|
|
float mises = 0;
|
|
float maxMises = 0;
|
|
float wi;
|
|
float[] w;
|
|
float[] valuesJ;
|
|
float[] scvIJ;
|
|
float[][] values;
|
|
//
|
|
w = combinationsArray[combNum].ToArray();
|
|
values = new float[componentNames.Length][];
|
|
//
|
|
for (int i = 0; i < componentNames.Length; i++) values[i] = new float[scv[0][i].Length];
|
|
//
|
|
for (int i = 0; i < stepIds.Length; i++)
|
|
{
|
|
wi = w[i];
|
|
for (int j = 0; j < componentNames.Length; j++)
|
|
{
|
|
valuesJ = values[j];
|
|
scvIJ = scv[i][j];
|
|
for (int k = 0; k < scvIJ.Length; k++)
|
|
{
|
|
valuesJ[k] += wi * scvIJ[k];
|
|
}
|
|
}
|
|
}
|
|
//
|
|
float a, b, c;
|
|
for (int i = 0; i < values[0].Length; i++)
|
|
{
|
|
a = values[0][i] - values[1][i];
|
|
b = values[1][i] - values[2][i];
|
|
c = values[2][i] - values[0][i];
|
|
mises = (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])));
|
|
//
|
|
{
|
|
if (mises > maxMises)
|
|
{
|
|
maxMises = mises;
|
|
}
|
|
}
|
|
}
|
|
indices[combNum] = combNum;
|
|
maxMisses[combNum] = maxMises;
|
|
//
|
|
count++;
|
|
if (count % 1000 == 0) { System.Diagnostics.Debug.WriteLine(count); }
|
|
}
|
|
);
|
|
//
|
|
Array.Sort(maxMisses, indices);
|
|
//
|
|
int index;
|
|
string line;
|
|
List<string> lines = new List<string>();
|
|
for (int i = 0; i < indices.Length; i++)
|
|
{
|
|
index = indices[i];
|
|
line = maxMisses[i].ToString() + ";";
|
|
foreach (var value in combinationsArray[index]) line += value.ToString() + ";";
|
|
lines.Add(line);
|
|
}
|
|
//
|
|
File.WriteAllLines(@"C:\Temp\combinations.csv", lines.ToArray());
|
|
//
|
|
maxCombination = combinationsArray[indices.Last()];
|
|
float maxMisesAll = maxMisses.Last();
|
|
maxMisesAll = maxMisses.Last();
|
|
}
|
|
private float[][] GetWeightsLC1(int numSteps)
|
|
{
|
|
float[][] weights = new float[numSteps][];
|
|
//
|
|
weights[0] = new float[] { 1.1f }; // pressure
|
|
weights[1] = new float[] { 37000000 }; // MAy
|
|
weights[2] = new float[] { 10000, -10000 }; // FAx
|
|
weights[3] = new float[] { 20000, -20000 }; // FAy
|
|
weights[4] = new float[] { 43000, -43000 }; // FAz
|
|
weights[5] = new float[] { 3000000, -3000000 }; // MAx
|
|
weights[6] = new float[] { 21000000, -21000000 }; // MAz
|
|
weights[7] = new float[] { 10000, -10000 }; // FCx
|
|
weights[8] = new float[] { 5000, -5000 }; // FCy
|
|
weights[9] = new float[] { 9000, -9000 }; // FCz
|
|
weights[10] = new float[] { 3000000, -3000000 }; // MCx
|
|
weights[11] = new float[] { 3100000, -3100000 }; // MCy
|
|
weights[12] = new float[] { 1000000, -1000000 }; // MCz
|
|
weights[13] = new float[] { 2000, -2000 }; // FDx
|
|
weights[14] = new float[] { 1400, -1400 }; // FDy
|
|
weights[15] = new float[] { 1400, -1400 }; // FDz
|
|
weights[16] = new float[] { 700000, -700000 }; // MDx
|
|
weights[17] = new float[] { 700000, -700000 }; // MDy
|
|
weights[18] = new float[] { 500000, -500000 }; // MDz
|
|
//
|
|
return weights;
|
|
}
|
|
private float[][] GetWeightsLC2(int numSteps)
|
|
{
|
|
float[][] weights = new float[numSteps][];
|
|
//
|
|
weights[0] = new float[] { 1.1f }; // pressure
|
|
weights[1] = new float[] { 10000, -10000 }; // FCx
|
|
weights[2] = new float[] { 5000, -5000 }; // FCy
|
|
weights[3] = new float[] { 9000, -9000 }; // FCz
|
|
weights[4] = new float[] { 2000, -2000 }; // FDx
|
|
weights[5] = new float[] { 1400, -1400 }; // FDy
|
|
weights[6] = new float[] { 1400, -1400 }; // FDz
|
|
weights[7] = new float[] { 103000 }; // FEz
|
|
weights[8] = new float[] { 3000000, -3000000 }; // MCx
|
|
weights[9] = new float[] { 3100000, -3100000 }; // MCy
|
|
weights[10] = new float[] { 1000000, -1000000 }; // MCz
|
|
weights[11] = new float[] { 700000, -700000 }; // MDx
|
|
weights[12] = new float[] { 700000, -700000 }; // MDy
|
|
weights[13] = new float[] { 500000, -500000 }; // MDz
|
|
//
|
|
return weights;
|
|
}
|
|
//
|
|
public void TestLineProbe(int stepId, int incrementId)
|
|
{
|
|
FieldData fieldData;
|
|
fieldData = new FieldData(FOFieldNames.Stress, FOComponentNames.S11, stepId, incrementId);
|
|
FeElementSet allElements = new FeElementSet("all", _mesh.Elements.Keys.ToArray());
|
|
PartExchangeData s11 = GetSetNodesCellsAndValues(allElements, fieldData);
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|