SAM 数据模型、Part 与 Mesh API / SAM Data Models, Parts, and Mesh APIs
本篇解释
mdb.models['Model-1'].parts['Part-1']背后的 C++ 数据结构,以及插件如何安全读取 Part、Feature、Node 和 Element。
1. 数据层次
basBasis
`-- basMdb
`-- basModelMap
`-- basNewModel
+-- ptoKPartRepository
| `-- ptoKPart
| `-- ftrFeatureList
| `-- bmeMesh / omeMesh
| +-- bmeNodeData
| +-- bmeElementData
| `-- bmeElementClass
+-- Materials / Sections
+-- Steps / Loads / BCs
+-- Interactions
`-- Assembly / Sketch / Output RequestsPython 中的 mdb 是该底层模型通过 Python 接口包装后的用户视图,不代表底层由 Python 字典直接保存。
2. 数据库根对象
2.1 basBasis
进程级数据库入口/单例。
static basBasis* Instance();
static void Finalize();
const basMdb& Fetch();
const basMdb& GetMdb();
void Replace(const basMdb& root);
void UncheckedReplace(const basMdb& root);
void NewMdb();
void OpenMdb(const QString& fileName);
void CloseMdb();
void OpenDdb(const QString& fileName);
void SaveDdb();
void SaveDdbAs(const QString& fileName);
void CloseDdb();
void CleanDdbCows();读取当前数据库通常从 basBasis::Instance()->GetMdb() 开始。
2.2 basMdb
当前 MDB 根对象。
basModelMap& GetModels();
const basModelMap& ConstGetModels() const;
void SetModels(const basModelMap&);
mdlRepository& GetJobs();
const mdlRepository& ConstGetJobs() const;
basUserData& GetUserData();
const basUserData& ConstGetUserData() const;
double ConstGetModCount() const;
void UpdateModCount();
int GetLastModelID() const;
void IncrementModelIDCounter();2.3 basModelMap
由宏生成:
MDLIDREPOSITORY_DECL(QString, basNewModel, basModelMap);逻辑含义是 QString 模型名 -> basNewModel。它基于 SAM 仓库模板,不应直接假定为 std::map。
3. Model
3.1 basNewModel
表示单个分析模型,内部以 Repository/Extension 保存不同业务对象。
mdlRepository& GetPart();
const mdlRepository& ConstGetPart() const;
mdlRepository& GetSketch();
mdlRepository& GetMaterials();
mdlRepository& GetSections();
mdlRepository& GetSteps();
mdlRepository& GetLoads();
mdlRepository& GetBCs();
mdlRepository& GetInteractions();
mdlRepository& GetInteractionProperties();
mdlRepository& GetFieldOutputs();
mdlRepository& GetHistoryOutputs();
mdlExtension& GetAssy();
const mdlExtension& ConstGetAssy() const;
void Rewire(const QString& modelName);
void RewireMissingExtensions(const QString& modelName);
void AssertValid() const;主要子仓库包括:
- Part、Sketch、Assembly;
- Material、Section、Profile;
- Step、Load、Boundary Condition;
- Interaction、Interaction Property;
- Field/History Output Request;
- Constraint、Connector、Amplitude;
- Remeshing Rule、Analytical Field 等。
读取时优先使用 ConstGet*(),只有明确修改模型且理解 SAM 的 COW、回调和再生机制时才使用可写接口。
4. Part 与 Feature
4.1 ptoKPartRepository
由仓库宏生成,逻辑映射为:
QString Part 名 -> ptoKPartptoKPartReposRewireCB() 用于模型或 Part 重命名后的引用重连。
4.2 ptoKPart
Part 的核心 C++ 对象,继承 ftrPrimaryObject。
ptoKPart(bdoTheory theory, const QString& name);
ftrPrimaryObject* Copy() const;
ptoKPart* CopyCompress(const QString& newName) const;
bdoSpace GetSpace() const;
bdoAnalysis GetAnalysis() const;
bdoTheory GetTheory() const;
bool HasTwistDof() const;
void SetAnalysis(bdoAnalysis);
void SetSpace(bdoSpace);
void SetTwistDof(bool);
void SetStartNodeLabel(uint);
void SetStartElemLabel(uint);
bool Regenerate(basNewModel&);
void Restore();
void Backup();
void UpdateScene();
bool IsLocked() const;
bool Lock();
bool UnLock(...);
bool IsValid() const;
void SetName(const QString&);
QString GetColor() const;Part 不只是节点和单元数组,还包含 Feature 历史、属性分配、几何、网格、锁定和再生状态。
4.3 ftrFeatureList
管理 Part 的 Feature 历史和求值结果。
int NmrFeatures() const;
cowListInt GetIds() const;
cowListInt GetUserVisibleIds() const;
ftrFeature* Get(int featureId) const;
const ftrFeature* ConstGet(int featureId) const;
bool FeatureExists(const QString&) const;
bool IsOutOfDate() const;
bool Suppress(int id, bool user = true);
bool Resume(int id);
bool Delete(int featureId);
bool Regenerate(const cowListInt& featureIds);
bool RegenerateFeatureAndAppend(ftrFeature*);
bool MeshExists(uint instanceId) const;
const bmeMesh* ConstGetMesh(uint instanceId) const;
bmeMesh* GetMesh(uint instanceId);
bool DeleteMesh(uint instanceId);
gslBBox GetBBox(...) const;
void Backup();
void Restore();修改 Feature 或 Mesh 后需要考虑再生、时间戳、有效性和场景更新。
5. Mesh
5.1 bmeMesh
基础有限元网格对象。
bmeMesh(bmeMeshType type);
virtual bmeMesh* VirtualCopy() const;
bool HasOrphanElements() const;
bool HasNativeElements() const;
bool HasOrphanNodes() const;
bool AllElementsOrphan() const;
bool HasNativeNodes() const;
uint NumNodes() const;
uint NumElements() const;
uint Dim() const;
uint MeshNodeIndex(int userNodeLabel) const;
uint NumElementClasses() const;
bmeElementClass& ElemClass(uint classIndex);
int GetMeshElemIndexFromLabel(int userElementLabel) const;
uint GetClassIndex(uint meshElementIndex) const;
uint GetClassElemIndex(uint meshElementIndex) const;
gslBBox GetBBox() const;
void ApplyTransform(const gslMatrix&);
void InvalidateMeshData();必须区分:
- User Node/Element Label:用户界面看到的编号;
- Mesh Index:内部连续索引;
- Class Index:单元类型组索引;
- Class Element Index:某个单元类型组内部的索引。
5.2 bmeNodeData
节点坐标和标签容器。
uint NumNodes() const;
bool HasUserNodeLabel() const;
int GetUserNodeLabel(uint meshNodeIndex) const;
uint GetMeshNodeIndex(int userNodeLabel) const;
void GetUserNodeLabels(cowListInt&) const;
int GetMinUserNodeLabel() const;
int GetMaxUserNodeLabel() const;
const utiCoordCont3D& CoordContainer() const;
bool DeleteNode(uint meshNodeIndex);
void AppendNodes(const bmeNodeData&);
void AppendNodes(const utiCoordCont3D&);
bool SetUserNodeLabel(uint index, int label);
bool SetUserNodeLabels(const cowListInt&);
void SetDimension(uint);
gslBBox GetBBox() const;5.3 bmeElementData
管理单元类、连接关系和用户标签。
const bmeElementClass& GetClass(uint classIndex) const;
bmeElementClass& GetClassToModify(uint classIndex);
const bmeElementClass& GetElemClass(uint meshElementIndex) const;
int GetMeshElemIndexFromLabel(uint userLabel) const;
uint GetClassIndex(uint meshElementIndex) const;
uint GetClassElemIndex(uint meshElementIndex) const;
bool SetElementType(uint classIndex, const QString&);
bool AddElements(uint classIndex,
const cowListInt& connectivity);
bool AddElementClass(bmeElementClass*);
bool RemoveElements(const bmeFEMElemList&);
void UpdateConnectivity(const int* nodeMap);
int GetUserElementLabel(uint meshElementIndex) const;
bool SetUserElementLabel(uint meshElementIndex, int label);
bool SetUserElementLabels(const cowListInt&);5.4 bmeElementClass
表示同一单元类型的一组单元。
virtual bmeElementClass* Copy() const;
int NumNodesPerElem() const;
void SetElemType(const QString&);
const bmeElemCtrlParams& GetElemControlParams() const;
bmeElemCtrlParams& ElemControlParams();
void SetElemControlParams(const bmeElemCtrlParams&);
void InvertElementsConnectivities();
void InvertElementConnectivity(int elementIndex);
void RemoveElement(int classElementNumber);
void RemoveElements(int count, int* classElementNumbers);5.5 omeMesh
孤立网格实现:
omeMesh();
omeMesh(const omeMesh&, uint instanceId);
omeMesh(const bmeMesh&, uint instanceId);
virtual bmeMesh* VirtualCopy() const;
virtual void ResetOrphanElements();6. SAMReMesh
高层网格处理辅助类。
SAMReMesh(ftrFeatureList*);
void GetAllNodesData(bmeNodeData&, vector<str_NODE>&);
void GetAllNodesID(bmeNodeData&, cowListInt&);
void GetAllElementsData(bmeElementData&,
vector<str_ELEMENT>&);
bool GetNodeIDAndCoordinates(bmeNodeData&,
int label,
str_NODE&);
void GetNodesCoordinates(...);
bool addNewNodes(...);
bool deleteOldElement(const vector<int>&);
bool createNewNodes(const cowList<str_NODE>&);
bool modifyElemConnection(const cowList<str_ELEMENT>&);
bool detachMesh(...);
static bool getFreeEdge(...);
double calculateTriangleArea(...);
bool calculateQuadrilateralCentroid(...);它适合工程网格处理,但不能绕开以下规则:
- 用户 Label 与内部 Index 的转换;
- Element Class 的连接关系;
- Feature 再生和 Part 有效性;
- 模型修改通知和场景更新;
- 修改失败时的恢复策略。
7. 数据修改的推荐流程
取得当前 basMdb
-> 定位 basNewModel
-> 定位 ptoKPart
-> 检查锁定、有效性和网格存在性
-> Backup/建立可恢复状态
-> 修改 Feature 或 Mesh
-> 更新标签、连接和缓存
-> Regenerate/AssertValid
-> UpdateScene
-> 失败时 Restore具体项目仍应优先通过已验证的 SAM Kernel 命令修改模型,因为直接写底层 C++ 对象可能绕过 Journal、Replay、Undo 和 GUI 通知。
8. Python 数据视图
典型 Python 层次:
mdb
mdb.models
mdb.models['Model-1']
mdb.models['Model-1'].parts
mdb.models['Model-1'].parts['Part-1']
part.nodes
part.elements
part.sets如果:
print(mdb.models['Model-1'].parts.keys())返回空列表,说明 Model 存在但没有 Part;此时读取节点、单元或面积当然不会有结果。
9. 常见错误
- 把节点 Label 当作内部数组索引;
- 修改连接后未更新逆连接和缓存;
- 只改临时 Mesh 副本,没有写回 Feature/Part;
- 修改模型但未触发再生和 Scene 更新;
- 在没有 Part 或没有 Mesh 时直接解引用;
- 跨 DLL/PYD 长期保存已经失效的 SAM 对象指针;
- 在只读操作中错误取得可写 COW 对象,造成无意修改。