From 8b7c759c08283a6f5323846d520b02a8144d024a Mon Sep 17 00:00:00 2001 From: Vasyl Skorych Date: Tue, 12 May 2026 14:07:28 +0200 Subject: [PATCH 1/6] feat: Add PBC_VELOCITY script command - closes #48 --- Modules/ScriptInterface/ConsoleSimulator.cpp | 15 ++++++++++++--- Modules/ScriptInterface/ScriptAnalyzer.cpp | 6 ++++-- Modules/ScriptInterface/ScriptJob.h | 6 ++++-- Modules/ScriptInterface/ScriptRunner.cpp | 11 +++++++++-- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/Modules/ScriptInterface/ConsoleSimulator.cpp b/Modules/ScriptInterface/ConsoleSimulator.cpp index 2582dc0..13c4123 100644 --- a/Modules/ScriptInterface/ConsoleSimulator.cpp +++ b/Modules/ScriptInterface/ConsoleSimulator.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2023, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2023, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ConsoleSimulator.h" @@ -81,6 +82,12 @@ void CConsoleSimulator::SetupSystemStructure() const pbc.SetDomain(m_job.pbcDomain.coordBeg, m_job.pbcDomain.coordEnd); m_systemStructure.SetPBC(pbc); } + if (!m_job.pbcVelocity.IsInf()) + { + SPBC pbc = m_systemStructure.GetPBC(); + pbc.vVel = m_job.pbcVelocity; + m_systemStructure.SetPBC(pbc); + } if (m_job.resetBonds.ToBool()) m_systemStructure.ResetInitBondLength(); const auto GetGeometryPtr = [&](const SJob::SGeometryMotionInterval& _motion) -> CRealGeometry* @@ -324,6 +331,8 @@ void CConsoleSimulator::PrintSimulationInfo() if (pbc.bX) PrintFormatted(" Periodic boundary domain X [m]", pbc.initDomain.coordBeg.x, "to", pbc.initDomain.coordEnd.x); if (pbc.bY) PrintFormatted(" Periodic boundary domain Y [m]", pbc.initDomain.coordBeg.y, "to", pbc.initDomain.coordEnd.y); if (pbc.bZ) PrintFormatted(" Periodic boundary domain Z [m]", pbc.initDomain.coordBeg.z, "to", pbc.initDomain.coordEnd.z); + if (!pbc.vVel.IsZero()) + PrintFormatted(" Periodic boundary velocity (X:Y:Z) [m/s]", pbc.vVel.x, ":", pbc.vVel.y, ":", pbc.vVel.z); } PrintFormatted("External acceleration (X:Y:Z) [m/s^2]", extAccel.x, ":", extAccel.y, ":", extAccel.z); PrintFormatted("Simulation domain X [m]", simDomain.coordBeg.x, "to", simDomain.coordEnd.x); @@ -396,7 +405,7 @@ template void CConsoleSimulator::PrintFormatted(const std::string& _message, Args... args) const { // length of the message - static int length = 38; + static int length = 42; // justify text m_out.setf(std::ios::left, std::ios::adjustfield); // print the message diff --git a/Modules/ScriptInterface/ScriptAnalyzer.cpp b/Modules/ScriptInterface/ScriptAnalyzer.cpp index 95a92a5..d7b373b 100644 --- a/Modules/ScriptInterface/ScriptAnalyzer.cpp +++ b/Modules/ScriptInterface/ScriptAnalyzer.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ScriptAnalyzer.h" @@ -117,6 +118,7 @@ void CScriptAnalyzer::ProcessLine(const std::string& _line, std::ostream& _out / else if (key == "SIMULATION_DOMAIN") ss >> m_jobs.back().simulationDomain; else if (key == "PBC_FLAGS") ss >> m_jobs.back().pbcFlags[0] >> m_jobs.back().pbcFlags[1] >> m_jobs.back().pbcFlags[2]; else if (key == "PBC_DOMAIN") ss >> m_jobs.back().pbcDomain; + else if (key == "PBC_VELOCITY") ss >> m_jobs.back().pbcVelocity; else if (key == "SELECTIVE_SAVING_P") { m_jobs.back().selectiveSavingFlag = true; ss >> m_jobs.back().selectiveSavingFlags.bAngVelocity >> m_jobs.back().selectiveSavingFlags.bCoordinates >> m_jobs.back().selectiveSavingFlags.bForce >> m_jobs.back().selectiveSavingFlags.bQuaternion >> m_jobs.back().selectiveSavingFlags.bVelocity >> m_jobs.back().selectiveSavingFlags.bTensor >> m_jobs.back().selectiveSavingFlags.bTemperature; } else if (key == "SELECTIVE_SAVING_SB") { m_jobs.back().selectiveSavingFlag = true; ss >> m_jobs.back().selectiveSavingFlags.bSBForce >> m_jobs.back().selectiveSavingFlags.bSBTangOverlap >> m_jobs.back().selectiveSavingFlags.bSBTotTorque; } else if (key == "SELECTIVE_SAVING_LB") { m_jobs.back().selectiveSavingFlag = true; ss >> m_jobs.back().selectiveSavingFlags.bLBForce; } diff --git a/Modules/ScriptInterface/ScriptJob.h b/Modules/ScriptInterface/ScriptJob.h index 76d6514..7a7899b 100644 --- a/Modules/ScriptInterface/ScriptJob.h +++ b/Modules/ScriptInterface/ScriptJob.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -124,6 +125,7 @@ struct SJob SVolumeType simulationDomain{ CVector3{ std::numeric_limits::infinity() }, CVector3{ std::numeric_limits::infinity() } }; std::array pbcFlags; // is it enabled in X,Y,Z directions SVolumeType pbcDomain{ CVector3{ std::numeric_limits::infinity() }, CVector3{ std::numeric_limits::infinity() } }; + CVector3 pbcVelocity{ std::numeric_limits::infinity() }; // velocity of PBC boundaries // materials std::vector materialProperties; diff --git a/Modules/ScriptInterface/ScriptRunner.cpp b/Modules/ScriptInterface/ScriptRunner.cpp index 00c7c3d..cf5eb69 100644 --- a/Modules/ScriptInterface/ScriptRunner.cpp +++ b/Modules/ScriptInterface/ScriptRunner.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ScriptRunner.h" @@ -83,6 +84,12 @@ void CScriptRunner::GeneratePackage() pbc.SetDomain(m_job.pbcDomain.coordBeg, m_job.pbcDomain.coordEnd); m_systemStructure.SetPBC(pbc); } + if (!m_job.pbcVelocity.IsInf()) + { + SPBC pbc = m_systemStructure.GetPBC(); + pbc.vVel = m_job.pbcVelocity; + m_systemStructure.SetPBC(pbc); + } // setup generators CPackageGenerator generator; From 538e052b8a370db322ae2d560a56d2155cc3a282 Mon Sep 17 00:00:00 2001 From: Vasyl Skorych Date: Tue, 12 May 2026 14:47:14 +0200 Subject: [PATCH 2/6] feat: Include PBC velocity in text scene info - refs #48 --- Modules/SimResultsStorage/ExportAsText.cpp | 7 ++++--- Modules/SimResultsStorage/ImportFromText.cpp | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Modules/SimResultsStorage/ExportAsText.cpp b/Modules/SimResultsStorage/ExportAsText.cpp index eb65da5..4b48419 100644 --- a/Modules/SimResultsStorage/ExportAsText.cpp +++ b/Modules/SimResultsStorage/ExportAsText.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2022, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2022, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ExportAsText.h" @@ -387,7 +388,7 @@ void CExportAsText::WriteSceneData() SetStatus("Writing scene data to result file"); if (m_selectors.sceneInfo.domain ) WriteLine(ETXTCommands::SIMULATION_DOMAIN , m_systemStructure->GetSimulationDomain()); - if (m_selectors.sceneInfo.pbc ) WriteLine(ETXTCommands::PERIODIC_BOUNDARIES, m_systemStructure->GetPBC().bEnabled, m_systemStructure->GetPBC().bX, m_systemStructure->GetPBC().bY, m_systemStructure->GetPBC().bZ, m_systemStructure->GetPBC().initDomain); + if (m_selectors.sceneInfo.pbc ) WriteLine(ETXTCommands::PERIODIC_BOUNDARIES, m_systemStructure->GetPBC().bEnabled, m_systemStructure->GetPBC().bX, m_systemStructure->GetPBC().bY, m_systemStructure->GetPBC().bZ, m_systemStructure->GetPBC().initDomain, m_systemStructure->GetPBC().vVel); if (m_selectors.sceneInfo.anisotropy ) WriteLine(ETXTCommands::ANISOTROPY , m_systemStructure->IsAnisotropyEnabled()); if (m_selectors.sceneInfo.contactRadius) WriteLine(ETXTCommands::CONTACT_RADIUS , m_systemStructure->IsContactRadiusEnabled()); } diff --git a/Modules/SimResultsStorage/ImportFromText.cpp b/Modules/SimResultsStorage/ImportFromText.cpp index 34f54c1..707768d 100644 --- a/Modules/SimResultsStorage/ImportFromText.cpp +++ b/Modules/SimResultsStorage/ImportFromText.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ImportFromText.h" @@ -222,9 +223,9 @@ CImportFromText::SImportFileInfo CImportFromText::Import(const std::string& _fil { CVector3 domainBeg, domainEnd; SPBC tempPBC; - tempStream >> tempPBC.bEnabled >> tempPBC.bX >> tempPBC.bY >> tempPBC.bZ >> domainBeg >> domainEnd; + tempPBC.vVel.Init(0); // default for legacy text files without velocity + tempStream >> tempPBC.bEnabled >> tempPBC.bX >> tempPBC.bY >> tempPBC.bZ >> domainBeg >> domainEnd >> tempPBC.vVel; tempPBC.SetDomain(domainBeg, domainEnd); - tempPBC.vVel.Init(0); m_pSystemStructure->SetPBC(tempPBC); break; } From 1ddf23c8c0e57270fcc1ba1215f604a2b22a5f37 Mon Sep 17 00:00:00 2001 From: Vasyl Skorych Date: Wed, 20 May 2026 16:12:53 +0200 Subject: [PATCH 3/6] feat: Add dynamic generators to text format - closes #44 --- Modules/GeneralSources/MUSENDefinitions.h | 6 ++- .../ObjectsGenerator/GenerationManager.cpp | 11 ++-- Modules/ObjectsGenerator/GenerationManager.h | 11 ++-- Modules/ObjectsGenerator/ObjectsGenerator.cpp | 53 ++++++++++++++++++- Modules/ObjectsGenerator/ObjectsGenerator.h | 20 ++++++- Modules/ScriptInterface/ScriptAnalyzer.cpp | 1 + Modules/ScriptInterface/ScriptRunner.cpp | 11 +++- Modules/SimResultsStorage/ExportAsText.cpp | 9 +++- Modules/SimResultsStorage/ExportAsText.h | 19 ++++--- Modules/SimResultsStorage/ImportFromText.cpp | 10 +++- Modules/SimResultsStorage/ImportFromText.h | 9 ++-- QTDialogs/MUSENMainWindow/ExportAsTextTab.cpp | 12 +++-- QTDialogs/MUSENMainWindow/ExportAsTextTab.h | 8 +-- QTDialogs/MUSENMainWindow/ExportAsTextTab.ui | 14 ++++- QTDialogs/MUSENMainWindow/MUSENMainWindow.cpp | 4 +- .../ObjectsGeneratorTab.cpp | 7 +-- 16 files changed, 163 insertions(+), 42 deletions(-) diff --git a/Modules/GeneralSources/MUSENDefinitions.h b/Modules/GeneralSources/MUSENDefinitions.h index 72a8aaf..159350f 100644 --- a/Modules/GeneralSources/MUSENDefinitions.h +++ b/Modules/GeneralSources/MUSENDefinitions.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -70,6 +71,7 @@ enum class ETXTCommands : unsigned OBJECT_TOT_TORQUE = 43, OBJECT_PLANE_COORD = 44, OBJECT_TANG_OVERLAP = 45, + DYNAMIC_GENERATOR = 46, }; // ********* physical constants diff --git a/Modules/ObjectsGenerator/GenerationManager.cpp b/Modules/ObjectsGenerator/GenerationManager.cpp index 3567f82..fe08ebe 100644 --- a/Modules/ObjectsGenerator/GenerationManager.cpp +++ b/Modules/ObjectsGenerator/GenerationManager.cpp @@ -1,3 +1,8 @@ +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. + See LICENSE file for license and warranty information. */ + #include "GenerationManager.h" CGenerationManager::CGenerationManager() : CMusenComponent() @@ -37,10 +42,11 @@ std::vector CGenerationManager::GetGenerators() const return res; } -void CGenerationManager::CreateNewGenerator() +CObjectsGenerator* CGenerationManager::AddGenerator() { m_vGenerators.push_back(new CObjectsGenerator(m_pAgglomDB, &m_pSystemStructure->m_MaterialDatabase)); m_vGenerators.back()->m_sName = "ObjectsGenerator " + std::to_string(m_vGenerators.size()); + return m_vGenerators.back(); } void CGenerationManager::DeleteGenerator( size_t _nIndex ) @@ -57,8 +63,7 @@ void CGenerationManager::LoadConfiguration() for (int i = 0; i < protoMessage.objects_generator().generators_size(); ++i) { const ProtoObjectsGenerator& protoGen = protoMessage.objects_generator().generators(i); - CreateNewGenerator(); - CObjectsGenerator* gen = m_vGenerators.back(); + CObjectsGenerator* gen = AddGenerator(); const int version = protoGen.version(); gen->m_sName = protoGen.name(); gen->m_sVolumeKey = protoGen.volume_key(); diff --git a/Modules/ObjectsGenerator/GenerationManager.h b/Modules/ObjectsGenerator/GenerationManager.h index 7399053..f4cc220 100644 --- a/Modules/ObjectsGenerator/GenerationManager.h +++ b/Modules/ObjectsGenerator/GenerationManager.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -27,7 +28,11 @@ class CGenerationManager : public CMusenComponent // Returns const pointers to all defined generators std::vector GetGenerators() const; - void CreateNewGenerator(); + /** + * \brief Adds a new empty generator with default name. + * \details The generator will be added to the end of the list and will be active by default. + * \return Pointer to the newly added generator. */ + CObjectsGenerator* AddGenerator(); void DeleteGenerator( size_t _nIndex ); void Initialize(); diff --git a/Modules/ObjectsGenerator/ObjectsGenerator.cpp b/Modules/ObjectsGenerator/ObjectsGenerator.cpp index 4bf1d99..7fdd2d3 100644 --- a/Modules/ObjectsGenerator/ObjectsGenerator.cpp +++ b/Modules/ObjectsGenerator/ObjectsGenerator.cpp @@ -1,9 +1,11 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ObjectsGenerator.h" #include "Quaternion.h" +#include "MUSENStringFunctions.h" CObjectsGenerator::CObjectsGenerator(CAgglomeratesDatabase* _pAgglomD, CMaterialsDatabase* _pMaterialsDB) : m_pAgglomDB( _pAgglomD ), m_pMaterialsDB( _pMaterialsDB ) @@ -301,6 +303,53 @@ bool CObjectsGenerator::IsGeneratingBonds() const return false; } +std::ostream& operator<<(std::ostream& _s, const CObjectsGenerator& _g) +{ + const auto WriteMap = [&_s](const std::map& _map) + { + _s << " " << _map.size(); + for (const auto& [k, v] : _map) + _s << " " << MakeSingleString(k) << " " << MakeSingleString(v); + }; + + _s << MakeSingleString(_g.m_sName) << " " << _g.m_bActive << " " + << MakeSingleString(_g.m_sVolumeKey) << " " << _g.m_maxIterations << " " << _g.m_bInsideGeometries << " " + << _g.m_bGenerateMixture << " " << MakeSingleString(_g.m_sMixtureKey) << " " << MakeSingleString(_g.m_sAgglomerateKey) << " " << _g.m_dAgglomerateScaleFactor; + WriteMap(_g.m_partMaterials); + WriteMap(_g.m_bondMaterials); + _s << " " << _g.m_bRandomVelocity << " " << _g.m_vObjInitVel << " " << _g.m_dVelMagnitude << " " + << _g.m_dStartGenerationTime << " " << _g.m_dUpdateStep << " " << _g.m_dEndGenerationTime << " " + << static_cast(_g.m_rateType) << " " << _g.m_rateValue; + return _s; +} + +std::istream& operator>>(std::istream& _s, CObjectsGenerator& _g) +{ + const auto ReadMap = [&_s](std::map& _map) + { + _map.clear(); + size_t n = 0; + _s >> n; + for (size_t i = 0; i < n; ++i) + { + std::string k, v; + _s >> k >> v; + _map[k] = v; + } + }; + _s >> _g.m_sName >> _g.m_bActive + >> _g.m_sVolumeKey >> _g.m_maxIterations >> _g.m_bInsideGeometries + >> _g.m_bGenerateMixture >> _g.m_sMixtureKey >> _g.m_sAgglomerateKey >> _g.m_dAgglomerateScaleFactor; + ReadMap(_g.m_partMaterials); + ReadMap(_g.m_bondMaterials); + _s >> _g.m_bRandomVelocity >> _g.m_vObjInitVel >> _g.m_dVelMagnitude + >> _g.m_dStartGenerationTime >> _g.m_dUpdateStep >> _g.m_dEndGenerationTime; + int rateType = 0; + _s >> rateType >> _g.m_rateValue; + _g.m_rateType = static_cast(rateType); + return _s; +} + void CObjectsGenerator::GenerateNewObject(std::vector* _pCoordPart, std::vector* _pQuatPart, std::vector* _pPartRad, std::vector* _pPartContRad, std::vector* _sMaterialsKey, const SVolumeType& _boundBox, SPBC& _PBC, const double _dCurrentTime) { diff --git a/Modules/ObjectsGenerator/ObjectsGenerator.h b/Modules/ObjectsGenerator/ObjectsGenerator.h index 8a41382..2e01c2c 100644 --- a/Modules/ObjectsGenerator/ObjectsGenerator.h +++ b/Modules/ObjectsGenerator/ObjectsGenerator.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -73,6 +74,21 @@ class CObjectsGenerator // Checks whether the generator will produce bonds. [[nodiscard]] bool IsGeneratingBonds() const; + /** + * \brief Text-format serialization. + * \details Config only, runtime state is skipped. + * \param _s Output stream. + * \param _g Objects generator to serialize. + * \return Reference to the output stream. */ + friend std::ostream& operator<<(std::ostream& _s, const CObjectsGenerator& _g); + /** + * \brief Text-format deserialization. + * \details Config only, runtime state is skipped. + * \param _s Input stream. + * \param _g Objects generator to deserialize into. + * \return Reference to the input stream. */ + friend std::istream& operator>>(std::istream& _s, CObjectsGenerator& _g); + private: // return true if creation was successfully void GenerateNewObject( std::vector* _pCoordPart, std::vector* _pQuatPart, diff --git a/Modules/ScriptInterface/ScriptAnalyzer.cpp b/Modules/ScriptInterface/ScriptAnalyzer.cpp index d7b373b..0d37333 100644 --- a/Modules/ScriptInterface/ScriptAnalyzer.cpp +++ b/Modules/ScriptInterface/ScriptAnalyzer.cpp @@ -277,6 +277,7 @@ void CScriptAnalyzer::ProcessLine(const std::string& _line, std::ostream& _out / { m_jobs.back().txtExportSettings.generators.packageGenerator = GetValueFromStream(&ss).ToBool(true); m_jobs.back().txtExportSettings.generators.bondsGenerator = GetValueFromStream(&ss).ToBool(true); + m_jobs.back().txtExportSettings.generators.dynamicGenerator = GetValueFromStream(&ss).ToBool(true); } else if (key == "TEXT_EXPORT_PRECISION") { diff --git a/Modules/ScriptInterface/ScriptRunner.cpp b/Modules/ScriptInterface/ScriptRunner.cpp index cf5eb69..8e09ca0 100644 --- a/Modules/ScriptInterface/ScriptRunner.cpp +++ b/Modules/ScriptInterface/ScriptRunner.cpp @@ -9,6 +9,7 @@ #include "FileConverter.h" #include "ImportFromText.h" #include "ExportAsText.h" +#include "GenerationManager.h" #include "BondsGenerator.h" #include "PackageGenerator.h" @@ -265,9 +266,12 @@ void CScriptRunner::ExportToText() CBondsGenerator bondsGenerator; bondsGenerator.SetSystemStructure(&m_systemStructure); bondsGenerator.LoadConfiguration(); + CGenerationManager dynamicGenerator; + dynamicGenerator.SetSystemStructure(&m_systemStructure); + dynamicGenerator.LoadConfiguration(); CExportAsText exporter; CConstraints constraints; - exporter.SetPointers(&m_systemStructure, &constraints, &packageGenerator, &bondsGenerator); + exporter.SetPointers(&m_systemStructure, &constraints, &packageGenerator, &bondsGenerator, &dynamicGenerator); exporter.SetFileName(m_job.resultFileName); exporter.SetSelectors(m_job.txtExportSettings); exporter.SetPrecision(m_job.txtPrecision); @@ -294,12 +298,15 @@ void CScriptRunner::ImportFromText() m_systemStructure.SaveToFile(m_job.resultFileName); CPackageGenerator packageGenerator; CBondsGenerator bondsGenerator; + CGenerationManager dynamicGenerator; packageGenerator.SetSystemStructure(&m_systemStructure); bondsGenerator.SetSystemStructure(&m_systemStructure); - CImportFromText importer(&m_systemStructure, &packageGenerator, &bondsGenerator); + dynamicGenerator.SetSystemStructure(&m_systemStructure); + CImportFromText importer(&m_systemStructure, &packageGenerator, &bondsGenerator, &dynamicGenerator); importer.Import(m_job.sourceFileName); packageGenerator.SaveConfiguration(); bondsGenerator.SaveConfiguration(); + dynamicGenerator.SaveConfiguration(); m_systemStructure.SaveToFile(m_job.resultFileName); m_out << "Import from text finished" << std::endl; } diff --git a/Modules/SimResultsStorage/ExportAsText.cpp b/Modules/SimResultsStorage/ExportAsText.cpp index 4b48419..62dce92 100644 --- a/Modules/SimResultsStorage/ExportAsText.cpp +++ b/Modules/SimResultsStorage/ExportAsText.cpp @@ -7,14 +7,16 @@ #include "Constraints.h" #include "PackageGenerator.h" #include "BondsGenerator.h" +#include "GenerationManager.h" #include "MUSENFileFunctions.h" -void CExportAsText::SetPointers(const CSystemStructure* _systemStructure, const CConstraints* _constraints, const CPackageGenerator* _pakageGenerator, const CBondsGenerator* _bondsGenerator) +void CExportAsText::SetPointers(const CSystemStructure* _systemStructure, const CConstraints* _constraints, const CPackageGenerator* _pakageGenerator, const CBondsGenerator* _bondsGenerator, const CGenerationManager* _dynamicGenerator) { m_systemStructure = _systemStructure; m_constraints = _constraints; m_packageGenerator = _pakageGenerator; m_bondsGenerator = _bondsGenerator; + m_dynamicGenerator = _dynamicGenerator; } void CExportAsText::SetSelectors(const SExportSelector& _selectors) @@ -473,6 +475,11 @@ void CExportAsText::WriteGeneratorsData() if (m_selectors.generators.bondsGenerator) for (const auto& g : m_bondsGenerator->Generators()) WriteLine(ETXTCommands::BONDS_GENERATOR, *g); + + // dynamic generator + if (m_selectors.generators.dynamicGenerator) + for (const auto* g : m_dynamicGenerator->GetGenerators()) + WriteLine(ETXTCommands::DYNAMIC_GENERATOR, *g); } void CExportAsText::TryOpenFileW(std::ofstream& _file, const std::filesystem::path& _name, std::ios::openmode _mode/* = 0*/) diff --git a/Modules/SimResultsStorage/ExportAsText.h b/Modules/SimResultsStorage/ExportAsText.h index cfe83ba..0dd711d 100644 --- a/Modules/SimResultsStorage/ExportAsText.h +++ b/Modules/SimResultsStorage/ExportAsText.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2022, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2022, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -21,6 +22,7 @@ class CPackageGenerator; class CBondsGenerator; +class CGenerationManager; class CSystemStructure; class CConstraints; @@ -89,7 +91,7 @@ class CExportAsText }; struct SGeneratorsFlags : SBaseFlags { - CREATE_FLAGS(SGeneratorsFlags, packageGenerator, bondsGenerator) + CREATE_FLAGS(SGeneratorsFlags, packageGenerator, bondsGenerator, dynamicGenerator) }; /* * All flags to select elements and their properties to be exported. @@ -179,10 +181,11 @@ class CExportAsText SExportSelector m_selectors; // Selection of objects and properties to export. - const CSystemStructure* m_systemStructure{}; // Pointer to system structure. - const CConstraints* m_constraints{}; // Pointer to defined constraints. - const CPackageGenerator* m_packageGenerator{}; // Pointer to package generator. - const CBondsGenerator* m_bondsGenerator{}; // Pointer to bonds generator. + const CSystemStructure* m_systemStructure{}; // Pointer to system structure. + const CConstraints* m_constraints{}; // Pointer to defined constraints. + const CPackageGenerator* m_packageGenerator{}; // Pointer to package generator. + const CBondsGenerator* m_bondsGenerator{}; // Pointer to bonds generator. + const CGenerationManager* m_dynamicGenerator{}; // Pointer to dynamic generator. std::filesystem::path m_resFileName; // Name of resulting text file. std::ofstream m_resFile; // Resulting text file. @@ -199,7 +202,7 @@ class CExportAsText public: // Sets pointers to required objects. Must be called before export. - void SetPointers(const CSystemStructure* _systemStructure, const CConstraints* _constraints, const CPackageGenerator* _pakageGenerator, const CBondsGenerator* _bondsGenerator); + void SetPointers(const CSystemStructure* _systemStructure, const CConstraints* _constraints, const CPackageGenerator* _pakageGenerator, const CBondsGenerator* _bondsGenerator, const CGenerationManager* _dynamicGenerator); // Sets exporting settings. void SetSelectors(const SExportSelector& _selectors); diff --git a/Modules/SimResultsStorage/ImportFromText.cpp b/Modules/SimResultsStorage/ImportFromText.cpp index 707768d..9c8831e 100644 --- a/Modules/SimResultsStorage/ImportFromText.cpp +++ b/Modules/SimResultsStorage/ImportFromText.cpp @@ -6,11 +6,13 @@ #include "ImportFromText.h" #include "PackageGenerator.h" #include "BondsGenerator.h" +#include "GenerationManager.h" -CImportFromText::CImportFromText(CSystemStructure* _pSystemStructure, CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator) +CImportFromText::CImportFromText(CSystemStructure* _pSystemStructure, CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator, CGenerationManager* _dynamicGenerator) : m_pSystemStructure{ _pSystemStructure } , m_packageGenerator{ _pakageGenerator } , m_bondsGenerator{ _bondsGenerator } + , m_dynamicGenerator{ _dynamicGenerator } { } @@ -333,6 +335,12 @@ CImportFromText::SImportFileInfo CImportFromText::Import(const std::string& _fil tempStream >> *g; break; } + case ETXTCommands::DYNAMIC_GENERATOR: + { + auto* g = m_dynamicGenerator->AddGenerator(); + tempStream >> *g; + break; + } } } } diff --git a/Modules/SimResultsStorage/ImportFromText.h b/Modules/SimResultsStorage/ImportFromText.h index ad42a13..9786ea4 100644 --- a/Modules/SimResultsStorage/ImportFromText.h +++ b/Modules/SimResultsStorage/ImportFromText.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -7,6 +8,7 @@ class CPackageGenerator; class CBondsGenerator; +class CGenerationManager; class CImportFromText { @@ -38,6 +40,7 @@ class CImportFromText CSystemStructure* m_pSystemStructure; // Pointer to system structure. CPackageGenerator* m_packageGenerator{ nullptr }; CBondsGenerator* m_bondsGenerator{ nullptr }; + CGenerationManager* m_dynamicGenerator{ nullptr }; struct STDObjectInfo // Time-dependent properties for one object. { std::vector vTime; @@ -55,7 +58,7 @@ class CImportFromText std::vector m_vObjects; // Local storage of all TD properties of all objects. public: - CImportFromText(CSystemStructure* _pSystemStructure, CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator); + CImportFromText(CSystemStructure* _pSystemStructure, CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator, CGenerationManager* _dynamicGenerator); // Imports data from text file. Returns struct with extensive information about import process. SImportFileInfo Import(const std::string& _fileName); diff --git a/QTDialogs/MUSENMainWindow/ExportAsTextTab.cpp b/QTDialogs/MUSENMainWindow/ExportAsTextTab.cpp index 32037bf..9445351 100644 --- a/QTDialogs/MUSENMainWindow/ExportAsTextTab.cpp +++ b/QTDialogs/MUSENMainWindow/ExportAsTextTab.cpp @@ -1,6 +1,7 @@ /* Copyright (c) 2013-2020, MUSEN Development Team. - * Copyright (c) 2025, DyssolTEC GmbH. - * All rights reserved. This file is part of MUSEN framework. See LICENSE file for license and warranty information. */ + Copyright (c) 2025, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. + See LICENSE file for license and warranty information. */ #include "ExportAsTextTab.h" #include "qtOperations.h" @@ -31,10 +32,11 @@ void CExportWorker::StopExporting() const //////////////////////////////////////////////////////////////////////////////////////////////////// /// Tab -CExportAsTextTab::CExportAsTextTab(CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator, QWidget* _parent) +CExportAsTextTab::CExportAsTextTab(CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator, CGenerationManager* _dynamicGenerator, QWidget* _parent) : CMusenDialog{ _parent } , m_packageGenerator{ _pakageGenerator } , m_bondsGenerator{ _bondsGenerator } + , m_dynamicGenerator{ _dynamicGenerator } { ui.setupUi(this); @@ -62,7 +64,7 @@ void CExportAsTextTab::SetPointers(CSystemStructure* _systemStructure, CUnitConv m_constraints.SetPointers(_systemStructure, _materialsDB); ui.constraintsTab->SetPointers(_systemStructure, _unitConvertor, _materialsDB, _geometriesDB, _agglomeratesDB); ui.constraintsTab->SetConstraintsPtr(&m_constraints); - m_exporter.SetPointers(_systemStructure, &m_constraints, m_packageGenerator, m_bondsGenerator); + m_exporter.SetPointers(_systemStructure, &m_constraints, m_packageGenerator, m_bondsGenerator, m_dynamicGenerator); } void CExportAsTextTab::setVisible(bool _visible) @@ -249,7 +251,7 @@ void CExportAsTextTab::ApplyAllFlags() SetFlags(&settings.sceneInfo , ui.groupScene , { ui.checkInfoDomain, ui.checkInfoPBC, ui.checkInfoAnisotropy, ui.checkInfoContactRadius }); SetFlags(&settings.geometries , ui.groupGeometries, { ui.checkGeometryGeneral, ui.checkGeometryTDP, ui.checkGeometryWalls, ui.checkGeometryVolumes }); SetFlags(&settings.materials , ui.groupMaterials , { ui.checkMaterialCompounds, ui.checkMaterialInteractions, ui.checkMaterialMixtures }); - SetFlags(&settings.generators , ui.groupGenerators, { ui.checkGeneratorPackage, ui.checkGeneratorBonds }); + SetFlags(&settings.generators , ui.groupGenerators, { ui.checkGeneratorPackage, ui.checkGeneratorBonds, ui.checkGeneratorDynamic }); } m_exporter.SetSelectors(settings); diff --git a/QTDialogs/MUSENMainWindow/ExportAsTextTab.h b/QTDialogs/MUSENMainWindow/ExportAsTextTab.h index 0a68aa2..2d81069 100644 --- a/QTDialogs/MUSENMainWindow/ExportAsTextTab.h +++ b/QTDialogs/MUSENMainWindow/ExportAsTextTab.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2022, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2022, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -40,9 +41,10 @@ class CExportAsTextTab : public CMusenDialog CPackageGenerator* m_packageGenerator{ nullptr }; // Pointer to actual package generator. CBondsGenerator* m_bondsGenerator{ nullptr }; // Pointer to actual bonds generator. + CGenerationManager* m_dynamicGenerator{ nullptr }; // Pointer to actual dynamic generator manager. public: - CExportAsTextTab(CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator, QWidget* _parent = nullptr); + CExportAsTextTab(CPackageGenerator* _pakageGenerator, CBondsGenerator* _bondsGenerator, CGenerationManager* _dynamicGenerator, QWidget* _parent = nullptr); // Sets all pointers to all required data. Must be called before any other function. void SetPointers(CSystemStructure* _systemStructure, CUnitConvertor* _unitConvertor, CMaterialsDatabase* _materialsDB, CGeometriesDatabase* _geometriesDB, CAgglomeratesDatabase* _agglomeratesDB) override; diff --git a/QTDialogs/MUSENMainWindow/ExportAsTextTab.ui b/QTDialogs/MUSENMainWindow/ExportAsTextTab.ui index 3735ac7..5e06447 100644 --- a/QTDialogs/MUSENMainWindow/ExportAsTextTab.ui +++ b/QTDialogs/MUSENMainWindow/ExportAsTextTab.ui @@ -14,7 +14,7 @@ Export as text - + :/MusenGUI/Resources/MUSEN_Ico.png:/MusenGUI/Resources/MUSEN_Ico.png @@ -1002,6 +1002,16 @@ + + + + Dynamic generator + + + true + + + @@ -1216,7 +1226,7 @@ buttonExport - + diff --git a/QTDialogs/MUSENMainWindow/MUSENMainWindow.cpp b/QTDialogs/MUSENMainWindow/MUSENMainWindow.cpp index dff1938..7a07b48 100644 --- a/QTDialogs/MUSENMainWindow/MUSENMainWindow.cpp +++ b/QTDialogs/MUSENMainWindow/MUSENMainWindow.cpp @@ -64,7 +64,7 @@ MUSENMainWindow::MUSENMainWindow(const QString& _buildVersion, QWidget* parent / m_pAgglomeratesAnalyzerTab = new CAgglomeratesAnalyzerTab(this); m_pGeometriesAnalyzerTab = new CGeometriesAnalyzerTab(this); //m_pCollisionsAnalyzerTab = new CCollisionsAnalyzerTab(this); - m_pExportAsTextTab = new CExportAsTextTab(&m_PackageGenerator, &m_BondsGenerator, this); + m_pExportAsTextTab = new CExportAsTextTab(&m_PackageGenerator, &m_BondsGenerator, &m_GenerationManager, this); m_pFileMergerTab = new CFileMergerTab(this); m_pFileConverterTab = new CFileConverterTab(this); m_pSimulatorSettingsTab = new CSimulatorSettingsTab(&m_SimulatorManager, this); @@ -456,7 +456,7 @@ void MUSENMainWindow::LoadSystemStructureFromText() QApplication::setOverrideCursor(Qt::WaitCursor); m_pViewManager->DisableView(); - CImportFromText importer(&m_SystemStructure, &m_PackageGenerator, &m_BondsGenerator); + CImportFromText importer(&m_SystemStructure, &m_PackageGenerator, &m_BondsGenerator, &m_GenerationManager); const CImportFromText::SImportFileInfo importInfo = importer.Import(qs2ss(fileName)); switch (importInfo.importResult) { diff --git a/QTDialogs/ObjectsGeneratorTab/ObjectsGeneratorTab.cpp b/QTDialogs/ObjectsGeneratorTab/ObjectsGeneratorTab.cpp index 48f9c84..6d9fc8f 100644 --- a/QTDialogs/ObjectsGeneratorTab/ObjectsGeneratorTab.cpp +++ b/QTDialogs/ObjectsGeneratorTab/ObjectsGeneratorTab.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "ObjectsGeneratorTab.h" @@ -51,7 +52,7 @@ void CObjectsGeneratorTab::InitializeConnections() const void CObjectsGeneratorTab::AddGenerator() { - m_generationManager->CreateNewGenerator(); + m_generationManager->AddGenerator(); UpdateWholeView(); } From b6a5a841f8de0b181cfdfd5b37c83e4ea9f22e45 Mon Sep 17 00:00:00 2001 From: Vasyl Skorych Date: Wed, 20 May 2026 18:26:07 +0200 Subject: [PATCH 4/6] feat: Add dynamic generators to script interface. - refs #44 --- .../AgglomeratesDatabase.cpp | 13 ++- .../AgglomeratesDatabase.h | 6 +- Modules/ScriptInterface/ConsoleSimulator.cpp | 87 +++++++++++++++++++ Modules/ScriptInterface/ScriptAnalyzer.cpp | 27 ++++++ Modules/ScriptInterface/ScriptJob.h | 22 +++++ 5 files changed, 151 insertions(+), 4 deletions(-) diff --git a/Databases/AgglomerateDatabase/AgglomeratesDatabase.cpp b/Databases/AgglomerateDatabase/AgglomeratesDatabase.cpp index 96fca54..45784ca 100644 --- a/Databases/AgglomerateDatabase/AgglomeratesDatabase.cpp +++ b/Databases/AgglomerateDatabase/AgglomeratesDatabase.cpp @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #include "AgglomeratesDatabase.h" @@ -44,6 +45,14 @@ SAgglomerate* CAgglomeratesDatabase::GetAgglomerate(const std::string& _sKey) return NULL; } +const SAgglomerate* CAgglomeratesDatabase::GetAgglomerateByName(const std::string& _name) const +{ + for (const auto* a : m_vAgglomerates) + if (a->sName == _name) + return a; + return nullptr; +} + double CAgglomeratesDatabase::CalculateVolume(SAgglomerate* _pAgglom) { double dVolume = 0; diff --git a/Databases/AgglomerateDatabase/AgglomeratesDatabase.h b/Databases/AgglomerateDatabase/AgglomeratesDatabase.h index 772f752..a9d392a 100644 --- a/Databases/AgglomerateDatabase/AgglomeratesDatabase.h +++ b/Databases/AgglomerateDatabase/AgglomeratesDatabase.h @@ -1,5 +1,6 @@ -/* Copyright (c) 2013-2020, MUSEN Development Team. All rights reserved. - This file is part of MUSEN framework http://msolids.net/musen. +/* Copyright (c) 2013-2020, MUSEN Development Team. + Copyright (c) 2026, DyssolTEC GmbH. + All rights reserved. This file is part of MUSEN framework https://github.com/msolids/musen. See LICENSE file for license and warranty information. */ #pragma once @@ -63,6 +64,7 @@ class CAgglomeratesDatabase SAgglomerate* GetAgglomerate(size_t _nIndex); SAgglomerate* GetAgglomerate(const std::string& _sKey); + const SAgglomerate* GetAgglomerateByName(const std::string& _name) const; int GetAgglomerateIndex(const std::string& _sKey); std::string GetFileName() { return m_sDatabaseFileName; } diff --git a/Modules/ScriptInterface/ConsoleSimulator.cpp b/Modules/ScriptInterface/ConsoleSimulator.cpp index 13c4123..26c75bd 100644 --- a/Modules/ScriptInterface/ConsoleSimulator.cpp +++ b/Modules/ScriptInterface/ConsoleSimulator.cpp @@ -137,6 +137,93 @@ void CConsoleSimulator::SetupGenerationManager() m_generationManager.SetSystemStructure(&m_systemStructure); m_generationManager.LoadConfiguration(); m_agglomeratesDatabase.LoadFromFile(m_job.agglomeratesDBFileName); + + const auto ResolveVolumeKey = [this](const std::string& _nameOrKey) + { + if (const auto* v = m_systemStructure.AnalysisVolumeByName(_nameOrKey)) + return v->Key(); + return _nameOrKey; + }; + const auto ResolveCompoundKey = [this](const std::string& _nameOrKey) + { + if (const auto* c = m_systemStructure.m_MaterialDatabase.GetCompoundByName(_nameOrKey)) + return c->GetKey(); + return _nameOrKey; + }; + const auto ResolveMixtureKey = [this](const std::string& _nameOrKey) + { + if (const auto* m = m_systemStructure.m_MaterialDatabase.GetMixtureByName(_nameOrKey)) + return m->GetKey(); + return _nameOrKey; + }; + const auto ResolveAgglomerateKey = [this](const std::string& _nameOrKey) + { + if (const auto* a = m_agglomeratesDatabase.GetAgglomerateByName(_nameOrKey)) + return a->sKey; + return _nameOrKey; + }; + const auto ParseRateType = [](const std::string& _name) + { + if (_name == "OBJECTS_PER_STEP") return CObjectsGenerator::ERateType::OBJECTS_PER_STEP; + if (_name == "OBJECTS_TOTAL") return CObjectsGenerator::ERateType::OBJECTS_TOTAL; + return CObjectsGenerator::ERateType::GENERATION_RATE; + }; + + for (const auto& [idx1, dg] : m_job.dynamicGenerators) + { + const size_t index = idx1 - 1; + while (index >= m_generationManager.GetGeneratorsNumber()) + m_generationManager.AddGenerator(); + CObjectsGenerator* gen = m_generationManager.GetGenerator(index); + if (!dg.volume.empty()) + gen->m_sVolumeKey = ResolveVolumeKey(dg.volume); + if (dg.maxIterations != 0) + gen->m_maxIterations = dg.maxIterations; + if (dg.inside.IsDefined()) + gen->m_bInsideGeometries = dg.inside.ToBool(); + // generation-mode (mixture vs agglomerate) is inferred from which key the user set; when more than one is set, the later wins + if (!dg.mixture.empty()) + { + gen->m_sMixtureKey = ResolveMixtureKey(dg.mixture); + gen->m_bGenerateMixture = true; + } + if (!dg.agglomerate.empty()) + { + gen->m_sAgglomerateKey = ResolveAgglomerateKey(dg.agglomerate); + gen->m_bGenerateMixture = false; + } + if (std::isfinite(dg.agglomerateScale)) + { + gen->m_dAgglomerateScaleFactor = dg.agglomerateScale; + gen->m_bGenerateMixture = false; + } + // material-override maps are merged additively per alias, existing entries for other aliases stay + for (const auto& [alias, nameOrKey] : dg.partMaterials) + gen->m_partMaterials[alias] = ResolveCompoundKey(nameOrKey); + for (const auto& [alias, nameOrKey] : dg.bondMaterials) + gen->m_bondMaterials[alias] = ResolveCompoundKey(nameOrKey); + // velocity mode (fixed vs random) is inferred from which key the user set; when more than one is set, the later wins + if (!dg.velocity.IsInf()) + { + gen->m_vObjInitVel = dg.velocity; + gen->m_bRandomVelocity = false; + } + if (std::isfinite(dg.velMagnitude)) + { + gen->m_dVelMagnitude = dg.velMagnitude; + gen->m_bRandomVelocity = true; + } + if (std::isfinite(dg.startTime)) + gen->m_dStartGenerationTime = dg.startTime; + if (std::isfinite(dg.endTime)) + gen->m_dEndGenerationTime = dg.endTime; + if (std::isfinite(dg.updateStep)) + gen->m_dUpdateStep = dg.updateStep; + if (!dg.rateTypeName.empty()) + gen->m_rateType = ParseRateType(dg.rateTypeName); + if (std::isfinite(dg.rateValue)) + gen->m_rateValue = dg.rateValue; + } } void CConsoleSimulator::SetupModelManager() diff --git a/Modules/ScriptInterface/ScriptAnalyzer.cpp b/Modules/ScriptInterface/ScriptAnalyzer.cpp index 0d37333..a87a4cc 100644 --- a/Modules/ScriptInterface/ScriptAnalyzer.cpp +++ b/Modules/ScriptInterface/ScriptAnalyzer.cpp @@ -163,6 +163,33 @@ void CScriptAnalyzer::ProcessLine(const std::string& _line, std::ostream& _out / else if (key == "BOND_GEN_DIAMETER") m_jobs.back().bondGenerators[index].diameter = GetValueFromStream(&ss); else if (key == "BOND_GEN_OVERLAY") m_jobs.back().bondGenerators[index].overlay = GetValueFromStream(&ss); } + else if (key.rfind("DYN_GEN", 0) == 0) + { + const auto index = GetValueFromStream(&ss); + if (key == "DYN_GEN_VOLUME") m_jobs.back().dynamicGenerators[index].volume = GetRestOfLine(&ss); + else if (key == "DYN_GEN_MAX_ITERATIONS") m_jobs.back().dynamicGenerators[index].maxIterations = static_cast(GetValueFromStream(&ss)); + else if (key == "DYN_GEN_INSIDE") m_jobs.back().dynamicGenerators[index].inside = GetValueFromStream(&ss); + else if (key == "DYN_GEN_MIXTURE") m_jobs.back().dynamicGenerators[index].mixture = GetRestOfLine(&ss); + else if (key == "DYN_GEN_AGGLOMERATE") m_jobs.back().dynamicGenerators[index].agglomerate = GetRestOfLine(&ss); + else if (key == "DYN_GEN_AGGLO_SCALE") m_jobs.back().dynamicGenerators[index].agglomerateScale = GetValueFromStream(&ss); + else if (key == "DYN_GEN_VELOCITY") m_jobs.back().dynamicGenerators[index].velocity = GetValueFromStream(&ss); + else if (key == "DYN_GEN_VEL_MAGNITUDE") m_jobs.back().dynamicGenerators[index].velMagnitude = GetValueFromStream(&ss); + else if (key == "DYN_GEN_START_TIME") m_jobs.back().dynamicGenerators[index].startTime = GetValueFromStream(&ss); + else if (key == "DYN_GEN_END_TIME") m_jobs.back().dynamicGenerators[index].endTime = GetValueFromStream(&ss); + else if (key == "DYN_GEN_UPDATE_STEP") m_jobs.back().dynamicGenerators[index].updateStep = GetValueFromStream(&ss); + else if (key == "DYN_GEN_RATE_TYPE") m_jobs.back().dynamicGenerators[index].rateTypeName = ToUpperCase(GetRestOfLine(&ss)); + else if (key == "DYN_GEN_RATE") m_jobs.back().dynamicGenerators[index].rateValue = GetValueFromStream(&ss); + else if (key == "DYN_GEN_PART_MATERIAL") + { + const auto alias = GetValueFromStream(&ss); + m_jobs.back().dynamicGenerators[index].partMaterials[alias] = GetRestOfLine(&ss); + } + else if (key == "DYN_GEN_BOND_MATERIAL") + { + const auto alias = GetValueFromStream(&ss); + m_jobs.back().dynamicGenerators[index].bondMaterials[alias] = GetRestOfLine(&ss); + } + } else if (key == "MATERIAL_PROPERTY") { const auto propertyStr = ToUpperCase(GetValueFromStream(&ss)); diff --git a/Modules/ScriptInterface/ScriptJob.h b/Modules/ScriptInterface/ScriptJob.h index 7a7899b..2c462a1 100644 --- a/Modules/ScriptInterface/ScriptJob.h +++ b/Modules/ScriptInterface/ScriptJob.h @@ -43,6 +43,25 @@ struct SJob CTriState overlay{ CTriState::EState::UNDEFINED }; }; + struct SDynamicGenerator + { + std::string volume; // analysis-volume name or key + size_t maxIterations{ 0 }; + CTriState inside{ CTriState::EState::UNDEFINED }; + std::string mixture; // mixture name or key + std::string agglomerate; // agglomerate key + double agglomerateScale{ std::numeric_limits::infinity() }; // agglomerate scale factor + std::map partMaterials; // agglomerate particle-material alias->material overrides (additive) + std::map bondMaterials; // agglomerate bond-material alias->material overrides (additive) + CVector3 velocity{ std::numeric_limits::infinity() }; // velocity for fixed-velocity mode + double velMagnitude{ std::numeric_limits::infinity() }; // velocity magnitude for random-velocity mode + double startTime{ std::numeric_limits::infinity() }; + double endTime{ std::numeric_limits::infinity() }; + double updateStep{ std::numeric_limits::infinity() }; + std::string rateTypeName; // "GENERATION_RATE" | "OBJECTS_PER_STEP" | "OBJECTS_TOTAL" + double rateValue{ std::numeric_limits::infinity() }; + }; + struct SMDBMaterialProperties { ETPPropertyTypes propertyKey; @@ -151,6 +170,9 @@ struct SJob // bonds generator, std::map bondGenerators; + // dynamic generator, + std::map dynamicGenerators; + // export as text CExportAsText::SExportSelector txtExportSettings; double timeBeg{ -1 }; From a6bb93abaab88c88e146616682b20e9c4edad5ad Mon Sep 17 00:00:00 2001 From: Vasyl Skorych Date: Wed, 20 May 2026 18:27:08 +0200 Subject: [PATCH 5/6] chore: Trim trailing spaces in agglomerate names --- Installers/Data/Databases/Agglomerates.madb | Bin 1473617 -> 1473616 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Installers/Data/Databases/Agglomerates.madb b/Installers/Data/Databases/Agglomerates.madb index 8d3c71f972044f352b63138f3181860facf99f64..9508f5962397f807d0de4e7366f9934b22a19804 100644 GIT binary patch delta 83 zcmcckBl5zJ$c7fi7N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj5Eh7E` l!b_SMx%m9@^HXwC6?7E>QuFds+mi)EfLL^UvVhpTYyi4H8$kd7 delta 84 zcmcccBl6;p$c7fi7N!>F7M2#)7Pc1l7LFFq7OocV7M>Q~7QPn#7J(MQ7NHj5Eh7E` mB1@YXx%mC^^HXwC6?7E>QuFds721;oM1WXydy;_IyKDf`?;BwN From 782a8c113939738cc408fece5d149052aeab4623 Mon Sep 17 00:00:00 2001 From: Vasyl Skorych Date: Wed, 20 May 2026 18:29:35 +0200 Subject: [PATCH 6/6] ci: Use windows-2025 instead of windows-latest --- .github/workflows/build_windows.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_windows.yml b/.github/workflows/build_windows.yml index 28d3c55..90dc5fb 100644 --- a/.github/workflows/build_windows.yml +++ b/.github/workflows/build_windows.yml @@ -25,7 +25,7 @@ jobs: # Verify MUSEN builds with different CUDA versions compile-check: name: compile-check (CUDA ${{ matrix.cuda }}) - runs-on: windows-latest + runs-on: windows-2025 strategy: fail-fast: false matrix: @@ -99,7 +99,7 @@ jobs: # Build Debug, Release, Installer, ModelsCreator full-test: - runs-on: windows-latest + runs-on: windows-2025 steps: - name: Checkout @@ -228,7 +228,7 @@ jobs: # Full build with CUDA_VERSION_RELEASE and all compute capabilities and publish GitHub Release release: - runs-on: windows-latest + runs-on: windows-2025 needs: [compile-check, full-test] if: startsWith(github.ref, 'refs/tags/v')