From b414b391303cb780f51c040058f2b10e34e709b6 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 20 Nov 2020 15:14:08 +0100 Subject: [PATCH] Added supercell energy background builder Added an energy background builder for the supercell that can be used to inject energy backgrounds into build msl files --- .../Logic/Routines/EnvironmentRoutines.c | 2 +- .../IUnitCellVectorEncoder.cs | 14 ++ .../UnitCellVectorEncoder.cs | 14 ++ .../Lattice/Owned/EnergyBackgroundEntity.cs | 5 - .../EntityBuilder/Main/JobDbModelBuilder.cs | 6 +- .../Base => }/IPostBuildOptimizer.cs | 0 .../JumpSelectionOptimizer.cs | 0 .../Postbuild/EnergyBackgroundBuilder.cs | 153 ++++++++++++++++++ .../LatticeConfiguration.cs | 7 + .../IProjectModelContextBuilder.cs | 6 + .../ProjectModelContextBuilder.cs | 3 + .../Context/MslEvaluationContext.cs | 24 +-- .../Helper/MetaDataHelper.cs | 2 +- .../Queries/LatticeMetaEvaluation.cs | 2 +- .../Mocassin.UI.Xml/Helper/MslHelper.cs | 87 ++++++++++ 15 files changed, 297 insertions(+), 28 deletions(-) rename src/ModelBuilder/ICon.Model.Translator/Database/Optimization/{PostBuildOptimizer/Base => }/IPostBuildOptimizer.cs (100%) rename src/ModelBuilder/ICon.Model.Translator/Database/Optimization/{PostBuildOptimizer/JumpSelectionOptimizer => }/JumpSelectionOptimizer.cs (100%) create mode 100644 src/ModelBuilder/ICon.Model.Translator/Database/Postbuild/EnergyBackgroundBuilder.cs create mode 100644 src/ModelBuilder/Mocassin.UI.Xml/Helper/MslHelper.cs diff --git a/src/McSolver/Libraries/Simulator/Logic/Routines/EnvironmentRoutines.c b/src/McSolver/Libraries/Simulator/Logic/Routines/EnvironmentRoutines.c index 996e6bcf..0f9bce00 100644 --- a/src/McSolver/Libraries/Simulator/Logic/Routines/EnvironmentRoutines.c +++ b/src/McSolver/Libraries/Simulator/Logic/Routines/EnvironmentRoutines.c @@ -436,7 +436,7 @@ static void AddStaticEnvBackgroundStateEnergies(SCONTEXT_PARAMETER, EnvironmentS { let vector = environment->LatticeVector; let particleId = environment->EnvironmentDefinition->PositionParticleIds[j]; - let cellEntry = cellBackground->Begin == NULL? 0.0 : array_Get(*cellBackground, vector.D, particleId); + let cellEntry = cellBackground->Begin == NULL ? 0.0 : array_Get(*cellBackground, vector.D, particleId); let latticeEntry = latticeBackground->Begin == NULL ? 0.0 : array_Get(*latticeBackground, vecCoorSet4(vector), particleId); span_Get(environment->EnergyStates, particleId) += cellEntry + latticeEntry; } diff --git a/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/IUnitCellVectorEncoder.cs b/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/IUnitCellVectorEncoder.cs index 85e53e8e..72d14b5b 100644 --- a/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/IUnitCellVectorEncoder.cs +++ b/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/IUnitCellVectorEncoder.cs @@ -109,6 +109,13 @@ public interface IUnitCellVectorEncoder /// bool TryDecode(in Vector4I encoded, out Fractional3D decoded); + /// + /// Decodes a 4D encoded vector into absolute fractional vector starting at the unit cell origin without performing bound checks + /// + /// + /// + void DecodeUnchecked(in Vector4I encoded, out Fractional3D decoded); + /// /// Tries to decode multiple 4D vectors into a list of fractional vectors (Returns false if not possible) /// @@ -126,6 +133,13 @@ public interface IUnitCellVectorEncoder /// bool TryDecode(in Vector4I encoded, out Cartesian3D decoded); + /// + /// Decodes a 4D encoded vector into absolute cartesian vector starting at the unit cell origin without performing bound checks + /// + /// + /// + void DecodeUnchecked(in Vector4I encoded, out Cartesian3D decoded); + /// /// Tries to decoded 4D encoded vector into a spherical vector from unit cell origin (Returns false if not possible) /// diff --git a/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/UnitCellVectorEncoder.cs b/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/UnitCellVectorEncoder.cs index 30ae4c1d..7ca3a599 100644 --- a/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/UnitCellVectorEncoder.cs +++ b/src/ModelBuilder/ICon.Framework.Mathematics/CoordinateSystems/UnitCellVectorEncoder.cs @@ -83,6 +83,13 @@ public bool TryEncodeAsRelative(in Fractional3D origin, in Fractional3D vector, /// public bool TryDecode(in Vector4I encoded, out Fractional3D decoded) => TryDecodeFractional(encoded.Coordinates, out decoded); + /// + public void DecodeUnchecked(in Vector4I encoded, out Fractional3D decoded) + { + var offset = PositionList[encoded.P]; + decoded = new Fractional3D(encoded.A + offset.A, encoded.B + offset.B, encoded.C + offset.C); + } + /// public bool TryDecode(IEnumerable encoded, out List decoded) { @@ -115,6 +122,13 @@ public bool TryDecode(in Vector4I encoded, out Cartesian3D decoded) return true; } + /// + public void DecodeUnchecked(in Vector4I encoded, out Cartesian3D decoded) + { + DecodeUnchecked(encoded, out Fractional3D fractional3D); + decoded = Transformer.ToCartesian(fractional3D); + } + /// public bool TryDecode(in Vector4I encoded, out Spherical3D decoded) { diff --git a/src/ModelBuilder/ICon.Model.Translator/Database/Entities/Lattice/Owned/EnergyBackgroundEntity.cs b/src/ModelBuilder/ICon.Model.Translator/Database/Entities/Lattice/Owned/EnergyBackgroundEntity.cs index 72192640..e6cd2981 100644 --- a/src/ModelBuilder/ICon.Model.Translator/Database/Entities/Lattice/Owned/EnergyBackgroundEntity.cs +++ b/src/ModelBuilder/ICon.Model.Translator/Database/Entities/Lattice/Owned/EnergyBackgroundEntity.cs @@ -5,11 +5,6 @@ /// public class EnergyBackgroundEntity : InteropArray { - /// - /// The empty energy background property - /// - public static readonly EnergyBackgroundEntity Empty = new EnergyBackgroundEntity(new double[0, 0, 0, 0, 0]); - /// public EnergyBackgroundEntity() { diff --git a/src/ModelBuilder/ICon.Model.Translator/Database/EntityBuilder/Main/JobDbModelBuilder.cs b/src/ModelBuilder/ICon.Model.Translator/Database/EntityBuilder/Main/JobDbModelBuilder.cs index a3c6d731..d8de10c4 100644 --- a/src/ModelBuilder/ICon.Model.Translator/Database/EntityBuilder/Main/JobDbModelBuilder.cs +++ b/src/ModelBuilder/ICon.Model.Translator/Database/EntityBuilder/Main/JobDbModelBuilder.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Mocassin.Framework.Events; using Mocassin.Framework.Extensions; +using Mocassin.Model.Structures; using Mocassin.Model.Translator.Database.Entities.Other.Meta; using Mocassin.Model.Translator.Jobs; using Mocassin.Model.Translator.ModelContext; @@ -189,6 +190,9 @@ protected SimulationJobModel GetJobModel(ISimulationModel simulationModel, JobCo /// protected JobMetaDataEntity GetJobMetaDataEntity(JobConfiguration jobConfiguration, IJobCollection jobCollection) { + var positionCountPerCell = ProjectModelContext.ModelProject + .Manager().DataAccess + .Query(x => x.GetLinearizedExtendedPositionCount()); var entity = new JobMetaDataEntity { CollectionName = jobConfiguration.CollectionName, @@ -200,7 +204,7 @@ protected JobMetaDataEntity GetJobMetaDataEntity(JobConfiguration jobConfigurati Mcsp = jobConfiguration.TargetMcsp, TimeLimit = jobConfiguration.TimeLimit, DopingInfo = jobConfiguration.LatticeConfiguration.GetDopingString(), - LatticeInfo = jobConfiguration.LatticeConfiguration.GetSizeString() + LatticeInfo = jobConfiguration.LatticeConfiguration.GetSizeString(positionCountPerCell) }; AddKineticMetaData(entity, jobConfiguration); diff --git a/src/ModelBuilder/ICon.Model.Translator/Database/Optimization/PostBuildOptimizer/Base/IPostBuildOptimizer.cs b/src/ModelBuilder/ICon.Model.Translator/Database/Optimization/IPostBuildOptimizer.cs similarity index 100% rename from src/ModelBuilder/ICon.Model.Translator/Database/Optimization/PostBuildOptimizer/Base/IPostBuildOptimizer.cs rename to src/ModelBuilder/ICon.Model.Translator/Database/Optimization/IPostBuildOptimizer.cs diff --git a/src/ModelBuilder/ICon.Model.Translator/Database/Optimization/PostBuildOptimizer/JumpSelectionOptimizer/JumpSelectionOptimizer.cs b/src/ModelBuilder/ICon.Model.Translator/Database/Optimization/JumpSelectionOptimizer.cs similarity index 100% rename from src/ModelBuilder/ICon.Model.Translator/Database/Optimization/PostBuildOptimizer/JumpSelectionOptimizer/JumpSelectionOptimizer.cs rename to src/ModelBuilder/ICon.Model.Translator/Database/Optimization/JumpSelectionOptimizer.cs diff --git a/src/ModelBuilder/ICon.Model.Translator/Database/Postbuild/EnergyBackgroundBuilder.cs b/src/ModelBuilder/ICon.Model.Translator/Database/Postbuild/EnergyBackgroundBuilder.cs new file mode 100644 index 00000000..cb3533a7 --- /dev/null +++ b/src/ModelBuilder/ICon.Model.Translator/Database/Postbuild/EnergyBackgroundBuilder.cs @@ -0,0 +1,153 @@ +using System; +using Mocassin.Mathematics.ValueTypes; +using Mocassin.Model.Particles; +using Mocassin.Model.Structures; +using Mocassin.Model.Translator.ModelContext; + +namespace Mocassin.Model.Translator.Database.Postbuild +{ + /// + /// Builder that creates for instances based on + /// energy provider functions + /// + public class EnergyBackgroundBuilder + { + /// + /// The lattice size in A direction + /// + public int SizeA { get; } + + /// + /// The lattice size in B direction + /// + public int SizeB { get; } + + /// + /// The lattice size in C direction + /// + public int SizeC { get; } + + /// + /// Creates a new for a specific supercell size + /// + /// + /// + /// + public EnergyBackgroundBuilder(int sizeA, int sizeB, int sizeC) + { + SizeA = sizeA; + SizeB = sizeB; + SizeC = sizeC; + } + + /// + /// Builds an using the provided and energy provider for vectors + /// + /// + /// + /// + public EnergyBackgroundEntity Build(IProjectModelContext modelContext, Func energyFunc) + { + var transformedEnergyFunc = TransformEnergyFunction(modelContext, energyFunc); + return Build(modelContext, transformedEnergyFunc); + } + + /// + /// Builds an using the provided and energy provider for vectors + /// + /// + /// + /// + public EnergyBackgroundEntity Build(IProjectModelContext modelContext, Func energyFunc) + { + var transformedEnergyFunc = TransformEnergyFunction(modelContext, energyFunc); + return Build(modelContext, transformedEnergyFunc); + } + + /// + /// Builds an using the provided and energy provider for vectors + /// + /// + /// + /// + public EnergyBackgroundEntity Build(IProjectModelContext modelContext, Func energyFunc) + { + var particles = modelContext.ModelProject.DataTracker.MapObjects(); + var positionCount = modelContext.ModelProject + .Manager().DataAccess + .Query(x => x.GetLinearizedExtendedPositionCount()); + var rawResult = CreateRawArray(positionCount, particles.Length); + + for (var a = 0; a < SizeA; a++) + { + for (var b = 0; b < SizeB; b++) + { + for (var c = 0; c < SizeC; c++) + { + for (var p = 0; p < positionCount; p++) + { + for (var particleId = 1; particleId < particles.Length; particleId++) + { + var particle = particles[particleId]; + var vector4 = new Vector4I(a, b, c, p); + rawResult[a, b, c, p, particleId] = energyFunc.Invoke(particle, vector4); + } + } + } + } + } + + return new EnergyBackgroundEntity(rawResult); + } + + /// + /// Provides a new zero initialized 5D array of correct size + /// + /// + /// + /// + private double[,,,,] CreateRawArray(int positionCount, int particleCount) => new double[SizeA, SizeB, SizeC, positionCount, particleCount]; + + /// + /// Transforms the provided energy provider function for to use data + /// + /// + /// + /// + private static Func TransformEnergyFunction(IProjectModelContext modelContext, Func energyFunc) + { + var vectorEncoder = modelContext.ModelProject + .Manager().DataAccess + .Query(x => x.GetVectorEncoder()); + + double ProvideEnergy(IParticle particle, Vector4I vector4) + { + vectorEncoder.DecodeUnchecked(vector4, out Cartesian3D cartesian3D); + return energyFunc.Invoke(particle, cartesian3D); + } + + return ProvideEnergy; + } + + /// + /// Transforms the provided energy provider function for to use data + /// + /// + /// + /// + private static Func TransformEnergyFunction(IProjectModelContext modelContext, Func energyFunc) + { + var vectorEncoder = modelContext.ModelProject + .Manager().DataAccess + .Query(x => x.GetVectorEncoder()); + + double ProvideEnergy(IParticle particle, Vector4I vector4) + { + vectorEncoder.DecodeUnchecked(vector4, out Fractional3D fractional3D); + return energyFunc.Invoke(particle, fractional3D); + } + + return ProvideEnergy; + } + } +} \ No newline at end of file diff --git a/src/ModelBuilder/ICon.Model.Translator/Jobs/Objects/LatticeConfiguration/LatticeConfiguration.cs b/src/ModelBuilder/ICon.Model.Translator/Jobs/Objects/LatticeConfiguration/LatticeConfiguration.cs index 9008f133..3235115f 100644 --- a/src/ModelBuilder/ICon.Model.Translator/Jobs/Objects/LatticeConfiguration/LatticeConfiguration.cs +++ b/src/ModelBuilder/ICon.Model.Translator/Jobs/Objects/LatticeConfiguration/LatticeConfiguration.cs @@ -55,6 +55,13 @@ public void CopyTo(LatticeConfiguration latticeConfiguration) /// public string GetSizeString() => $"{SizeA},{SizeB},{SizeC}"; + /// + /// Get set size as a default formatted including the position count + /// + /// + /// + public string GetSizeString(int sizeP) => $"{SizeA},{SizeB},{SizeC},{sizeP}"; + /// /// Get the set dopings as a default formatted /// diff --git a/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/IProjectModelContextBuilder.cs b/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/IProjectModelContextBuilder.cs index 69296ec7..1b03a9b9 100644 --- a/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/IProjectModelContextBuilder.cs +++ b/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/IProjectModelContextBuilder.cs @@ -48,5 +48,11 @@ public interface IProjectModelContextBuilder /// /// Task BuildContextAsync(); + + /// + /// Builds a new project model context from the current model project + /// + /// + IProjectModelContext Build(); } } \ No newline at end of file diff --git a/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/ProjectModelContextBuilder.cs b/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/ProjectModelContextBuilder.cs index 323b4742..a35e1eca 100644 --- a/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/ProjectModelContextBuilder.cs +++ b/src/ModelBuilder/ICon.Model.Translator/ModelContext/Main/ContextBuilder/ProjectModelContextBuilder.cs @@ -59,6 +59,9 @@ public async Task BuildContextAsync() return projectModelContext; } + /// + public IProjectModelContext Build() => BuildContextAsync().Result; + /// /// Creates all context components independently and awaits their completion /// diff --git a/src/ModelBuilder/Mocassin.Tools.Evaluation/Context/MslEvaluationContext.cs b/src/ModelBuilder/Mocassin.Tools.Evaluation/Context/MslEvaluationContext.cs index 75aa31f0..c46d976b 100644 --- a/src/ModelBuilder/Mocassin.Tools.Evaluation/Context/MslEvaluationContext.cs +++ b/src/ModelBuilder/Mocassin.Tools.Evaluation/Context/MslEvaluationContext.cs @@ -10,6 +10,7 @@ using Mocassin.Model.Translator.ModelContext; using Mocassin.Tools.Evaluation.Queries; using Mocassin.UI.Data.Base; +using Mocassin.UI.Data.Helper; using Mocassin.UI.Data.Main; namespace Mocassin.Tools.Evaluation.Context @@ -148,21 +149,6 @@ public void EnsureModelContextCreated(JobContext jobContext) GetSimulationModel(jobContext.JobModel); } - /// - /// Restores the from a passed project xml - /// - /// - /// - public IProjectModelContext RestoreProjectModelContext(string projectXml) - { - var dbBuildTemplate = ProjectDataObject.CreateFromXml(projectXml); - var modelProject = ModelProjectProvider.Invoke(); - modelProject.InputPipeline.PushToProject(dbBuildTemplate.ProjectModelData.GetInputSequence()); - dbBuildTemplate.ProjectCustomizationTemplate.PushToModel(modelProject); - var builder = new ProjectModelContextBuilder(modelProject); - return builder.BuildContextAsync().Result; - } - /// /// Takes an of and builds the sequence of /// instances @@ -173,7 +159,7 @@ public IQueryable RestoreProjectModelContext(IQueryable x.ProjectXml) - .Select(x => RestoreProjectModelContext(x.ProjectXml)); + .Select(x => MslHelper.RestoreModelContext(x)); } /// @@ -188,7 +174,7 @@ public IProjectModelContext GetProjectModelContext(int contextId) if (ProjectContextCache.TryGetValue(contextId, out var context)) return context; var packageModel = LoadJobPackageModel(contextId); - var context2 = RestoreProjectModelContext(packageModel.ProjectXml); + var context2 = MslHelper.RestoreModelContext(packageModel); lock (lockObject) { ProjectContextCache[contextId] = context2; @@ -243,8 +229,8 @@ public ISimulationModel GetSimulationModel(SimulationJobModel jobModel) var modelContext = GetProjectModelContext(jobModel); if (SimulationModelCache.TryGetValue(jobModel.SimulationPackageId, out var result)) return result; - var buildGraph = ProjectDataObject.CreateFromXml(jobModel.SimulationJobPackageModel.ProjectXml); - var simulation = buildGraph.ProjectJobSetTemplate + var buildTemplate = ProjectDataObject.CreateFromXml(jobModel.SimulationJobPackageModel.ProjectXml); + var simulation = buildTemplate.ProjectJobSetTemplate .ToInternals(modelContext.ModelProject) .First(x => x.CollectionId == jobModel.JobMetaData.CollectionIndex) .GetSimulation(); diff --git a/src/ModelBuilder/Mocassin.Tools.Evaluation/Helper/MetaDataHelper.cs b/src/ModelBuilder/Mocassin.Tools.Evaluation/Helper/MetaDataHelper.cs index 07e86474..6a466ba0 100644 --- a/src/ModelBuilder/Mocassin.Tools.Evaluation/Helper/MetaDataHelper.cs +++ b/src/ModelBuilder/Mocassin.Tools.Evaluation/Helper/MetaDataHelper.cs @@ -18,7 +18,7 @@ public static class MetaDataHelper public static int GetNumberOfUnitCells(IJobMetaData metaData) { var split = metaData.LatticeInfo.Split(','); - if (split.Length != 3) throw new InvalidOperationException("The lattice info in the database is corrupt."); + if (split.Length < 3) throw new InvalidOperationException("The lattice info in the database is corrupt."); return split.Sum(int.Parse); } } diff --git a/src/ModelBuilder/Mocassin.Tools.Evaluation/Queries/LatticeMetaEvaluation.cs b/src/ModelBuilder/Mocassin.Tools.Evaluation/Queries/LatticeMetaEvaluation.cs index 43419bde..2acdf226 100644 --- a/src/ModelBuilder/Mocassin.Tools.Evaluation/Queries/LatticeMetaEvaluation.cs +++ b/src/ModelBuilder/Mocassin.Tools.Evaluation/Queries/LatticeMetaEvaluation.cs @@ -40,7 +40,7 @@ protected override LatticeMetaData GetValue(JobContext jobContext) protected Vector4I GetLatticeSizeInfo(JobContext jobContext, IUnitCellVectorEncoder vectorEncoder) { var split = jobContext.JobModel.JobMetaData.LatticeInfo.Split(','); - if (split.Length != 3) throw new InvalidOperationException("Invalid format of lattice size string."); + if (split.Length < 3) throw new InvalidOperationException("Invalid format of lattice size string."); return new Vector4I(int.Parse(split[0]), int.Parse(split[1]), int.Parse(split[2]), vectorEncoder.PositionCount); } } diff --git a/src/ModelBuilder/Mocassin.UI.Xml/Helper/MslHelper.cs b/src/ModelBuilder/Mocassin.UI.Xml/Helper/MslHelper.cs new file mode 100644 index 00000000..09fb3916 --- /dev/null +++ b/src/ModelBuilder/Mocassin.UI.Xml/Helper/MslHelper.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using System.Numerics; +using System.Runtime.InteropServices.ComTypes; +using System.Text.RegularExpressions; +using Mocassin.Mathematics.ValueTypes; +using Mocassin.Model.DataManagement; +using Mocassin.Model.ModelProject; +using Mocassin.Model.Translator; +using Mocassin.Model.Translator.Database.Entities.Other.Meta; +using Mocassin.Model.Translator.ModelContext; +using Mocassin.UI.Data.Base; +using Mocassin.UI.Data.Main; + +namespace Mocassin.UI.Data.Helper +{ + /// + /// Provides helper methods for dealing with entities from or translating them back + /// to data objects + /// + public static class MslHelper + { + /// + /// Restores the using the project XML on the provided + /// and model provider function + /// + /// + /// + /// + public static IModelProject RestoreModelProject(SimulationJobPackageModel jobPackage, Func modelProjectProviderFunc) + { + var project = modelProjectProviderFunc.Invoke(); + var dataObj = ProjectDataObject.CreateFromXml(jobPackage.ProjectXml); + var modelPushResult = project.InputPipeline.PushToProject(dataObj.ProjectModelData.GetInputSequence()); + if (modelPushResult.Any(x => !x.IsGood)) throw new InvalidOperationException("The project Xml is damaged or invalid."); + dataObj.ProjectCustomizationTemplate.PushToModel(project); + return project; + } + + /// + /// Restores the using the project XML on the provided + /// and a default build + /// + /// + /// + public static IModelProject RestoreModelProject(SimulationJobPackageModel jobPackage) => RestoreModelProject(jobPackage, ModelProjectFactory.CreateDefault); + + /// + /// Restores the using the project XML on the provided + /// and model provider function + /// + /// + /// + /// + public static IProjectModelContext RestoreModelContext(SimulationJobPackageModel jobPackage, Func modelProjectProviderFunc) + { + var project = RestoreModelProject(jobPackage, modelProjectProviderFunc); + var contextBuilder = new ProjectModelContextBuilder(project); + return contextBuilder.Build(); + } + + /// + /// Restores the using the project XML on the provided + /// and a default build + /// + /// + /// + public static IProjectModelContext RestoreModelContext(SimulationJobPackageModel jobPackage) => RestoreModelContext(jobPackage, ModelProjectFactory.CreateDefault); + + /// + /// Parses the that describes the supercell size A,B,C,P from a with an optional flag to ignore the 4th dimension + /// + /// + /// + /// + public static Vector4I ParseLatticeSizeInfo(IJobMetaData jobMetaData, bool ignoreDimension4 = false) + { + var split = jobMetaData.LatticeInfo.Split(','); + return split.Length switch + { + 3 when ignoreDimension4 => new Vector4I(int.Parse(split[0]), int.Parse(split[1]), int.Parse(split[2]), 0), + 4 when !ignoreDimension4 => new Vector4I(int.Parse(split[0]), int.Parse(split[1]), int.Parse(split[2]), int.Parse(split[3])), + _ => throw new FormatException($"The string {jobMetaData.LatticeInfo} could not be parsed.") + }; + } + } +} \ No newline at end of file