2183 lines
113 KiB
C#
2183 lines
113 KiB
C#
|
|
using CaeGlobals;
|
|||
|
|
using CaeMesh;
|
|||
|
|
using CaeModel;
|
|||
|
|
using FileInOut.Output.Calculix;
|
|||
|
|
using System;
|
|||
|
|
using System.Collections.Generic;
|
|||
|
|
using System.IO;
|
|||
|
|
using System.Linq;
|
|||
|
|
using System.Text;
|
|||
|
|
#pragma warning disable IDE0130
|
|||
|
|
|
|||
|
|
namespace FileInOut.Output
|
|||
|
|
{
|
|||
|
|
[Serializable]
|
|||
|
|
public static class CalculixFileWriter
|
|||
|
|
{
|
|||
|
|
// Methods
|
|||
|
|
public static void Write(string fileName, FeModel model, ConvertPyramidsToEnum convertPyramidsTo,
|
|||
|
|
Dictionary<int, double[]> deformations = null)
|
|||
|
|
{
|
|||
|
|
List<CalculixKeyword> keywords = GetAllKeywords(model, convertPyramidsTo, deformations);
|
|||
|
|
// Write file
|
|||
|
|
StringBuilder sb = new StringBuilder();
|
|||
|
|
foreach (var keyword in keywords)
|
|||
|
|
{
|
|||
|
|
WriteKeywordRecursively(sb, keyword);
|
|||
|
|
}
|
|||
|
|
// Write to file in multiple steps
|
|||
|
|
int step = 10_000_000;
|
|||
|
|
int upper;
|
|||
|
|
using (StreamWriter sw = new StreamWriter(fileName, false))
|
|||
|
|
{
|
|||
|
|
for (int i = 0; i < sb.Length; i+=step)
|
|||
|
|
{
|
|||
|
|
upper = Math.Min(sb.Length - i, step);
|
|||
|
|
sw.Write(sb.ToString(i, upper));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void Clean(FeModel model)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.Sections)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is MassSection ms)
|
|||
|
|
{
|
|||
|
|
if (ms is PointMassSection pms)
|
|||
|
|
{
|
|||
|
|
pms.ElementSetName = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
public static void WriteMaterials(string fileName, FeModel model, string[] materialNames)
|
|||
|
|
{
|
|||
|
|
List<CalculixKeyword> keywords = new List<CalculixKeyword>();
|
|||
|
|
|
|||
|
|
// 1. Heading
|
|||
|
|
CalTitle title = new CalTitle("Heading", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendHeading(model, title);
|
|||
|
|
|
|||
|
|
// 2. Materials
|
|||
|
|
title = new CalTitle("Materials", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendMaterials(model, title, null, materialNames, true);
|
|||
|
|
|
|||
|
|
// 3. Write file
|
|||
|
|
StringBuilder sb = new StringBuilder();
|
|||
|
|
foreach (var keyword in keywords)
|
|||
|
|
{
|
|||
|
|
WriteKeywordRecursively(sb, keyword);
|
|||
|
|
}
|
|||
|
|
File.WriteAllText(fileName, sb.ToString());
|
|||
|
|
}
|
|||
|
|
// 添加2025-8-27
|
|||
|
|
public static List<CalculixKeyword> GetAllKeywords(FeModel model, ConvertPyramidsToEnum convertPyramidsTo,
|
|||
|
|
Dictionary<int, double[]> deformations = null)
|
|||
|
|
{
|
|||
|
|
List<CalculixKeyword> keywords = GetModelKeywords(model, convertPyramidsTo, deformations);
|
|||
|
|
|
|||
|
|
// Add user keywords
|
|||
|
|
if (model.CalculixUserKeywords != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.CalculixUserKeywords)
|
|||
|
|
{
|
|||
|
|
// Deep clone to prevent the changes in user keywords
|
|||
|
|
AddUserKeywordByIndices(keywords, entry.Key, entry.Value.DeepClone());
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return keywords;
|
|||
|
|
}
|
|||
|
|
public static List<CalculixKeyword> GetModelKeywords(FeModel model, ConvertPyramidsToEnum convertPyramidsTo,
|
|||
|
|
Dictionary<int, double[]> deformations = null,
|
|||
|
|
bool addAllMaterials = false)
|
|||
|
|
{
|
|||
|
|
// Clone surfaces
|
|||
|
|
OrderedDictionary<string, FeSurface> originalSurfaces = model.Mesh.Surfaces;
|
|||
|
|
OrderedDictionary<string, FeElementSet> originalElementSets = model.Mesh.ElementSets;
|
|||
|
|
//
|
|||
|
|
model.Mesh.Surfaces = originalSurfaces.DeepClone();
|
|||
|
|
model.Mesh.ElementSets = originalElementSets.DeepClone();
|
|||
|
|
Dictionary<int, FeElement> replacedElements = new Dictionary<int, FeElement>();
|
|||
|
|
//
|
|||
|
|
try
|
|||
|
|
{
|
|||
|
|
// Only keywords from the model, not user keywords
|
|||
|
|
// Always add a title keyword to get all possible keyword types to the keyword editor
|
|||
|
|
int maxNodeId = model.Mesh.MaxNodeId;
|
|||
|
|
int maxElementId = model.Mesh.MaxElementId;
|
|||
|
|
List<FeNode> additionalNodes = new List<FeNode>();
|
|||
|
|
List<FeNodeSet> additionalNodeSets = new List<FeNodeSet>();
|
|||
|
|
List<CalElement> additionalElementKeywords = new List<CalElement>();
|
|||
|
|
HashSet<string> additionalElementSetNames = new HashSet<string>();
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds;
|
|||
|
|
Dictionary<string, string[]> referencePointsNodeSetNames;
|
|||
|
|
Dictionary<CoordinateSystem, HashSet<string>> coordinateSystemNodeSets =
|
|||
|
|
new Dictionary<CoordinateSystem, HashSet<string>>();
|
|||
|
|
List<SectionData> additionalSectionData = new List<SectionData>();
|
|||
|
|
List<Material> additionalMaterials = new List<Material>();
|
|||
|
|
List<BoundaryCondition> additionalBoundaryConditions = new List<BoundaryCondition>();
|
|||
|
|
OrderedDictionary<string, List<PreTensionLoad>> preTensionLoads;
|
|||
|
|
List<double[]> equationParameters = new List<double[]>();
|
|||
|
|
//
|
|||
|
|
// Collect pre-tension loads to use them in reference point preparation
|
|||
|
|
GetPretensionLoads(model, out preTensionLoads);
|
|||
|
|
// Prepare reference points
|
|||
|
|
GetReferencePoints(model, preTensionLoads, ref maxNodeId, ref additionalNodeSets,
|
|||
|
|
out referencePointsNodeSetNames, out referencePointsNodeIds);
|
|||
|
|
// Prepare coordinate system-node set pairs
|
|||
|
|
GetCoordinateSystemNodeSet(model, referencePointsNodeSetNames, ref coordinateSystemNodeSets);
|
|||
|
|
// Fix pyramid surfaces
|
|||
|
|
FixPyramidSurfaces(model, convertPyramidsTo, ref replacedElements, ref additionalElementSetNames);
|
|||
|
|
// Prepare mass sections
|
|||
|
|
GetMassSections(model, referencePointsNodeIds, ref maxElementId, ref additionalElementKeywords,
|
|||
|
|
ref additionalElementSetNames, ref additionalSectionData);
|
|||
|
|
// Prepare point springs
|
|||
|
|
GetPointSprings(model, referencePointsNodeIds, ref maxElementId, ref additionalElementKeywords,
|
|||
|
|
ref additionalElementSetNames, ref additionalSectionData);
|
|||
|
|
// Collect compression only constraints
|
|||
|
|
GetCompressionOnlyConstraintData(model, ref maxNodeId, ref maxElementId, ref additionalNodes,
|
|||
|
|
ref additionalNodeSets, ref additionalElementKeywords,
|
|||
|
|
ref additionalElementSetNames, ref additionalSectionData,
|
|||
|
|
ref additionalMaterials, ref additionalBoundaryConditions,
|
|||
|
|
ref equationParameters);
|
|||
|
|
// 修改于: 2025-8-27 by Luke
|
|||
|
|
CalTitle title;
|
|||
|
|
List<CalculixKeyword> keywords = new List<CalculixKeyword>();
|
|||
|
|
|
|||
|
|
// 1. Heading
|
|||
|
|
title = new CalTitle("Heading", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendHeading(model, title);
|
|||
|
|
|
|||
|
|
// 2. Submodel
|
|||
|
|
string[] nodeSetNames = GetAllSubmodelNodeSetNames(model);
|
|||
|
|
if (nodeSetNames.Length > 0)
|
|||
|
|
{
|
|||
|
|
title = new CalTitle("Submodel", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendSubmodel(model, nodeSetNames, title);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3. Nodes
|
|||
|
|
title = new CalTitle("Nodes", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendNodes(model, additionalNodes, referencePointsNodeIds, deformations, title);
|
|||
|
|
|
|||
|
|
// 4. Elements
|
|||
|
|
title = new CalTitle("Elements", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendElements(model, additionalElementKeywords, title, convertPyramidsTo);
|
|||
|
|
|
|||
|
|
// 5. Node sets
|
|||
|
|
title = new CalTitle("Node sets", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendNodeSets(model, additionalNodeSets, title);
|
|||
|
|
|
|||
|
|
// 6. Element sets
|
|||
|
|
title = new CalTitle("Element sets", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendElementSets(model, additionalElementSetNames, title);
|
|||
|
|
|
|||
|
|
// 7. Surfaces
|
|||
|
|
title = new CalTitle("Surfaces", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendSurfaces(model, title);
|
|||
|
|
|
|||
|
|
// 8. Physical constants
|
|||
|
|
title = new CalTitle("Physical constants", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendPhysicalConstants(model, title);
|
|||
|
|
|
|||
|
|
// 9. Coordinate systems
|
|||
|
|
title = new CalTitle("Coordinate systems", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendCoordinateSystems(coordinateSystemNodeSets, title);
|
|||
|
|
|
|||
|
|
// 10. Materials
|
|||
|
|
title = new CalTitle("Materials", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendMaterials(model, title, additionalMaterials, null, addAllMaterials);
|
|||
|
|
|
|||
|
|
// 11. Sections
|
|||
|
|
title = new CalTitle("Sections", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendSections(model, additionalSectionData, title);
|
|||
|
|
|
|||
|
|
// 12. Pre-tension sections
|
|||
|
|
title = new CalTitle("Pre-tension sections", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendPreTensionSections(preTensionLoads, referencePointsNodeIds, title);
|
|||
|
|
|
|||
|
|
// 13. Constraints
|
|||
|
|
title = new CalTitle("Constraints", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendConstraints(model, referencePointsNodeIds, equationParameters, title);
|
|||
|
|
|
|||
|
|
// 14. Surface interactions
|
|||
|
|
title = new CalTitle("Surface interactions", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendSurfaceInteractions(model, title);
|
|||
|
|
|
|||
|
|
// 15. Contact pairs
|
|||
|
|
title = new CalTitle("Contact pairs", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendContactPairs(model, title);
|
|||
|
|
|
|||
|
|
// 16. Amplitudes
|
|||
|
|
title = new CalTitle("Amplitudes", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendAmplitudes(model, title);
|
|||
|
|
|
|||
|
|
// 17. Initial conditions
|
|||
|
|
title = new CalTitle("Initial conditions", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendInitialConditions(model, referencePointsNodeIds, title);
|
|||
|
|
|
|||
|
|
// 18. Steps
|
|||
|
|
title = new CalTitle("Steps", "");
|
|||
|
|
keywords.Add(title);
|
|||
|
|
AppendSteps(model, additionalBoundaryConditions, referencePointsNodeIds, title);
|
|||
|
|
//
|
|||
|
|
return keywords;
|
|||
|
|
}
|
|||
|
|
catch (Exception ex)
|
|||
|
|
{
|
|||
|
|
throw ex;
|
|||
|
|
}
|
|||
|
|
finally
|
|||
|
|
{
|
|||
|
|
model.Mesh.ElementSets = originalElementSets;
|
|||
|
|
model.Mesh.Surfaces = originalSurfaces;
|
|||
|
|
//
|
|||
|
|
foreach (var entry in replacedElements)
|
|||
|
|
{
|
|||
|
|
model.Mesh.Elements[entry.Key] = entry.Value;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
Clean(model);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void GetPretensionLoads(FeModel model, out OrderedDictionary<string, List<PreTensionLoad>> preTensionLoads)
|
|||
|
|
{
|
|||
|
|
string name;
|
|||
|
|
List<PreTensionLoad> preTensionLoadsList;
|
|||
|
|
preTensionLoads =
|
|||
|
|
new OrderedDictionary<string, List<PreTensionLoad>>("Pretension Loads", StringComparer.OrdinalIgnoreCase);
|
|||
|
|
foreach (var step in model.StepCollection.StepsList)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in step.Loads)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is PreTensionLoad ptl)
|
|||
|
|
{
|
|||
|
|
name = ptl.SurfaceName;
|
|||
|
|
if (!ptl.AutoComputeDirection) name += "_" + ptl.X.ToString() + ptl.Y.ToString() + ptl.Z.ToString();
|
|||
|
|
//
|
|||
|
|
if (preTensionLoads.TryGetValue(name, out preTensionLoadsList)) preTensionLoadsList.Add(ptl);
|
|||
|
|
else preTensionLoads.Add(name, new List<PreTensionLoad>() { ptl });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void GetReferencePoints(FeModel model, OrderedDictionary<string, List<PreTensionLoad>> preTensionLoads,
|
|||
|
|
ref int maxNodeId, ref List<FeNodeSet> additionalNodeSets,
|
|||
|
|
out Dictionary<string, string[]> referencePointsNodeSetNames,
|
|||
|
|
out Dictionary<string, int[]> referencePointsNodeIds)
|
|||
|
|
{
|
|||
|
|
HashSet<string> allNodeSetNames = new HashSet<string>(model.Mesh.NodeSets.Keys);
|
|||
|
|
foreach (var nodeSet in additionalNodeSets) allNodeSetNames.Add(nodeSet.Name);
|
|||
|
|
//
|
|||
|
|
string[] nodeSetNames;
|
|||
|
|
FeNodeSet rpNodeSet;
|
|||
|
|
referencePointsNodeIds = new Dictionary<string, int[]>();
|
|||
|
|
referencePointsNodeSetNames = new Dictionary<string, string[]>();
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
// Fill reference point nodes
|
|||
|
|
int id = maxNodeId;
|
|||
|
|
FeReferencePoint rp;
|
|||
|
|
foreach (var entry in model.Mesh.ReferencePoints)
|
|||
|
|
{
|
|||
|
|
rp = entry.Value;
|
|||
|
|
// Check name
|
|||
|
|
rp.RefNodeSetName = rp.Name + FeReferencePoint.RefName + id + 1;
|
|||
|
|
if (allNodeSetNames.Contains(rp.RefNodeSetName))
|
|||
|
|
rp.RefNodeSetName = allNodeSetNames.GetNextNumberedKey(rp.RefNodeSetName);
|
|||
|
|
rp.RotNodeSetName = rp.Name + FeReferencePoint.RotName + id + 2;
|
|||
|
|
if (allNodeSetNames.Contains(rp.RotNodeSetName))
|
|||
|
|
rp.RotNodeSetName = allNodeSetNames.GetNextNumberedKey(rp.RotNodeSetName);
|
|||
|
|
//
|
|||
|
|
rpNodeSet = new FeNodeSet(rp.RefNodeSetName, new int[] { id + 1 });
|
|||
|
|
additionalNodeSets.Add(rpNodeSet);
|
|||
|
|
allNodeSetNames.Add(rpNodeSet.Name);
|
|||
|
|
//
|
|||
|
|
rpNodeSet = new FeNodeSet(rp.RotNodeSetName, new int[] { id + 2 });
|
|||
|
|
additionalNodeSets.Add(rpNodeSet);
|
|||
|
|
allNodeSetNames.Add(rpNodeSet.Name);
|
|||
|
|
//
|
|||
|
|
nodeSetNames = new string[] { rp.RefNodeSetName, rp.RotNodeSetName };
|
|||
|
|
referencePointsNodeSetNames.Add(entry.Key, nodeSetNames);
|
|||
|
|
referencePointsNodeIds.Add(entry.Key, new int[] { id + 1, id + 2 });
|
|||
|
|
id += 2;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
foreach (var entry in preTensionLoads)
|
|||
|
|
{
|
|||
|
|
referencePointsNodeIds.Add(entry.Key, new int[] { id + 1 });
|
|||
|
|
id++;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
maxNodeId = id;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void GetCoordinateSystemNodeSet(FeModel model, Dictionary<string, string[]> referencePointsNodeSetNames,
|
|||
|
|
ref Dictionary<CoordinateSystem, HashSet<string>> coordinateSystemNodeSets)
|
|||
|
|
{
|
|||
|
|
if (model == null || model.StepCollection == null || model.Mesh.CoordinateSystems == null ||
|
|||
|
|
model.Mesh.CoordinateSystems.Count() == 0) return;
|
|||
|
|
//
|
|||
|
|
string nodeSetName;
|
|||
|
|
HashSet<string> nodeSetNames;
|
|||
|
|
FeSurface surface;
|
|||
|
|
FeReferencePoint referencePoint;
|
|||
|
|
CoordinateSystem coordinateSystem;
|
|||
|
|
// Boundary conditions
|
|||
|
|
foreach (var boundaryCondition in model.StepCollection.GetAllBoundaryConditions())
|
|||
|
|
{
|
|||
|
|
if (boundaryCondition.Active &&
|
|||
|
|
model.Mesh.CoordinateSystems.TryGetValue(boundaryCondition.CoordinateSystemName, out coordinateSystem) &&
|
|||
|
|
coordinateSystem != null && boundaryCondition is DisplacementRotation displacementRotation)
|
|||
|
|
{
|
|||
|
|
// Node set
|
|||
|
|
if (displacementRotation.RegionType == RegionTypeEnum.NodeSetName)
|
|||
|
|
{
|
|||
|
|
nodeSetName = displacementRotation.RegionName;
|
|||
|
|
if (coordinateSystemNodeSets.TryGetValue(coordinateSystem, out nodeSetNames))
|
|||
|
|
nodeSetNames.Add(nodeSetName);
|
|||
|
|
else coordinateSystemNodeSets.Add(coordinateSystem, new HashSet<string>() { nodeSetName });
|
|||
|
|
}
|
|||
|
|
// Surface
|
|||
|
|
else if (displacementRotation.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
{
|
|||
|
|
surface = model.Mesh.Surfaces[displacementRotation.RegionName];
|
|||
|
|
nodeSetName = surface.NodeSetName;
|
|||
|
|
if (coordinateSystemNodeSets.TryGetValue(coordinateSystem, out nodeSetNames))
|
|||
|
|
nodeSetNames.Add(nodeSetName);
|
|||
|
|
else coordinateSystemNodeSets.Add(coordinateSystem, new HashSet<string>() { nodeSetName });
|
|||
|
|
}
|
|||
|
|
// Reference point - user coordinate systems do not work for reference points
|
|||
|
|
else if (displacementRotation.RegionType == RegionTypeEnum.ReferencePointName)
|
|||
|
|
{
|
|||
|
|
//referencePoint = model.Mesh.ReferencePoints[displacementRotation.RegionName];
|
|||
|
|
//nodeSetName = referencePointsNodeSetNames[referencePoint.Name][0];
|
|||
|
|
////
|
|||
|
|
//if (coordinateSystemNodeSets.TryGetValue(coordinateSystem, out nodeSetNames))
|
|||
|
|
// nodeSetNames.Add(nodeSetName);
|
|||
|
|
//else coordinateSystemNodeSets.Add(coordinateSystem, new HashSet<string>() { nodeSetName });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Loads
|
|||
|
|
foreach (var load in model.StepCollection.GetAllLoads())
|
|||
|
|
{
|
|||
|
|
if (load.Active &&
|
|||
|
|
model.Mesh.CoordinateSystems.TryGetValue(load.CoordinateSystemName, out coordinateSystem) &&
|
|||
|
|
coordinateSystem != null)
|
|||
|
|
{
|
|||
|
|
if (load is CLoad cLoad)
|
|||
|
|
{
|
|||
|
|
// Node set
|
|||
|
|
if (load.RegionType == RegionTypeEnum.NodeSetName)
|
|||
|
|
{
|
|||
|
|
nodeSetName = load.RegionName;
|
|||
|
|
if (coordinateSystemNodeSets.TryGetValue(coordinateSystem, out nodeSetNames))
|
|||
|
|
nodeSetNames.Add(nodeSetName);
|
|||
|
|
else coordinateSystemNodeSets.Add(coordinateSystem, new HashSet<string>() { nodeSetName });
|
|||
|
|
}
|
|||
|
|
// Reference point
|
|||
|
|
else if (load.RegionType == RegionTypeEnum.ReferencePointName)
|
|||
|
|
{
|
|||
|
|
referencePoint = model.Mesh.ReferencePoints[load.RegionName];
|
|||
|
|
nodeSetName = referencePointsNodeSetNames[referencePoint.Name][0];
|
|||
|
|
//
|
|||
|
|
if (coordinateSystemNodeSets.TryGetValue(coordinateSystem, out nodeSetNames))
|
|||
|
|
nodeSetNames.Add(nodeSetName);
|
|||
|
|
else coordinateSystemNodeSets.Add(coordinateSystem, new HashSet<string>() { nodeSetName });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (load is STLoad stLoad)
|
|||
|
|
{
|
|||
|
|
// Surface
|
|||
|
|
if (stLoad.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
{
|
|||
|
|
surface = model.Mesh.Surfaces[stLoad.RegionName];
|
|||
|
|
nodeSetName = surface.NodeSetName;
|
|||
|
|
if (coordinateSystemNodeSets.TryGetValue(coordinateSystem, out nodeSetNames))
|
|||
|
|
nodeSetNames.Add(nodeSetName);
|
|||
|
|
else coordinateSystemNodeSets.Add(coordinateSystem, new HashSet<string>() { nodeSetName });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void FixPyramidSurfaces(FeModel model, ConvertPyramidsToEnum convertPyramidsTo,
|
|||
|
|
ref Dictionary<int, FeElement> replacedElements,
|
|||
|
|
ref HashSet<string> additionalElementSetNames)
|
|||
|
|
{
|
|||
|
|
// Determine if there are any pyramids in the model
|
|||
|
|
List<BasePart> pyramidContainingParts = new List<BasePart>();
|
|||
|
|
foreach (var entry in model.Mesh.Parts)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.ElementTypes.Contains(typeof(LinearPyramidElement)) ||
|
|||
|
|
entry.Value.ElementTypes.Contains(typeof(ParabolicPyramidElement)))
|
|||
|
|
pyramidContainingParts.Add(entry.Value);
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
if (pyramidContainingParts.Count > 0)
|
|||
|
|
{
|
|||
|
|
// Create a mapping from pyramid faces to wedge or hex faces
|
|||
|
|
Dictionary<FeFaceName, FeFaceName> pyramidToNormalFaceName;
|
|||
|
|
if (convertPyramidsTo == ConvertPyramidsToEnum.Wedges)
|
|||
|
|
{
|
|||
|
|
pyramidToNormalFaceName = new Dictionary<FeFaceName, FeFaceName>() {{ FeFaceName.S1, FeFaceName.S5 },
|
|||
|
|
{ FeFaceName.S2, FeFaceName.S1 },
|
|||
|
|
{ FeFaceName.S3, FeFaceName.S4 },
|
|||
|
|
{ FeFaceName.S4, FeFaceName.S2 },
|
|||
|
|
{ FeFaceName.S5, FeFaceName.S3 }};
|
|||
|
|
}
|
|||
|
|
else if (convertPyramidsTo == ConvertPyramidsToEnum.Hexahedrons)
|
|||
|
|
{
|
|||
|
|
pyramidToNormalFaceName = new Dictionary<FeFaceName, FeFaceName>() {{ FeFaceName.S1, FeFaceName.S1 },
|
|||
|
|
{ FeFaceName.S2, FeFaceName.S3 },
|
|||
|
|
{ FeFaceName.S3, FeFaceName.S4 },
|
|||
|
|
{ FeFaceName.S4, FeFaceName.S5 },
|
|||
|
|
{ FeFaceName.S5, FeFaceName.S6 }};
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
//
|
|||
|
|
Type elementType;
|
|||
|
|
FeElement element;
|
|||
|
|
HashSet<int> elementIds = new HashSet<int>();
|
|||
|
|
HashSet<int> allPyramidElementIds = new HashSet<int>();
|
|||
|
|
foreach (var part in pyramidContainingParts) elementIds.UnionWith(part.Labels);
|
|||
|
|
// Collect all pyramid element ids
|
|||
|
|
foreach (var elementId in elementIds)
|
|||
|
|
{
|
|||
|
|
element = model.Mesh.Elements[elementId];
|
|||
|
|
elementType = element.GetType();
|
|||
|
|
if (elementType == typeof(LinearPyramidElement) || elementType == typeof(ParabolicPyramidElement))
|
|||
|
|
{
|
|||
|
|
allPyramidElementIds.Add(elementId);
|
|||
|
|
replacedElements.Add(element.Id, element);
|
|||
|
|
//
|
|||
|
|
if (element is LinearPyramidElement lpe)
|
|||
|
|
{
|
|||
|
|
if (convertPyramidsTo == ConvertPyramidsToEnum.Wedges)
|
|||
|
|
model.Mesh.Elements[elementId] = lpe.ConvertToWedge();
|
|||
|
|
else if (convertPyramidsTo == ConvertPyramidsToEnum.Hexahedrons)
|
|||
|
|
model.Mesh.Elements[elementId] = lpe.ConvertToHex();
|
|||
|
|
else
|
|||
|
|
throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
else if (element is ParabolicPyramidElement ppe)
|
|||
|
|
{
|
|||
|
|
if (convertPyramidsTo == ConvertPyramidsToEnum.Wedges)
|
|||
|
|
model.Mesh.Elements[elementId] = ppe.ConvertToWedge();
|
|||
|
|
else if (convertPyramidsTo == ConvertPyramidsToEnum.Hexahedrons)
|
|||
|
|
model.Mesh.Elements[elementId] = ppe.ConvertToHex();
|
|||
|
|
else
|
|||
|
|
throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
bool needFixing;
|
|||
|
|
string name;
|
|||
|
|
FeFaceName faceName;
|
|||
|
|
FeSurface surface;
|
|||
|
|
FeSurface fixedSurface;
|
|||
|
|
FeElementSet elementSet;
|
|||
|
|
HashSet<int> normalElementsIds;
|
|||
|
|
HashSet<int> pyramidElementsIds;
|
|||
|
|
Dictionary<FeFaceName, HashSet<int>> faceNameElementIds;
|
|||
|
|
HashSet<string> reservedElementSetNames = model.Mesh.GetReservedElementSetNames();
|
|||
|
|
//
|
|||
|
|
foreach (var surfaceEntry in model.Mesh.Surfaces)
|
|||
|
|
{
|
|||
|
|
// Determine if the surface contain pyramid elements
|
|||
|
|
needFixing = false;
|
|||
|
|
surface = surfaceEntry.Value;
|
|||
|
|
foreach (var entry in surface.ElementFaces)
|
|||
|
|
{
|
|||
|
|
elementSet = model.Mesh.ElementSets[entry.Value];
|
|||
|
|
if (allPyramidElementIds.Intersect(elementSet.Labels).Count() > 0)
|
|||
|
|
{
|
|||
|
|
needFixing = true;
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// If the surface contains pyramid elements
|
|||
|
|
if (needFixing)
|
|||
|
|
{
|
|||
|
|
// Collect pyramid and normal element ids separately
|
|||
|
|
faceNameElementIds = new Dictionary<FeFaceName, HashSet<int>>();
|
|||
|
|
foreach (var entry in surface.ElementFaces)
|
|||
|
|
{
|
|||
|
|
elementSet = model.Mesh.ElementSets[entry.Value];
|
|||
|
|
pyramidElementsIds = new HashSet<int>(allPyramidElementIds.Intersect(elementSet.Labels));
|
|||
|
|
normalElementsIds = new HashSet<int>(elementSet.Labels.Except(pyramidElementsIds));
|
|||
|
|
//
|
|||
|
|
if (normalElementsIds.Count > 0)
|
|||
|
|
{
|
|||
|
|
faceName = entry.Key;
|
|||
|
|
if (faceNameElementIds.TryGetValue(faceName, out elementIds)) elementIds.UnionWith(normalElementsIds);
|
|||
|
|
else faceNameElementIds.Add(faceName, normalElementsIds);
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
if (pyramidElementsIds.Count > 0)
|
|||
|
|
{
|
|||
|
|
faceName = pyramidToNormalFaceName[entry.Key];
|
|||
|
|
if (faceNameElementIds.TryGetValue(faceName, out elementIds)) elementIds.UnionWith(pyramidElementsIds);
|
|||
|
|
else faceNameElementIds.Add(faceName, pyramidElementsIds);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Create new surface with the same name
|
|||
|
|
fixedSurface = new FeSurface(surface.Name);
|
|||
|
|
//
|
|||
|
|
foreach (var entry in faceNameElementIds)
|
|||
|
|
{
|
|||
|
|
// Get element set name
|
|||
|
|
name = surface.Name + "_Pyramid_" + entry.Key;
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
// Create new element set
|
|||
|
|
elementSet = new FeElementSet(name, entry.Value.ToArray());
|
|||
|
|
model.Mesh.ElementSets.Add(elementSet.Name, elementSet);
|
|||
|
|
additionalElementSetNames.Add(elementSet.Name);
|
|||
|
|
//
|
|||
|
|
fixedSurface.AddElementFace(entry.Key, elementSet.Name);
|
|||
|
|
//
|
|||
|
|
fixedSurface.NodeSetName = surface.NodeSetName;
|
|||
|
|
}
|
|||
|
|
// Add fixed surface
|
|||
|
|
model.Mesh.Surfaces[fixedSurface.Name] = fixedSurface;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void GetMassSections(FeModel model, Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
ref int maxElementId, ref List<CalElement> additionalElementKeywords,
|
|||
|
|
ref HashSet<string> additionalElementSetNames,
|
|||
|
|
ref List<SectionData> additionalSectionData)
|
|||
|
|
{
|
|||
|
|
double aSum;
|
|||
|
|
double nodalMassFactor;
|
|||
|
|
double nodalMass;
|
|||
|
|
string name;
|
|||
|
|
List<int> elementIds;
|
|||
|
|
FeElement element;
|
|||
|
|
FeNodeSet nodeSet;
|
|||
|
|
FeElementSet elementSet;
|
|||
|
|
FeSurface surface;
|
|||
|
|
FeReferencePoint referencePoint;
|
|||
|
|
MassSectionData massSectionData;
|
|||
|
|
Dictionary<int, double> nodalValues;
|
|||
|
|
CalElement calElement;
|
|||
|
|
HashSet<string> reservedElementSetNames = model.Mesh.GetReservedElementSetNames();
|
|||
|
|
//
|
|||
|
|
foreach (var entry in model.Sections)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is MassSection ms)
|
|||
|
|
{
|
|||
|
|
if (ms is PointMassSection pms)
|
|||
|
|
{
|
|||
|
|
if (pms.RegionType == RegionTypeEnum.NodeSetName)
|
|||
|
|
{
|
|||
|
|
elementIds = new List<int>();
|
|||
|
|
nodeSet = model.Mesh.NodeSets[pms.RegionName];
|
|||
|
|
nodalMass = pms.Mass.Value;
|
|||
|
|
//
|
|||
|
|
foreach (var nodeId in nodeSet.Labels)
|
|||
|
|
{
|
|||
|
|
// Name
|
|||
|
|
name = pms.Name + "_NID_" + nodeId;
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
// Element keyword
|
|||
|
|
maxElementId++;
|
|||
|
|
element = new MassElement(maxElementId, new int[] { nodeId });
|
|||
|
|
calElement = new CalElement(FeElementType0D.Mass.ToString(), name, new List<FeElement> { element });
|
|||
|
|
additionalElementKeywords.Add(calElement);
|
|||
|
|
elementIds.Add(maxElementId);
|
|||
|
|
// Mass section
|
|||
|
|
massSectionData = new MassSectionData("NID_" + nodeId, name, nodalMass);
|
|||
|
|
additionalSectionData.Add(massSectionData);
|
|||
|
|
}
|
|||
|
|
// Add elements in sets
|
|||
|
|
name = pms.Name + "_All";
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
//
|
|||
|
|
elementSet = new FeElementSet(name, elementIds.ToArray());
|
|||
|
|
model.Mesh.ElementSets.Add(elementSet.Name, elementSet);
|
|||
|
|
additionalElementSetNames.Add(elementSet.Name);
|
|||
|
|
//
|
|||
|
|
pms.ElementSetName = name; // temporary storage
|
|||
|
|
}
|
|||
|
|
else if (pms.RegionType == RegionTypeEnum.ReferencePointName)
|
|||
|
|
{
|
|||
|
|
elementIds = new List<int>();
|
|||
|
|
referencePoint = model.Mesh.ReferencePoints[pms.RegionName];
|
|||
|
|
int nodeId = referencePointsNodeIds[referencePoint.Name][0];
|
|||
|
|
nodalMass = pms.Mass.Value;
|
|||
|
|
|
|||
|
|
// Name
|
|||
|
|
name = pms.Name + "_RP_" + referencePoint.Name;
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
// Element keyword
|
|||
|
|
maxElementId++;
|
|||
|
|
element = new MassElement(maxElementId, new int[] { nodeId });
|
|||
|
|
calElement = new CalElement(FeElementType0D.Mass.ToString(), name, new List<FeElement> { element });
|
|||
|
|
additionalElementKeywords.Add(calElement);
|
|||
|
|
elementIds.Add(maxElementId);
|
|||
|
|
// Mass section
|
|||
|
|
massSectionData = new MassSectionData("NID_" + nodeId, name, nodalMass);
|
|||
|
|
additionalSectionData.Add(massSectionData);
|
|||
|
|
// Add elements in sets
|
|||
|
|
pms.ElementSetName = name; // temporary storage
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
else if (ms is DistributedMassSection dms)
|
|||
|
|
{
|
|||
|
|
elementIds = new List<int>();
|
|||
|
|
surface = model.Mesh.Surfaces[dms.RegionName];
|
|||
|
|
nodeSet = model.Mesh.NodeSets[surface.NodeSetName];
|
|||
|
|
model.GetDistributedNodalValuesFromSurface(surface.Name, out nodalValues, out aSum);
|
|||
|
|
nodalMassFactor = dms.Mass.Value / aSum;
|
|||
|
|
//
|
|||
|
|
foreach (var nodeId in nodeSet.Labels)
|
|||
|
|
{
|
|||
|
|
// Name
|
|||
|
|
name = dms.Name + "_NID_" + nodeId;
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
// Element keyword
|
|||
|
|
maxElementId++;
|
|||
|
|
element = new MassElement(maxElementId, new int[] { nodeId });
|
|||
|
|
calElement = new CalElement(FeElementType0D.Mass.ToString(), name, new List<FeElement> { element });
|
|||
|
|
additionalElementKeywords.Add(calElement);
|
|||
|
|
elementIds.Add(maxElementId);
|
|||
|
|
// Mass section
|
|||
|
|
nodalMass = nodalValues[nodeId] * nodalMassFactor;
|
|||
|
|
massSectionData = new MassSectionData("NID_" + nodeId, name, nodalMass);
|
|||
|
|
additionalSectionData.Add(massSectionData);
|
|||
|
|
}
|
|||
|
|
// Add elements in sets
|
|||
|
|
name = dms.Name + "_All";
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
//
|
|||
|
|
elementSet = new FeElementSet(name, elementIds.ToArray());
|
|||
|
|
model.Mesh.ElementSets.Add(elementSet.Name, elementSet);
|
|||
|
|
additionalElementSetNames.Add(elementSet.Name);
|
|||
|
|
//
|
|||
|
|
dms.ElementSetName = name; // temporary storage
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void GetPointSprings(FeModel model, Dictionary<string, int[]> referencePointsNodeIds, ref int maxElementId,
|
|||
|
|
ref List<CalElement> additionalElementKeywords,
|
|||
|
|
ref HashSet<string> additionalElementSetNames,
|
|||
|
|
ref List<SectionData> additionalSectionData)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
bool twoD = model.Properties.ModelSpace.IsTwoD();
|
|||
|
|
int count;
|
|||
|
|
int[] elementIds;
|
|||
|
|
int[] refPointIds;
|
|||
|
|
int[] directions;
|
|||
|
|
double[] stiffnesses;
|
|||
|
|
string name;
|
|||
|
|
int elementId = maxElementId;
|
|||
|
|
FeNodeSet nodeSet;
|
|||
|
|
FeElementSet elementSet;
|
|||
|
|
List<FeElement> newElements;
|
|||
|
|
List<FeElement> oneSpringElements;
|
|||
|
|
// Collect point and surface springs
|
|||
|
|
Dictionary<string, PointSpringData[]> activeSprings = new Dictionary<string, PointSpringData[]>();
|
|||
|
|
foreach (var entry in model.Constraints)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is PointSpring ps && ps.Active)
|
|||
|
|
activeSprings.Add(ps.Name, new PointSpringData[] { new PointSpringData(ps) });
|
|||
|
|
else if (entry.Value is SurfaceSpring ss && ss.Active)
|
|||
|
|
activeSprings.Add(ss.Name, model.GetPointSpringsFromSurfaceSpring(ss));
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
HashSet<string> reservedElementSetNames = model.Mesh.GetReservedElementSetNames();
|
|||
|
|
//
|
|||
|
|
foreach (var entry in activeSprings)
|
|||
|
|
{
|
|||
|
|
oneSpringElements = new List<FeElement>();
|
|||
|
|
//
|
|||
|
|
foreach (PointSpringData psd in entry.Value)
|
|||
|
|
{
|
|||
|
|
directions = psd.GetSpringDirections();
|
|||
|
|
stiffnesses = psd.GetSpringStiffnessValues();
|
|||
|
|
//
|
|||
|
|
if (directions.Length == 0) continue;
|
|||
|
|
//
|
|||
|
|
for (int i = 0; i < directions.Length; i++)
|
|||
|
|
{
|
|||
|
|
// Name
|
|||
|
|
name = psd.Name + "_DOF_" + directions[i];
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
//
|
|||
|
|
newElements = new List<FeElement>();
|
|||
|
|
// Node id
|
|||
|
|
if (psd.RegionType == RegionTypeEnum.NodeId)
|
|||
|
|
{
|
|||
|
|
newElements.Add(new LinearSpringElement(elementId + 1, new int[] { psd.NodeId }));
|
|||
|
|
elementId++;
|
|||
|
|
}
|
|||
|
|
// Node set
|
|||
|
|
else if (psd.RegionType == RegionTypeEnum.NodeSetName)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh.NodeSets.TryGetValue(psd.RegionName, out nodeSet))
|
|||
|
|
{
|
|||
|
|
foreach (var label in nodeSet.Labels)
|
|||
|
|
{
|
|||
|
|
newElements.Add(new LinearSpringElement(elementId + 1, new int[] { label }));
|
|||
|
|
elementId++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Reference point
|
|||
|
|
else if (psd.RegionType == RegionTypeEnum.ReferencePointName)
|
|||
|
|
{
|
|||
|
|
if (referencePointsNodeIds.TryGetValue(psd.RegionName, out refPointIds))
|
|||
|
|
{
|
|||
|
|
newElements.Add(new LinearSpringElement(elementId + 1, new int[] { refPointIds[0] }));
|
|||
|
|
elementId++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
// Get element ids
|
|||
|
|
count = 0;
|
|||
|
|
elementIds = new int[newElements.Count];
|
|||
|
|
foreach (var element in newElements) elementIds[count++] = element.Id;
|
|||
|
|
// Add items
|
|||
|
|
elementSet = new FeElementSet(name, elementIds);
|
|||
|
|
model.Mesh.ElementSets.Add(elementSet.Name, elementSet);
|
|||
|
|
additionalElementSetNames.Add(elementSet.Name);
|
|||
|
|
additionalSectionData.Add(new LinearSpringSectionData("LinearSpringSection", name, directions[i],
|
|||
|
|
stiffnesses[i]));
|
|||
|
|
oneSpringElements.AddRange(newElements);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Add elements in sets
|
|||
|
|
name = entry.Key + "_All";
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
additionalElementKeywords.Add(new CalElement(FeElementTypeSpring.SPRING1.ToString(), name, oneSpringElements));
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
maxElementId = elementId;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void GetCompressionOnlyConstraintData(FeModel model, ref int maxNodeId, ref int maxElementId,
|
|||
|
|
ref List<FeNode> additionalNodes,
|
|||
|
|
ref List<FeNodeSet> additionalNodeSets,
|
|||
|
|
ref List<CalElement> additionalElementKeywords,
|
|||
|
|
ref HashSet<string> additionalElementSetNames,
|
|||
|
|
ref List<SectionData> additionalSectionData,
|
|||
|
|
ref List<Material> additionalMaterials,
|
|||
|
|
ref List<BoundaryCondition> additionalBoundaryConditions,
|
|||
|
|
ref List<double[]> equationParameters)
|
|||
|
|
{
|
|||
|
|
HashSet<string> elementIdsHash = new HashSet<string>();
|
|||
|
|
//
|
|||
|
|
bool twoD = model.Properties.ModelSpace.IsTwoD();
|
|||
|
|
bool shellEdgeFace;
|
|||
|
|
bool shellElement;
|
|||
|
|
bool nonLinear = false;
|
|||
|
|
double[] faceNormal;
|
|||
|
|
FeElement element;
|
|||
|
|
FeElementSet elementSet;
|
|||
|
|
FeSurface surface;
|
|||
|
|
Vec3D normalVec;
|
|||
|
|
List<Vec3D> nodeNormals;
|
|||
|
|
Dictionary<int, List<Vec3D>> nodeIdNodeNormals = new Dictionary<int, List<Vec3D>>();
|
|||
|
|
//
|
|||
|
|
double[] normal;
|
|||
|
|
Dictionary<int, double[]> nodeIdNormal = new Dictionary<int, double[]>();
|
|||
|
|
int count;
|
|||
|
|
int newNodeId = maxNodeId;
|
|||
|
|
int newElementId = maxElementId;
|
|||
|
|
List<int> elementIds;
|
|||
|
|
string name;
|
|||
|
|
//
|
|||
|
|
FeNode node1;
|
|||
|
|
FeNode node2;
|
|||
|
|
List<int> bcNodeIds = new List<int>();
|
|||
|
|
LinearGapElement gapElement;
|
|||
|
|
List<FeElement> elementsToAdd = new List<FeElement>();
|
|||
|
|
double clearance;
|
|||
|
|
double area;
|
|||
|
|
double nodeStiffness;
|
|||
|
|
double nodeForce;
|
|||
|
|
double offset;
|
|||
|
|
double nodeStiffnessPerArea;
|
|||
|
|
double nodeForcePerArea;
|
|||
|
|
Dictionary<int, double> nodeIdNodeWeight;
|
|||
|
|
HashSet<string> reservedElementSetNames = model.Mesh.GetReservedElementSetNames();
|
|||
|
|
// Get all nodes and their normals
|
|||
|
|
foreach (var constraintEntry in model.Constraints)
|
|||
|
|
{
|
|||
|
|
if (constraintEntry.Value is CompressionOnly co)
|
|||
|
|
{
|
|||
|
|
if (co.Active && co.Valid)
|
|||
|
|
{
|
|||
|
|
clearance = co.Clearance.Value;
|
|||
|
|
//
|
|||
|
|
nodeIdNodeNormals.Clear();
|
|||
|
|
surface = model.Mesh.Surfaces[co.MasterRegionName];
|
|||
|
|
model.GetDistributedNodalValuesFromSurface(surface.Name, out nodeIdNodeWeight, out area);
|
|||
|
|
//
|
|||
|
|
nodeStiffnessPerArea = co.SpringStiffness.Value;
|
|||
|
|
if (double.IsNaN(nodeStiffnessPerArea)) nodeStiffnessPerArea = GapSectionData.InitialSpringStiffness;
|
|||
|
|
nodeStiffnessPerArea = nodeStiffnessPerArea / area;
|
|||
|
|
//
|
|||
|
|
nodeForcePerArea = co.TensileForceAtNegativeInfinity.Value;
|
|||
|
|
if (double.IsNaN(nodeForcePerArea)) nodeForcePerArea = GapSectionData.InitialTensileForceAtNegativeInfinity;
|
|||
|
|
nodeForcePerArea = nodeForcePerArea / area;
|
|||
|
|
//
|
|||
|
|
offset = co.Offset.Value;
|
|||
|
|
//
|
|||
|
|
foreach (var entry in surface.ElementFaces)
|
|||
|
|
{
|
|||
|
|
elementSet = model.Mesh.ElementSets[entry.Value];
|
|||
|
|
foreach (var elementId in elementSet.Labels)
|
|||
|
|
{
|
|||
|
|
if (elementIdsHash.Contains(entry.Key.ToString() + "_" + elementId))
|
|||
|
|
throw new CaeException("Element id: " + elementId +
|
|||
|
|
" has more than one compression only constraint defined.");
|
|||
|
|
//
|
|||
|
|
element = model.Mesh.Elements[elementId];
|
|||
|
|
elementIdsHash.Add(entry.Key.ToString() + "_" + elementId);
|
|||
|
|
//
|
|||
|
|
model.Mesh.GetElementFaceCenterAndNormal(elementId, entry.Key, out _, out faceNormal,
|
|||
|
|
out shellElement);
|
|||
|
|
// Invert normal
|
|||
|
|
shellEdgeFace = shellElement && entry.Key != FeFaceName.S1 && entry.Key != FeFaceName.S2;
|
|||
|
|
if (shellElement && !shellEdgeFace)
|
|||
|
|
{
|
|||
|
|
faceNormal[0] *= -1;
|
|||
|
|
faceNormal[1] *= -1;
|
|||
|
|
faceNormal[2] *= -1;
|
|||
|
|
}
|
|||
|
|
normalVec = new Vec3D(faceNormal);
|
|||
|
|
//
|
|||
|
|
foreach (var nodeId in element.GetNodeIdsFromFaceName(entry.Key))
|
|||
|
|
{
|
|||
|
|
if (nodeIdNodeNormals.TryGetValue(nodeId, out nodeNormals)) nodeNormals.Add(normalVec);
|
|||
|
|
else nodeIdNodeNormals.Add(nodeId, new List<Vec3D>() { normalVec });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Get a dictionary of all node ids that have the same normal
|
|||
|
|
nodeIdNormal.Clear();
|
|||
|
|
foreach (var entry in nodeIdNodeNormals)
|
|||
|
|
{
|
|||
|
|
normalVec = new Vec3D();
|
|||
|
|
foreach (var normalEntry in entry.Value) normalVec += normalEntry;
|
|||
|
|
normalVec.Normalize();
|
|||
|
|
//
|
|||
|
|
nodeIdNormal.Add(entry.Key, normalVec.Coor);
|
|||
|
|
}
|
|||
|
|
// Get nodes, elements, element sets, gap sections, boundary conditions
|
|||
|
|
count = 1;
|
|||
|
|
foreach (var entry in nodeIdNormal)
|
|||
|
|
{
|
|||
|
|
if (nodeIdNodeWeight[entry.Key] != 0)
|
|||
|
|
{
|
|||
|
|
normal = entry.Value;
|
|||
|
|
elementIds = new List<int>();
|
|||
|
|
name = co.Name + "_ElementSet-" + count++;
|
|||
|
|
if (reservedElementSetNames.Contains(name)) name = reservedElementSetNames.GetNextNumberedKey(name);
|
|||
|
|
reservedElementSetNames.Add(name);
|
|||
|
|
// Node 1
|
|||
|
|
newNodeId++;
|
|||
|
|
bcNodeIds.Add(newNodeId);
|
|||
|
|
//
|
|||
|
|
node1 = new FeNode(newNodeId, model.Mesh.Nodes[entry.Key].Coor);
|
|||
|
|
node1.X -= offset * normal[0];
|
|||
|
|
node1.Y -= offset * normal[1];
|
|||
|
|
node1.Z -= offset * normal[2];
|
|||
|
|
additionalNodes.Add(node1);
|
|||
|
|
// Node 2
|
|||
|
|
newNodeId++;
|
|||
|
|
//
|
|||
|
|
node2 = new FeNode(newNodeId, model.Mesh.Nodes[entry.Key].Coor);
|
|||
|
|
additionalNodes.Add(node2);
|
|||
|
|
//
|
|||
|
|
newElementId++;
|
|||
|
|
gapElement = new LinearGapElement(newElementId, new int[] { node1.Id, node2.Id });
|
|||
|
|
elementIds.Add(newElementId);
|
|||
|
|
elementsToAdd.Add(gapElement);
|
|||
|
|
// Equations
|
|||
|
|
equationParameters.Add(new double[] { node2.Id, 1, 1, entry.Key, 1, -1 });
|
|||
|
|
equationParameters.Add(new double[] { node2.Id, 2, 1, entry.Key, 2, -1 });
|
|||
|
|
equationParameters.Add(new double[] { node2.Id, 3, 1, entry.Key, 3, -1 });
|
|||
|
|
//
|
|||
|
|
elementSet = new FeElementSet(name, elementIds.ToArray());
|
|||
|
|
model.Mesh.ElementSets.Add(elementSet.Name, elementSet);
|
|||
|
|
additionalElementSetNames.Add(elementSet.Name);
|
|||
|
|
// Scale to nodal area
|
|||
|
|
nodeStiffness = nodeStiffnessPerArea * nodeIdNodeWeight[entry.Key];
|
|||
|
|
nodeForce = nodeForcePerArea * nodeIdNodeWeight[entry.Key];
|
|||
|
|
// Gap section
|
|||
|
|
additionalSectionData.Add(new GapSectionData("GapSectionData", name, clearance, normal,
|
|||
|
|
nodeStiffness, nodeForce));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
if (co.NonLinear) nonLinear = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Add all elements
|
|||
|
|
if (elementsToAdd.Count > 0)
|
|||
|
|
additionalElementKeywords.Add(new CalElement(FeElementTypeGap.GAPUNI.ToString(), null, elementsToAdd));
|
|||
|
|
// Boundary conditions
|
|||
|
|
if (bcNodeIds.Count > 0)
|
|||
|
|
{
|
|||
|
|
name = "Internal_All_Compression_Only_Constraints_NodeSet";
|
|||
|
|
additionalNodeSets.Add(new FeNodeSet(name, bcNodeIds.ToArray()));
|
|||
|
|
DisplacementRotation dr = new DisplacementRotation("Compression_Only_BC", name, RegionTypeEnum.NodeSetName,
|
|||
|
|
twoD, false, 0);
|
|||
|
|
dr.U1.SetEquationFromValue(0);
|
|||
|
|
dr.U2.SetEquationFromValue(0);
|
|||
|
|
dr.U3.SetEquationFromValue(0);
|
|||
|
|
additionalBoundaryConditions.Add(dr);
|
|||
|
|
}
|
|||
|
|
// Materials
|
|||
|
|
if (nonLinear)
|
|||
|
|
{
|
|||
|
|
Material material = new Material(model.Materials.GetNextNumberedKey("Internal_compression_only"));
|
|||
|
|
material.AddProperty(new Density(new double[][] { new double[] { 1, 0 } }));
|
|||
|
|
material.AddProperty(new Elastic(new double[][] { new double[] { 1, 0, 0 } }));
|
|||
|
|
material.AddProperty(new Plastic(new double[][] { new double[] { 0, 0, 0 } }));
|
|||
|
|
additionalMaterials.Add(material);
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
maxNodeId = newNodeId;
|
|||
|
|
maxElementId = newElementId;
|
|||
|
|
}
|
|||
|
|
public static bool AddUserKeywordByIndices(List<CalculixKeyword> keywords, int[] indices, CalculixKeyword userKeyword)
|
|||
|
|
{
|
|||
|
|
if (indices.Length == 1)
|
|||
|
|
{
|
|||
|
|
keywords.Insert(indices[0], userKeyword);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
bool deactivated = false;
|
|||
|
|
CalculixKeyword keywordParent = keywords[indices[0]];
|
|||
|
|
if (keywordParent is CalDeactivated) deactivated = true;
|
|||
|
|
// Find a parent
|
|||
|
|
for (int i = 1; i < indices.Length - 1; i++)
|
|||
|
|
{
|
|||
|
|
if (indices[i] < keywordParent.Keywords.Count)
|
|||
|
|
{
|
|||
|
|
keywordParent = keywordParent.Keywords[indices[i]];
|
|||
|
|
if (keywordParent is CalDeactivated) deactivated = true;
|
|||
|
|
}
|
|||
|
|
else return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Add the keyword
|
|||
|
|
if (keywordParent.Keywords.Count < indices[indices.Length - 1]) return false;
|
|||
|
|
|
|||
|
|
if (!deactivated) keywordParent.Keywords.Insert(indices[indices.Length - 1], userKeyword);
|
|||
|
|
else keywordParent.Keywords.Insert(indices[indices.Length - 1], new CalDeactivated("User keyword"));
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
public static void RemoveLostUserKeywords(FeModel model)
|
|||
|
|
{
|
|||
|
|
List<CalculixKeyword> keywords = GetModelKeywords(model, ConvertPyramidsToEnum.Wedges, null, true);
|
|||
|
|
// Add user keywords
|
|||
|
|
List<int[]> keywordKeysToRemove = new List<int[]>();
|
|||
|
|
if (model.CalculixUserKeywords != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.CalculixUserKeywords)
|
|||
|
|
{
|
|||
|
|
if (!AddUserKeywordByIndices(keywords, entry.Key, entry.Value.DeepClone())) keywordKeysToRemove.Add(entry.Key);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Remove lost user keywords
|
|||
|
|
foreach (var indices in keywordKeysToRemove)
|
|||
|
|
{
|
|||
|
|
model.CalculixUserKeywords.Remove(indices);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
public static string GetShortKeywordData(CalculixKeyword keyword, bool useHiding)
|
|||
|
|
{
|
|||
|
|
StringBuilder sb = new StringBuilder();
|
|||
|
|
sb.Append(keyword.GetKeywordString());
|
|||
|
|
if (!(keyword is CalNode) &&
|
|||
|
|
!(keyword is CalElement) &&
|
|||
|
|
!(keyword is CalNodeSet) &&
|
|||
|
|
!(keyword is CalElementSet) &&
|
|||
|
|
!(keyword is CalInitialTemperature it && it.CanHideData) &&
|
|||
|
|
!(keyword is CalTemperatureBC tbc && tbc.CanHideData) &&
|
|||
|
|
!(keyword is CalVariablePressureLoad) &&
|
|||
|
|
!(keyword is CalImportedPressureLoad) &&
|
|||
|
|
!(keyword is CalSTLoad) &&
|
|||
|
|
!(keyword is CalDefinedTemperature dt && dt.CanHideData) &&
|
|||
|
|
!(keyword is CalAdditional))
|
|||
|
|
{
|
|||
|
|
sb.Append(keyword.GetDataString());
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
// //int n = 10;
|
|||
|
|
// //string[] lines = keyword.GetDataString().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
|
|||
|
|
// //for (int i = 0; i < Math.Min(n, lines.Length); i++) sb.AppendLine(lines[i]);
|
|||
|
|
// //if (lines.Length > n) sb.AppendLine("... hidden data ...");
|
|||
|
|
if (useHiding) sb.AppendLine("... hidden data ...");
|
|||
|
|
else sb.Append(keyword.GetDataString());
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
string text = sb.ToString();
|
|||
|
|
if (text.EndsWith(Environment.NewLine)) text = text.Substring(0, text.Length - Environment.NewLine.Length);
|
|||
|
|
return text;
|
|||
|
|
}
|
|||
|
|
private static void WriteKeywordRecursively(StringBuilder sb, CalculixKeyword keyword)
|
|||
|
|
{
|
|||
|
|
sb.Append(keyword.GetKeywordString());
|
|||
|
|
sb.Append(keyword.GetDataString());
|
|||
|
|
//
|
|||
|
|
foreach (var childKeyword in keyword.Keywords)
|
|||
|
|
{
|
|||
|
|
WriteKeywordRecursively(sb, childKeyword);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
private static string[] GetAllSubmodelNodeSetNames(FeModel model)
|
|||
|
|
{
|
|||
|
|
List<string> nodeSetNames = new List<string>();
|
|||
|
|
foreach (var step in model.StepCollection.StepsList)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in step.BoundaryConditions)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is SubmodelBC sm && sm.Active)
|
|||
|
|
{
|
|||
|
|
if (sm.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
nodeSetNames.Add(model.Mesh.Surfaces[sm.RegionName].NodeSetName);
|
|||
|
|
else nodeSetNames.Add(sm.RegionName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return nodeSetNames.ToArray();
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
private static void AppendHeading(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalHeading heading = new CalHeading(model.Name, model.HashName, model.UnitSystem.UnitSystemType);
|
|||
|
|
parent.AddKeyword(heading);
|
|||
|
|
}
|
|||
|
|
private static void AppendSubmodel(FeModel model, string[] nodeSetNames, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
//*Submodel, TYPE = NODE, INPUT = Model.frd
|
|||
|
|
CalSubmodel submodel = new CalSubmodel(model.Properties.GlobalResultsFileName, nodeSetNames);
|
|||
|
|
parent.AddKeyword(submodel);
|
|||
|
|
}
|
|||
|
|
private static void AppendNodes(FeModel model, List<FeNode> additionalNodes,
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
Dictionary<int, double[]> deformations, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
CalNode node = new CalNode(model, additionalNodes, referencePointsNodeIds, deformations);
|
|||
|
|
parent.AddKeyword(node);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
private static void AppendElements(FeModel model, List<CalElement> additionalElementKeywords,
|
|||
|
|
CalculixKeyword parent, ConvertPyramidsToEnum convertPyramidsTo)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
Dictionary<string, List<FeElement>> elementTypes = new Dictionary<string, List<FeElement>>();
|
|||
|
|
List<FeElement> elements;
|
|||
|
|
//
|
|||
|
|
string type;
|
|||
|
|
FeElement element;
|
|||
|
|
MeshPart part;
|
|||
|
|
CalElement elementKeyword;
|
|||
|
|
//
|
|||
|
|
foreach (var entry in model.Mesh.Parts)
|
|||
|
|
{
|
|||
|
|
elementTypes.Clear();
|
|||
|
|
part = (MeshPart)entry.Value;
|
|||
|
|
|
|||
|
|
// Labels中存当前Part的所有单元编号,根据其类型加入到对应单元类型中,然后按照类型输出
|
|||
|
|
foreach (int elementId in part.Labels)
|
|||
|
|
{
|
|||
|
|
element = model.Mesh.Elements[elementId];
|
|||
|
|
|
|||
|
|
if (part.LinearTriaType != FeElementTypeLinearTria.None &&
|
|||
|
|
element is LinearTriangleElement)
|
|||
|
|
{
|
|||
|
|
type = part.LinearTriaType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.LinearQuadType != FeElementTypeLinearQuad.None &&
|
|||
|
|
element is LinearQuadrilateralElement)
|
|||
|
|
{
|
|||
|
|
type = part.LinearQuadType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.LinearTetraType != FeElementTypeLinearTetra.None &&
|
|||
|
|
element is LinearTetraElement)
|
|||
|
|
{
|
|||
|
|
type = part.LinearTetraType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.LinearPyramidType != FeElementTypeLinearPyramid.None &&
|
|||
|
|
element is LinearPyramidElement)
|
|||
|
|
{
|
|||
|
|
type = part.LinearPyramidType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.LinearWedgeType != FeElementTypeLinearWedge.None &&
|
|||
|
|
element is LinearWedgeElement)
|
|||
|
|
{
|
|||
|
|
type = part.LinearWedgeType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.LinearWedgeType == FeElementTypeLinearWedge.None && //
|
|||
|
|
element is LinearWedgeElement) // converted pyramids
|
|||
|
|
{
|
|||
|
|
type = FeElementTypeLinearWedge.C3D6.ToString(); //
|
|||
|
|
}
|
|||
|
|
else if (part.LinearHexaType == FeElementTypeLinearHexa.None && //
|
|||
|
|
element is LinearHexaElement) // converted pyramids
|
|||
|
|
{
|
|||
|
|
type = FeElementTypeLinearHexa.C3D8.ToString(); //
|
|||
|
|
}
|
|||
|
|
else if (part.LinearHexaType != FeElementTypeLinearHexa.None &&
|
|||
|
|
element is LinearHexaElement)
|
|||
|
|
{
|
|||
|
|
type = part.LinearHexaType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicTriaType != FeElementTypeParabolicTria.None &&
|
|||
|
|
element is ParabolicTriangleElement)
|
|||
|
|
{
|
|||
|
|
type = part.ParabolicTriaType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicQuadType != FeElementTypeParabolicQuad.None &&
|
|||
|
|
element is ParabolicQuadrilateralElement)
|
|||
|
|
{
|
|||
|
|
type = part.ParabolicQuadType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicTetraType != FeElementTypeParabolicTetra.None &&
|
|||
|
|
element is ParabolicTetraElement)
|
|||
|
|
{
|
|||
|
|
type = part.ParabolicTetraType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicPyramidType != FeElementTypeParabolicPyramid.None &&
|
|||
|
|
element is ParabolicPyramidElement)
|
|||
|
|
{
|
|||
|
|
type = part.ParabolicPyramidType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicWedgeType != FeElementTypeParabolicWedge.None &&
|
|||
|
|
element is ParabolicWedgeElement)
|
|||
|
|
{
|
|||
|
|
type = part.ParabolicWedgeType.ToString();
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicWedgeType == FeElementTypeParabolicWedge.None && //
|
|||
|
|
element is ParabolicWedgeElement) // converted pyramids
|
|||
|
|
{
|
|||
|
|
type = FeElementTypeParabolicWedge.C3D15.ToString(); //
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicHexaType == FeElementTypeParabolicHexa.None && //
|
|||
|
|
element is ParabolicHexaElement) // converted pyramids
|
|||
|
|
{
|
|||
|
|
type = FeElementTypeParabolicHexa.C3D20.ToString(); //
|
|||
|
|
}
|
|||
|
|
else if (part.ParabolicHexaType != FeElementTypeParabolicHexa.None &&
|
|||
|
|
element is ParabolicHexaElement)
|
|||
|
|
{
|
|||
|
|
type = part.ParabolicHexaType.ToString();
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Add element to the corresponding type
|
|||
|
|
if (elementTypes.TryGetValue(type, out elements))
|
|||
|
|
{
|
|||
|
|
elements.Add(element);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
elementTypes.Add(type, new List<FeElement>() { element });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 按照类型输出
|
|||
|
|
foreach (var typeEntry in elementTypes)
|
|||
|
|
{
|
|||
|
|
elementKeyword = new CalElement(typeEntry.Key, part.Name, typeEntry.Value, convertPyramidsTo);
|
|||
|
|
parent.AddKeyword(elementKeyword);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Additional elements
|
|||
|
|
AppendAdditionalElements(additionalElementKeywords, parent);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendAdditionalElements(List<CalElement> additionalElementKeywords, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
List<CalculixKeyword> keywords = new List<CalculixKeyword>();
|
|||
|
|
foreach (var item in additionalElementKeywords)
|
|||
|
|
{
|
|||
|
|
keywords.Add(item);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
CalAdditional calAdditionalElements = new CalAdditional("Additional elements", keywords);
|
|||
|
|
if (calAdditionalElements.GetDataString().Length > 0)
|
|||
|
|
{
|
|||
|
|
parent.AddKeyword(calAdditionalElements);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendNodeSets(FeModel model, List<FeNodeSet> additionalNodeSets, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
HashSet<string> nodeSetNames = new HashSet<string>();
|
|||
|
|
//
|
|||
|
|
foreach (var entry in model.Mesh.NodeSets) AppendNodeSet(entry.Value, parent);
|
|||
|
|
nodeSetNames.UnionWith(model.Mesh.NodeSets.Keys);
|
|||
|
|
// Get additional node set keyword
|
|||
|
|
CalAdditional calAdditionalNodeSets = GetAdditionalNodeSetsKeyword(additionalNodeSets, ref nodeSetNames);
|
|||
|
|
// Append additional node set keyword
|
|||
|
|
if (calAdditionalNodeSets.GetDataString().Length > 0) parent.AddKeyword(calAdditionalNodeSets);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendNodeSet(FeNodeSet nodeSet, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalNodeSet calNodeSet;
|
|||
|
|
if (nodeSet.Active)
|
|||
|
|
{
|
|||
|
|
calNodeSet = new CalNodeSet(nodeSet);
|
|||
|
|
parent.AddKeyword(calNodeSet);
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(nodeSet.Name));
|
|||
|
|
}
|
|||
|
|
private static CalAdditional GetAdditionalNodeSetsKeyword(List<FeNodeSet> additionalNodeSets,
|
|||
|
|
ref HashSet<string> nodeSetNames)
|
|||
|
|
{
|
|||
|
|
CalculixKeyword keyword;
|
|||
|
|
List<CalculixKeyword> keywords = new List<CalculixKeyword>();
|
|||
|
|
foreach (var nodeSet in additionalNodeSets)
|
|||
|
|
{
|
|||
|
|
if (nodeSet.Active)
|
|||
|
|
{
|
|||
|
|
keyword = new CalNodeSet(nodeSet);
|
|||
|
|
keywords.Add(keyword);
|
|||
|
|
//
|
|||
|
|
nodeSetNames.Add(nodeSet.Name);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
CalAdditional calAdditionalNodeSets = new CalAdditional("Additional node sets", keywords);
|
|||
|
|
return calAdditionalNodeSets;
|
|||
|
|
}
|
|||
|
|
private static void AppendParts(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
CalElementSet part;
|
|||
|
|
foreach (var entry in model.Mesh.Parts)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active)
|
|||
|
|
{
|
|||
|
|
part = new CalElementSet(entry.Value, model);
|
|||
|
|
parent.AddKeyword(part);
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendElementSets(FeModel model, HashSet<string> additionalElementSetNames, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
CalculixUserKeyword tmp = new CalculixUserKeyword("");
|
|||
|
|
foreach (var entry in model.Mesh.ElementSets)
|
|||
|
|
{
|
|||
|
|
if (additionalElementSetNames.Contains(entry.Key)) AppendElementSet(model, entry.Value, tmp);
|
|||
|
|
else AppendElementSet(model, entry.Value, parent);
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
CalAdditional calAdditionalElementSets = new CalAdditional("Additional element sets", tmp.Keywords);
|
|||
|
|
if (calAdditionalElementSets.GetDataString().Length > 0) parent.AddKeyword(calAdditionalElementSets);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendElementSet(FeModel model, FeElementSet elementSet, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalElementSet calElementSet;
|
|||
|
|
if (elementSet.Active)
|
|||
|
|
{
|
|||
|
|
calElementSet = new CalElementSet(elementSet, model);
|
|||
|
|
parent.AddKeyword(calElementSet);
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(elementSet.Name));
|
|||
|
|
}
|
|||
|
|
private static void AppendSurfaces(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
CalSurface calSurface;
|
|||
|
|
foreach (var entry in model.Mesh.Surfaces)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active && entry.Value.ElementFaces != null)
|
|||
|
|
{
|
|||
|
|
calSurface = new CalSurface(entry.Value, model.Properties.ModelSpace.IsTwoD());
|
|||
|
|
parent.AddKeyword(calSurface);
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendPhysicalConstants(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model != null)
|
|||
|
|
{
|
|||
|
|
CalPhysicalConstants calPhysicalConstants = new CalPhysicalConstants(model.Properties);
|
|||
|
|
if (calPhysicalConstants.GetKeywordString().Length > 0) parent.AddKeyword(calPhysicalConstants);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendCoordinateSystems(Dictionary<CoordinateSystem, HashSet<string>> coordinateSystemNodeSets,
|
|||
|
|
CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in coordinateSystemNodeSets)
|
|||
|
|
{
|
|||
|
|
foreach (var nodeSetName in entry.Value)
|
|||
|
|
{
|
|||
|
|
parent.AddKeyword(new CalTransform(entry.Key, nodeSetName));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendMaterials(FeModel model, CalculixKeyword parent,
|
|||
|
|
List<Material> additionalMaterials,
|
|||
|
|
string[] materialNames = null,
|
|||
|
|
bool addAllMaterials = false)
|
|||
|
|
{
|
|||
|
|
CalMaterial calMaterial;
|
|||
|
|
HashSet<string> activeMaterialNames;
|
|||
|
|
//
|
|||
|
|
if (addAllMaterials) activeMaterialNames = new HashSet<string>(model.Materials.Keys);
|
|||
|
|
else activeMaterialNames = MaterialNamesUsedInActiveSections(model);
|
|||
|
|
//
|
|||
|
|
List<Material> materials = model.Materials.Values.ToList();
|
|||
|
|
if (additionalMaterials != null)
|
|||
|
|
{
|
|||
|
|
foreach (var additionalMaterial in additionalMaterials)
|
|||
|
|
{
|
|||
|
|
materials.Add(additionalMaterial);
|
|||
|
|
activeMaterialNames.Add(additionalMaterial.Name);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
foreach (var material in materials)
|
|||
|
|
{
|
|||
|
|
if ((material.Active && activeMaterialNames.Contains(material.Name)) ||
|
|||
|
|
(materialNames != null && materialNames.Contains(material.Name)))
|
|||
|
|
{
|
|||
|
|
calMaterial = new CalMaterial(material);
|
|||
|
|
parent.AddKeyword(calMaterial);
|
|||
|
|
//
|
|||
|
|
foreach (var property in material.Properties)
|
|||
|
|
{
|
|||
|
|
if (property is Density de)
|
|||
|
|
{
|
|||
|
|
calMaterial.AddKeyword(new CalDensity(de, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is SlipWear sw)
|
|||
|
|
{
|
|||
|
|
if (materialNames != null) // must be here
|
|||
|
|
calMaterial.AddKeyword(new CalSlipWear(sw, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is Elastic el)
|
|||
|
|
{
|
|||
|
|
calMaterial.AddKeyword(new CalElastic(el, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is ElasticWithDensity ewd)
|
|||
|
|
{
|
|||
|
|
Density density = new Density(new double[][] { new double[] { ewd.Density.Value } });
|
|||
|
|
calMaterial.AddKeyword(new CalDensity(density, material.TemperatureDependent));
|
|||
|
|
//
|
|||
|
|
Elastic elastic = new Elastic(new double[][] { new double[] { ewd.YoungsModulus.Value,
|
|||
|
|
ewd.PoissonsRatio.Value } });
|
|||
|
|
calMaterial.AddKeyword(new CalElastic(elastic, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is Plastic pl)
|
|||
|
|
{
|
|||
|
|
calMaterial.AddKeyword(new CalPlastic(pl, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is ThermalExpansion te)
|
|||
|
|
{
|
|||
|
|
calMaterial.AddKeyword(new CalThermalExpansion(te, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is ThermalConductivity tc)
|
|||
|
|
{
|
|||
|
|
calMaterial.AddKeyword(new CalThermalConductivity(tc, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else if (property is SpecificHeat sh)
|
|||
|
|
{
|
|||
|
|
calMaterial.AddKeyword(new CalSpecificHeat(sh, material.TemperatureDependent));
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (materialNames == null) parent.AddKeyword(new CalDeactivated(material.Name));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
}
|
|||
|
|
private static void AppendSections(FeModel model, List<SectionData> additionalSectionData, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.Sections) AppendSection(entry.Value, parent);
|
|||
|
|
//
|
|||
|
|
AppendAdditionalSections(additionalSectionData, parent);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendSection(Section section, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (section.Active)
|
|||
|
|
{
|
|||
|
|
if (section is SolidSection ss) parent.AddKeyword(new CalSolidSection(ss));
|
|||
|
|
else if (section is ShellSection shs) parent.AddKeyword(new CalShellSection(shs));
|
|||
|
|
else if (section is MembraneSection ms) parent.AddKeyword(new CalMembraneSection(ms));
|
|||
|
|
else if (section is PointMassSection pms) { }
|
|||
|
|
else if (section is DistributedMassSection dms) { }
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(section.Name));
|
|||
|
|
}
|
|||
|
|
private static void AppendAdditionalSections(List<SectionData> additionalSectionData, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalculixKeyword keyword;
|
|||
|
|
List<CalculixKeyword> keywords = new List<CalculixKeyword>();
|
|||
|
|
//
|
|||
|
|
foreach (var section in additionalSectionData)
|
|||
|
|
{
|
|||
|
|
if (section.Active)
|
|||
|
|
{
|
|||
|
|
if (section is LinearSpringSectionData lssd) keyword = new CalLinearSpringSection(lssd);
|
|||
|
|
else if (section is GapSectionData gsd) keyword = new CalGapSection(gsd);
|
|||
|
|
else if (section is MassSectionData msd) keyword = new CalMassSection(msd);
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
//
|
|||
|
|
if (keyword != null) keywords.Add(keyword);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
CalAdditional calAdditionalSections = new CalAdditional("Additional sections", keywords);
|
|||
|
|
if (calAdditionalSections.GetDataString().Length > 0) parent.AddKeyword(calAdditionalSections);
|
|||
|
|
}
|
|||
|
|
private static HashSet<string> MaterialNamesUsedInActiveSections(FeModel model)
|
|||
|
|
{
|
|||
|
|
HashSet<string> materialNames = new HashSet<string>();
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.Sections)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active) materialNames.Add(entry.Value.MaterialName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return materialNames;
|
|||
|
|
}
|
|||
|
|
private static void AppendPreTensionSections(OrderedDictionary<string, List<PreTensionLoad>> preTensionLoads,
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (preTensionLoads != null)
|
|||
|
|
{
|
|||
|
|
int nodeId;
|
|||
|
|
bool atLeastOneActive;
|
|||
|
|
PreTensionLoad ptl;
|
|||
|
|
foreach (var preTensionOnSurfaceEntry in preTensionLoads)
|
|||
|
|
{
|
|||
|
|
atLeastOneActive = false;
|
|||
|
|
foreach (var item in preTensionOnSurfaceEntry.Value) atLeastOneActive |= item.Active;
|
|||
|
|
// Take the first one since all the others are the same
|
|||
|
|
ptl = preTensionOnSurfaceEntry.Value[0];
|
|||
|
|
if (atLeastOneActive)
|
|||
|
|
{
|
|||
|
|
nodeId = referencePointsNodeIds[preTensionOnSurfaceEntry.Key][0];
|
|||
|
|
CalPreTensionSection preTension;
|
|||
|
|
if (ptl.AutoComputeDirection) preTension = new CalPreTensionSection(ptl.SurfaceName, nodeId);
|
|||
|
|
else preTension = new CalPreTensionSection(ptl.SurfaceName, nodeId, ptl.X.Value, ptl.Y.Value, ptl.Z.Value);
|
|||
|
|
parent.AddKeyword(preTension);
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated("Pre-tension " + ptl.SurfaceName));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendConstraints(FeModel model, Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
List<double[]> equationParameters, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.Constraints)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is PointSpring) { } // this constraint is split into elements and a section
|
|||
|
|
else if (entry.Value is SurfaceSpring) { } // this constraint is split into point springs
|
|||
|
|
else if (entry.Value is CompressionOnly) { } // this constraint is split into GAPUNI elements and GAP section
|
|||
|
|
else if (entry.Value is RigidBody rb)
|
|||
|
|
{
|
|||
|
|
string surfaceNodeSetName = null;
|
|||
|
|
if (rb.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
surfaceNodeSetName = model.Mesh.Surfaces[rb.RegionName].NodeSetName;
|
|||
|
|
CalRigidBody calRigidBody = new CalRigidBody(rb, referencePointsNodeIds, surfaceNodeSetName);
|
|||
|
|
parent.AddKeyword(calRigidBody);
|
|||
|
|
}
|
|||
|
|
else if (entry.Value is Tie tie)
|
|||
|
|
{
|
|||
|
|
CalTie calTie = new CalTie(tie);
|
|||
|
|
parent.AddKeyword(calTie);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
// Equations
|
|||
|
|
foreach (var equationParameter in equationParameters)
|
|||
|
|
{
|
|||
|
|
parent.AddKeyword(new CalEquation(equationParameter));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendSurfaceInteractions(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalSurfaceInteraction surfaceInteraction;
|
|||
|
|
foreach (var entry in model.SurfaceInteractions)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active)
|
|||
|
|
{
|
|||
|
|
surfaceInteraction = new CalSurfaceInteraction(entry.Value);
|
|||
|
|
parent.AddKeyword(surfaceInteraction);
|
|||
|
|
//
|
|||
|
|
foreach (var property in entry.Value.Properties)
|
|||
|
|
{
|
|||
|
|
if (property is SurfaceBehavior sb) surfaceInteraction.AddKeyword(new CalSurfaceBehavior(sb));
|
|||
|
|
else if (property is Friction fr) surfaceInteraction.AddKeyword(new CalFriction(fr));
|
|||
|
|
else if (property is GapConductance gc) surfaceInteraction.AddKeyword(new CalGapConductance(gc));
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendContactPairs(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.ContactPairs)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active)
|
|||
|
|
{
|
|||
|
|
CalContactPair calContactPair = new CalContactPair(entry.Value);
|
|||
|
|
parent.AddKeyword(calContactPair);
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendAmplitudes(FeModel model, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.Amplitudes)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is Amplitude a)
|
|||
|
|
{
|
|||
|
|
CalAmplitude calAmplitude = new CalAmplitude(a);
|
|||
|
|
parent.AddKeyword(calAmplitude);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendInitialConditions(FeModel model, Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
foreach (var entry in model.InitialConditions)
|
|||
|
|
{
|
|||
|
|
if (entry.Value.Active)
|
|||
|
|
{
|
|||
|
|
if (entry.Value is InitialTemperature it)
|
|||
|
|
{
|
|||
|
|
CalInitialTemperature calInitialTemperature = new CalInitialTemperature(model, it);
|
|||
|
|
parent.AddKeyword(calInitialTemperature);
|
|||
|
|
}
|
|||
|
|
else if (entry.Value is InitialTranslationalVelocity itv)
|
|||
|
|
{
|
|||
|
|
CalInitialTranslationalVelocity calInitialVelocity =
|
|||
|
|
new CalInitialTranslationalVelocity(model, itv, referencePointsNodeIds);
|
|||
|
|
parent.AddKeyword(calInitialVelocity);
|
|||
|
|
}
|
|||
|
|
else if (entry.Value is InitialAngularVelocity iav)
|
|||
|
|
{
|
|||
|
|
CalInitialAngularVelocity calInitialVelocity =
|
|||
|
|
new CalInitialAngularVelocity(model, iav, referencePointsNodeIds);
|
|||
|
|
parent.AddKeyword(calInitialVelocity);
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
}
|
|||
|
|
else parent.AddKeyword(new CalDeactivated(entry.Value.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
private static void AppendSteps(FeModel model, List<BoundaryCondition> additionalBoundaryConditions,
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalTitle title;
|
|||
|
|
HashSet<Type> loadTypes = model.StepCollection.GetAllLoadTypes();
|
|||
|
|
//
|
|||
|
|
foreach (var step in model.StepCollection.StepsList)
|
|||
|
|
{
|
|||
|
|
if (step is InitialStep) continue;
|
|||
|
|
else if (step is BoundaryDisplacementStep boundaryDisplacementStep) continue;
|
|||
|
|
//
|
|||
|
|
title = new CalTitle(step.Name, "");
|
|||
|
|
parent.AddKeyword(title);
|
|||
|
|
//
|
|||
|
|
CalculixKeyword calStepHeader;
|
|||
|
|
if (step.Active) calStepHeader = new CalStepHeader(step);
|
|||
|
|
else calStepHeader = new CalDeactivated(step.Name);
|
|||
|
|
title.AddKeyword(calStepHeader);
|
|||
|
|
// Step type
|
|||
|
|
if (step.Active)
|
|||
|
|
{
|
|||
|
|
if (step.GetType() == typeof(StaticStep) || step is SlipWearStep)
|
|||
|
|
{
|
|||
|
|
StaticStep staticStep = step as StaticStep;
|
|||
|
|
CalStaticStep calStaticStep = new CalStaticStep(staticStep);
|
|||
|
|
calStepHeader.AddKeyword(calStaticStep);
|
|||
|
|
}
|
|||
|
|
else if (step is FrequencyStep frequencyStep)
|
|||
|
|
{
|
|||
|
|
CalFrequencyStep calFrequencyStep = new CalFrequencyStep(frequencyStep);
|
|||
|
|
calStepHeader.AddKeyword(calFrequencyStep);
|
|||
|
|
}
|
|||
|
|
else if (step is ComplexFrequencyStep complexFrequencyStep)
|
|||
|
|
{
|
|||
|
|
CalComplexFrequencyStep calComplexFrequencyStep = new CalComplexFrequencyStep(complexFrequencyStep);
|
|||
|
|
calStepHeader.AddKeyword(calComplexFrequencyStep);
|
|||
|
|
}
|
|||
|
|
else if (step is BuckleStep buckleStep)
|
|||
|
|
{
|
|||
|
|
CalBuckleStep calBuckleStep = new CalBuckleStep(buckleStep);
|
|||
|
|
calStepHeader.AddKeyword(calBuckleStep);
|
|||
|
|
}
|
|||
|
|
else if (step is ModalDynamicsStep modalStep)
|
|||
|
|
{
|
|||
|
|
CalModalDynamicsStep calModalStep = new CalModalDynamicsStep(modalStep);
|
|||
|
|
calStepHeader.AddKeyword(calModalStep);
|
|||
|
|
// Damping
|
|||
|
|
if (modalStep.ModalDamping.DampingType != ModalDampingTypeEnum.Off)
|
|||
|
|
{
|
|||
|
|
CalTitle damping = new CalTitle("Damping", "");
|
|||
|
|
CalModalDamping calModalDamping = new CalModalDamping(modalStep.ModalDamping);
|
|||
|
|
damping.AddKeyword(calModalDamping);
|
|||
|
|
calStepHeader.AddKeyword(damping);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (step is SteadyStateDynamicsStep steadyStep)
|
|||
|
|
{
|
|||
|
|
CalSteadyStateDynamicsStep calSteadyStep = new CalSteadyStateDynamicsStep(steadyStep);
|
|||
|
|
calStepHeader.AddKeyword(calSteadyStep);
|
|||
|
|
// Damping
|
|||
|
|
if (steadyStep.ModalDamping.DampingType != ModalDampingTypeEnum.Off)
|
|||
|
|
{
|
|||
|
|
CalTitle damping = new CalTitle("Damping", "");
|
|||
|
|
CalModalDamping calModalDamping = new CalModalDamping(steadyStep.ModalDamping);
|
|||
|
|
damping.AddKeyword(calModalDamping);
|
|||
|
|
calStepHeader.AddKeyword(damping);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (step.GetType() == typeof(DynamicStep))
|
|||
|
|
{
|
|||
|
|
DynamicStep dynamicStep = step as DynamicStep;
|
|||
|
|
CalDynamicStep calDynamicStep = new CalDynamicStep(dynamicStep);
|
|||
|
|
calStepHeader.AddKeyword(calDynamicStep);
|
|||
|
|
// Damping
|
|||
|
|
if (dynamicStep.Damping.DampingType != DampingTypeEnum.Off)
|
|||
|
|
{
|
|||
|
|
CalTitle damping = new CalTitle("Damping", "");
|
|||
|
|
CalDamping calDamping = new CalDamping(dynamicStep.Damping);
|
|||
|
|
damping.AddKeyword(calDamping);
|
|||
|
|
calStepHeader.AddKeyword(damping);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (step.GetType() == typeof(HeatTransferStep))
|
|||
|
|
{
|
|||
|
|
HeatTransferStep heatTransferStep = step as HeatTransferStep;
|
|||
|
|
CalHeatTransferStep calHeatTransferStep = new CalHeatTransferStep(heatTransferStep);
|
|||
|
|
calStepHeader.AddKeyword(calHeatTransferStep);
|
|||
|
|
}
|
|||
|
|
else if (step.GetType() == typeof(UncoupledTempDispStep))
|
|||
|
|
{
|
|||
|
|
UncoupledTempDispStep uncoupledTempDispStep = step as UncoupledTempDispStep;
|
|||
|
|
CalUncoupledTempDispStep calUncoupledTempDispStep = new CalUncoupledTempDispStep(uncoupledTempDispStep);
|
|||
|
|
calStepHeader.AddKeyword(calUncoupledTempDispStep);
|
|||
|
|
}
|
|||
|
|
else if (step.GetType() == typeof(CoupledTempDispStep))
|
|||
|
|
{
|
|||
|
|
CoupledTempDispStep coupledTempDispStep = step as CoupledTempDispStep;
|
|||
|
|
CalCoupledTempDispStep calCoupledTempDispStep = new CalCoupledTempDispStep(coupledTempDispStep);
|
|||
|
|
calStepHeader.AddKeyword(calCoupledTempDispStep);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
// Controls
|
|||
|
|
title = new CalTitle("Controls", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
CalculixKeyword calParameter;
|
|||
|
|
foreach (var parameter in step.StepControls.Parameters)
|
|||
|
|
{
|
|||
|
|
if (parameter is ResetStepControlParameter rscp)
|
|||
|
|
calParameter = new CalResetParameter(rscp);
|
|||
|
|
else if (parameter is TimeIncrementationStepControlParameter tiscp)
|
|||
|
|
calParameter = new CalTimeIncrementationParameter(tiscp);
|
|||
|
|
else if (parameter is FieldStepControlParameter fscp)
|
|||
|
|
calParameter = new CalFieldParameter(fscp);
|
|||
|
|
else if (parameter is ContactStepControlParameter cscp)
|
|||
|
|
calParameter = new CalContactParameter(cscp);
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
//
|
|||
|
|
title.AddKeyword(calParameter);
|
|||
|
|
}
|
|||
|
|
// Frequency
|
|||
|
|
title = new CalTitle("Output frequency", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
CalOutputFrequency calOutputFrequency = new CalOutputFrequency(step.OutputFrequency);
|
|||
|
|
if (!calOutputFrequency.IsDefault()) title.AddKeyword(calOutputFrequency);
|
|||
|
|
}
|
|||
|
|
else calStepHeader.AddKeyword(new CalDeactivated(step.GetType().ToString()));
|
|||
|
|
// Boundary conditions title
|
|||
|
|
title = new CalTitle("Boundary conditions", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
// Boundary conditions op
|
|||
|
|
if (step.Active && !(step is ModalDynamicsStep))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Boundary, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
// Boundary conditions
|
|||
|
|
foreach (var bcEntry in step.BoundaryConditions)
|
|||
|
|
{
|
|||
|
|
if (step.Active && bcEntry.Value.Active)
|
|||
|
|
AppendBoundaryCondition(model, step, bcEntry.Value, referencePointsNodeIds, title);
|
|||
|
|
else title.AddKeyword(new CalDeactivated(bcEntry.Value.Name));
|
|||
|
|
}
|
|||
|
|
// Additional boundary conditions
|
|||
|
|
AppendAdditionalBoundaryConditions(model, step, additionalBoundaryConditions, referencePointsNodeIds, title);
|
|||
|
|
// Loads title
|
|||
|
|
title = new CalTitle("Loads", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
// Load op
|
|||
|
|
if (step.Active)
|
|||
|
|
{
|
|||
|
|
if (step.IsLoadTypeSupported(typeof(CLoad)))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Cload, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
if (step.IsLoadTypeSupported(typeof(DLoad)))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Dload, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
if (step.IsLoadTypeSupported(typeof(CFlux)))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Cflux, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
if (step.IsLoadTypeSupported(typeof(DFlux)) && loadTypes.Contains(typeof(DFlux)))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Dflux, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
if (step.IsLoadTypeSupported(typeof(FilmHeatTransfer)) && loadTypes.Contains(typeof(FilmHeatTransfer)))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Film, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
if (step.IsLoadTypeSupported(typeof(RadiationHeatTransfer)) &&
|
|||
|
|
loadTypes.Contains(typeof(RadiationHeatTransfer)))
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Radiate, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
// Loads
|
|||
|
|
foreach (var loadEntry in step.Loads)
|
|||
|
|
{
|
|||
|
|
if (step.Active && loadEntry.Value.Active) AppendLoad(model, step, loadEntry.Value, referencePointsNodeIds,
|
|||
|
|
title);
|
|||
|
|
else title.AddKeyword(new CalDeactivated(loadEntry.Value.Name));
|
|||
|
|
}
|
|||
|
|
// Defined fields title
|
|||
|
|
title = new CalTitle("Defined fields", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
// Defined fields op
|
|||
|
|
if (step.Active && step.DefinedFields.Count > 0)
|
|||
|
|
{
|
|||
|
|
title.AddKeyword(new CalOpParameter(OpKeywordEnum.Temperature, OpTypeEnum.New));
|
|||
|
|
}
|
|||
|
|
// Defined fields
|
|||
|
|
foreach (var definedFieldEntry in step.DefinedFields)
|
|||
|
|
{
|
|||
|
|
if (step.Active && definedFieldEntry.Value.Active) AppendDefinedField(model, definedFieldEntry.Value, title);
|
|||
|
|
else title.AddKeyword(new CalDeactivated(definedFieldEntry.Value.Name));
|
|||
|
|
}
|
|||
|
|
// History outputs
|
|||
|
|
title = new CalTitle("History outputs", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
//
|
|||
|
|
foreach (var historyOutputEntry in step.HistoryOutputs)
|
|||
|
|
{
|
|||
|
|
if (step.Active && historyOutputEntry.Value.Active) AppendHistoryOutput(model, step,
|
|||
|
|
historyOutputEntry.Value,
|
|||
|
|
title);
|
|||
|
|
else title.AddKeyword(new CalDeactivated(historyOutputEntry.Value.Name));
|
|||
|
|
}
|
|||
|
|
// Field outputs
|
|||
|
|
title = new CalTitle("Field outputs", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
//
|
|||
|
|
foreach (var fieldOutputEntry in step.FieldOutputs)
|
|||
|
|
{
|
|||
|
|
if (step.Active && fieldOutputEntry.Value.Active)
|
|||
|
|
AppendFieldOutput(model, step, fieldOutputEntry.Value, title);
|
|||
|
|
else title.AddKeyword(new CalDeactivated(fieldOutputEntry.Value.Name));
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
title = new CalTitle("End step", "");
|
|||
|
|
calStepHeader.AddKeyword(title);
|
|||
|
|
if (step.Active)
|
|||
|
|
{
|
|||
|
|
CalEndStep endStep = new CalEndStep();
|
|||
|
|
title.AddKeyword(endStep);
|
|||
|
|
}
|
|||
|
|
else title.AddKeyword(new CalDeactivated(step.Name));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendBoundaryCondition(FeModel model, Step step, BoundaryCondition boundaryCondition,
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
ComplexLoadTypeEnum complexLoadType;
|
|||
|
|
if (boundaryCondition.Complex) complexLoadType = ComplexLoadTypeEnum.Real;
|
|||
|
|
else complexLoadType = ComplexLoadTypeEnum.None;
|
|||
|
|
//
|
|||
|
|
AppendBoundaryCondition(model, boundaryCondition, referencePointsNodeIds, complexLoadType, parent);
|
|||
|
|
// Load case=2 - Imaginary component
|
|||
|
|
if (step is SteadyStateDynamicsStep && boundaryCondition.Complex && boundaryCondition.PhaseDeg.Value != 0)
|
|||
|
|
AppendBoundaryCondition(model, boundaryCondition, referencePointsNodeIds, ComplexLoadTypeEnum.Imaginary, parent);
|
|||
|
|
}
|
|||
|
|
private static void AppendBoundaryCondition(FeModel model, BoundaryCondition boundaryCondition,
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
ComplexLoadTypeEnum complexLoadType, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
if (boundaryCondition is FixedBC fix)
|
|||
|
|
{
|
|||
|
|
string nodeSetNameOfSurface = null;
|
|||
|
|
if (fix.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
nodeSetNameOfSurface = model.Mesh.Surfaces[fix.RegionName].NodeSetName;
|
|||
|
|
CalFixedBC calFixedBC = new CalFixedBC(fix, referencePointsNodeIds, nodeSetNameOfSurface);
|
|||
|
|
parent.AddKeyword(calFixedBC);
|
|||
|
|
}
|
|||
|
|
else if (boundaryCondition is DisplacementRotation dispRot)
|
|||
|
|
{
|
|||
|
|
string nodeSetNameOfSurface = null;
|
|||
|
|
if (dispRot.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
nodeSetNameOfSurface = model.Mesh.Surfaces[dispRot.RegionName].NodeSetName;
|
|||
|
|
CalDisplacementRotation calDisplacementRotation =
|
|||
|
|
new CalDisplacementRotation(dispRot, referencePointsNodeIds, nodeSetNameOfSurface, complexLoadType);
|
|||
|
|
parent.AddKeyword(calDisplacementRotation);
|
|||
|
|
}
|
|||
|
|
else if (boundaryCondition is SubmodelBC sm)
|
|||
|
|
{
|
|||
|
|
string surfaceNodeSetName = null;
|
|||
|
|
if (sm.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
surfaceNodeSetName = model.Mesh.Surfaces[sm.RegionName].NodeSetName;
|
|||
|
|
CalSubmodelBC calSubmodelBC = new CalSubmodelBC(sm, surfaceNodeSetName);
|
|||
|
|
parent.AddKeyword(calSubmodelBC);
|
|||
|
|
}
|
|||
|
|
else if (boundaryCondition is TemperatureBC tmp)
|
|||
|
|
{
|
|||
|
|
string surfaceNodeSetName = null;
|
|||
|
|
if (tmp.RegionType == RegionTypeEnum.SurfaceName)
|
|||
|
|
surfaceNodeSetName = model.Mesh.Surfaces[tmp.RegionName].NodeSetName;
|
|||
|
|
CalTemperatureBC calTemperatureBC = new CalTemperatureBC(model, tmp, surfaceNodeSetName);
|
|||
|
|
parent.AddKeyword(calTemperatureBC);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendAdditionalBoundaryConditions(FeModel model, Step step,
|
|||
|
|
List<BoundaryCondition> additionalBoundaryConditions,
|
|||
|
|
Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
CalculixUserKeyword tmp = new CalculixUserKeyword("");
|
|||
|
|
//
|
|||
|
|
foreach (var additionalBoundaryCondition in additionalBoundaryConditions)
|
|||
|
|
{
|
|||
|
|
if (step.Active && additionalBoundaryCondition.Active)
|
|||
|
|
AppendBoundaryCondition(model, step, additionalBoundaryCondition, referencePointsNodeIds, tmp);
|
|||
|
|
else tmp.AddKeyword(new CalDeactivated(additionalBoundaryCondition.Name));
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
CalAdditional calAdditionalBoundaryConditions = new CalAdditional("Additional boundary conditions", tmp.Keywords);
|
|||
|
|
if (calAdditionalBoundaryConditions.GetDataString().Length > 0) parent.AddKeyword(calAdditionalBoundaryConditions);
|
|||
|
|
}
|
|||
|
|
private static void AppendLoad(FeModel model, Step step, Load load, Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
ComplexLoadTypeEnum complexLoadType;
|
|||
|
|
if (load.Complex) complexLoadType = ComplexLoadTypeEnum.Real;
|
|||
|
|
else complexLoadType = ComplexLoadTypeEnum.None;
|
|||
|
|
//
|
|||
|
|
AppendLoad(model, load, referencePointsNodeIds, complexLoadType, parent);
|
|||
|
|
// Load case=2 - Imaginary component
|
|||
|
|
if (step is SteadyStateDynamicsStep && load.Complex && load.PhaseDeg.Value != 0)
|
|||
|
|
AppendLoad(model, load, referencePointsNodeIds, ComplexLoadTypeEnum.Imaginary, parent);
|
|||
|
|
}
|
|||
|
|
private static void AppendLoad(FeModel model, Load load, Dictionary<string, int[]> referencePointsNodeIds,
|
|||
|
|
ComplexLoadTypeEnum complexLoadType, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (model.Mesh != null)
|
|||
|
|
{
|
|||
|
|
if (load is CLoad cl)
|
|||
|
|
{
|
|||
|
|
CalCLoad cLoad = new CalCLoad(cl, referencePointsNodeIds, complexLoadType);
|
|||
|
|
parent.AddKeyword(cLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is MomentLoad ml)
|
|||
|
|
{
|
|||
|
|
CalMomentLoad mLoad = new CalMomentLoad(ml, referencePointsNodeIds, complexLoadType);
|
|||
|
|
parent.AddKeyword(mLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is DLoad dl)
|
|||
|
|
{
|
|||
|
|
if (dl.DistributionName == Distribution.DefaultDistributionName)
|
|||
|
|
{
|
|||
|
|
CalDLoad dLoad = new CalDLoad(dl, model.Mesh.Surfaces[dl.RegionName], complexLoadType);
|
|||
|
|
parent.AddKeyword(dLoad);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
CalVariablePressureLoad vpLoad = new CalVariablePressureLoad(model, dl, complexLoadType);
|
|||
|
|
parent.AddKeyword(vpLoad);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (load is HydrostaticPressure hpl)
|
|||
|
|
{
|
|||
|
|
CalVariablePressureLoad vpLoad = new CalVariablePressureLoad(model, hpl, complexLoadType);
|
|||
|
|
parent.AddKeyword(vpLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is ImportedPressure ipl)
|
|||
|
|
{
|
|||
|
|
CalImportedPressureLoad ipLoad = new CalImportedPressureLoad(model, ipl, complexLoadType);
|
|||
|
|
parent.AddKeyword(ipLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is STLoad stl)
|
|||
|
|
{
|
|||
|
|
CalSTLoad stLoad = new CalSTLoad(model, stl, complexLoadType);
|
|||
|
|
parent.AddKeyword(stLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is ImportedSTLoad istl)
|
|||
|
|
{
|
|||
|
|
CalImportedSTLoad istLoad = new CalImportedSTLoad(model, istl, complexLoadType);
|
|||
|
|
parent.AddKeyword(istLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is ShellEdgeLoad sel)
|
|||
|
|
{
|
|||
|
|
CalShellEdgeLoad seLoad = new CalShellEdgeLoad(sel, model.Mesh.Surfaces[sel.SurfaceName], complexLoadType);
|
|||
|
|
parent.AddKeyword(seLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is GravityLoad gl)
|
|||
|
|
{
|
|||
|
|
MassSection massSection;
|
|||
|
|
GravityLoad glClone = gl.DeepClone();
|
|||
|
|
if (gl.RegionType == RegionTypeEnum.MassSection)
|
|||
|
|
{
|
|||
|
|
massSection = (MassSection)model.Sections[glClone.RegionName];
|
|||
|
|
glClone.RegionName = massSection.ElementSetName;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
CalGravityLoad gLoad = new CalGravityLoad(glClone, complexLoadType);
|
|||
|
|
parent.AddKeyword(gLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is CentrifLoad cfl)
|
|||
|
|
{
|
|||
|
|
MassSection massSection;
|
|||
|
|
CentrifLoad cflClone = cfl.DeepClone();
|
|||
|
|
if (cfl.RegionType == RegionTypeEnum.MassSection)
|
|||
|
|
{
|
|||
|
|
massSection = (MassSection)model.Sections[cflClone.RegionName];
|
|||
|
|
cflClone.RegionName = massSection.ElementSetName;
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
CalCentrifLoad cLoad = new CalCentrifLoad(cflClone, complexLoadType);
|
|||
|
|
parent.AddKeyword(cLoad);
|
|||
|
|
}
|
|||
|
|
else if (load is PreTensionLoad ptl)
|
|||
|
|
{
|
|||
|
|
string name = ptl.SurfaceName;
|
|||
|
|
if (!ptl.AutoComputeDirection) name += "_" + ptl.X.ToString() + ptl.Y.ToString() + ptl.Z.ToString();
|
|||
|
|
//
|
|||
|
|
CalculixKeyword calKey;
|
|||
|
|
if (ptl.Type == PreTensionLoadType.Force)
|
|||
|
|
{
|
|||
|
|
int nodeId = referencePointsNodeIds[name][0];
|
|||
|
|
CLoad cLoad = new CLoad(ptl.Name, nodeId, ptl.GetMagnitudeValue(), 0, 0, ptl.TwoD,
|
|||
|
|
ptl.Complex, ptl.PhaseDeg.Value);
|
|||
|
|
cLoad.AmplitudeName = ptl.AmplitudeName;
|
|||
|
|
calKey = new CalCLoad(cLoad, referencePointsNodeIds, complexLoadType);
|
|||
|
|
}
|
|||
|
|
else if (ptl.Type == PreTensionLoadType.Displacement)
|
|||
|
|
{
|
|||
|
|
DisplacementRotation dr = new DisplacementRotation(ptl.Name, name, RegionTypeEnum.ReferencePointName,
|
|||
|
|
ptl.TwoD, ptl.Complex, ptl.PhaseDeg.Value);
|
|||
|
|
dr.U1.SetEquationFromValue(ptl.GetMagnitudeValue());
|
|||
|
|
dr.AmplitudeName = ptl.AmplitudeName;
|
|||
|
|
calKey = new CalDisplacementRotation(dr, referencePointsNodeIds, null, complexLoadType);
|
|||
|
|
}
|
|||
|
|
else throw new NotSupportedException();
|
|||
|
|
//
|
|||
|
|
parent.AddKeyword(calKey);
|
|||
|
|
}
|
|||
|
|
// Thermo
|
|||
|
|
else if (load is CFlux cf)
|
|||
|
|
{
|
|||
|
|
CalCFlux cFlux = new CalCFlux(cf);
|
|||
|
|
parent.AddKeyword(cFlux);
|
|||
|
|
}
|
|||
|
|
else if (load is DFlux df)
|
|||
|
|
{
|
|||
|
|
CalDFlux dFlux = new CalDFlux(df);
|
|||
|
|
parent.AddKeyword(dFlux);
|
|||
|
|
}
|
|||
|
|
else if (load is BodyFlux bf)
|
|||
|
|
{
|
|||
|
|
CalBodyFlux bFlux = new CalBodyFlux(bf);
|
|||
|
|
parent.AddKeyword(bFlux);
|
|||
|
|
}
|
|||
|
|
else if (load is FilmHeatTransfer fht)
|
|||
|
|
{
|
|||
|
|
CalFilmHeatTransfer filmHeatTransfer = new CalFilmHeatTransfer(fht, model.Mesh.Surfaces[fht.SurfaceName]);
|
|||
|
|
parent.AddKeyword(filmHeatTransfer);
|
|||
|
|
}
|
|||
|
|
else if (load is RadiationHeatTransfer rht)
|
|||
|
|
{
|
|||
|
|
CalRadiationHeatTransfer radiationHeatTransfer =
|
|||
|
|
new CalRadiationHeatTransfer(rht, model.Mesh.Surfaces[rht.SurfaceName]);
|
|||
|
|
parent.AddKeyword(radiationHeatTransfer);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
private static void AppendDefinedField(FeModel model, DefinedField definedField, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (definedField is DefinedTemperature dt)
|
|||
|
|
{
|
|||
|
|
CalDefinedTemperature definedTemperature = new CalDefinedTemperature(model, dt);
|
|||
|
|
parent.AddKeyword(definedTemperature);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
private static void AppendHistoryOutput(FeModel model, Step step, HistoryOutput historyOutput,
|
|||
|
|
CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (historyOutput is NodalHistoryOutput nho)
|
|||
|
|
{
|
|||
|
|
CalNodePrint nodePrint;
|
|||
|
|
if (nho.RegionType == RegionTypeEnum.ReferencePointName)
|
|||
|
|
{
|
|||
|
|
FeReferencePoint rp = model.Mesh.ReferencePoints[nho.RegionName];
|
|||
|
|
nodePrint = new CalNodePrint(nho, rp.RefNodeSetName, step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(nodePrint);
|
|||
|
|
nodePrint = new CalNodePrint(nho, rp.RotNodeSetName, step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(nodePrint);
|
|||
|
|
}
|
|||
|
|
else
|
|||
|
|
{
|
|||
|
|
nodePrint = new CalNodePrint(model, nho, step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(nodePrint);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (historyOutput is ElementHistoryOutput eho)
|
|||
|
|
{
|
|||
|
|
CalElPrint elPrint = new CalElPrint(eho, step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(elPrint);
|
|||
|
|
}
|
|||
|
|
else if (historyOutput is ContactHistoryOutput cho)
|
|||
|
|
{
|
|||
|
|
ContactPair cp = model.ContactPairs[cho.RegionName];
|
|||
|
|
|
|||
|
|
CalContactPrint contactPrint = new CalContactPrint(cho, cp.MasterRegionName, cp.SlaveRegionName,
|
|||
|
|
model.Mesh.Surfaces[cp.MasterRegionName].NodeSetName,
|
|||
|
|
model.Mesh.Surfaces[cp.SlaveRegionName].NodeSetName,
|
|||
|
|
step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(contactPrint);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
private static void AppendFieldOutput(FeModel model, Step step, FieldOutput fieldOutput, CalculixKeyword parent)
|
|||
|
|
{
|
|||
|
|
if (fieldOutput is NodalFieldOutput nfo)
|
|||
|
|
{
|
|||
|
|
CalNodeFile nodeFile = new CalNodeFile(nfo, step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(nodeFile);
|
|||
|
|
}
|
|||
|
|
else if (fieldOutput is ElementFieldOutput efo)
|
|||
|
|
{
|
|||
|
|
CalElFile elFile = new CalElFile(efo, step.OutputFrequency);
|
|||
|
|
parent.AddKeyword(elFile);
|
|||
|
|
}
|
|||
|
|
else if (fieldOutput is ContactFieldOutput cfo)
|
|||
|
|
{
|
|||
|
|
CalContactFile conFile = new CalContactFile(cfo);
|
|||
|
|
parent.AddKeyword(conFile);
|
|||
|
|
}
|
|||
|
|
else throw new NotImplementedException();
|
|||
|
|
}
|
|||
|
|
//
|
|||
|
|
static void AppendTitle(StringBuilder sb, string title)
|
|||
|
|
{
|
|||
|
|
sb.AppendLine("************************************************************");
|
|||
|
|
sb.AppendLine("** " + title);
|
|||
|
|
sb.AppendLine("************************************************************");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|