/// <summary>
        /// Asserts whether the <see cref="PersistableDataModel"/> contains the data
        /// that is representative for the <paramref name="calculation"/>
        /// and the <paramref name="filePath"/>.
        /// </summary>
        /// <param name="calculation">The calculation that contains the original data.</param>
        /// <param name="filePath">The file path that is used.</param>
        /// <param name="persistableDataModel">The <see cref="PersistableDataModel"/> that needs to be asserted.</param>
        /// <exception cref="AssertionException">Thrown when the data in <paramref name="persistableDataModel"/>
        /// is not correct.</exception>
        public static void AssertPersistableDataModel(MacroStabilityInwardsCalculation calculation, string filePath, PersistableDataModel persistableDataModel)
        {
            AssertProjectInfo(calculation, filePath, persistableDataModel.Info);
            AssertCalculationSettings(calculation.Output.SlidingCurve, persistableDataModel.CalculationSettings);

            IEnumerable <MacroStabilityInwardsSoilLayer2D> layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(calculation.InputParameters.SoilProfileUnderSurfaceLine.Layers);

            AssertPersistableSoils(layers, persistableDataModel.Soils.Soils);
            AssertPersistableGeometry(layers, persistableDataModel.Geometry);
            AssertPersistableSoilLayers(layers, persistableDataModel.SoilLayers, persistableDataModel.Soils.Soils, persistableDataModel.Geometry);
            AssertWaternets(new[]
            {
                DerivedMacroStabilityInwardsInput.GetWaternetDaily(calculation.InputParameters, new GeneralMacroStabilityInwardsInput()),
                DerivedMacroStabilityInwardsInput.GetWaternetExtreme(calculation.InputParameters, new GeneralMacroStabilityInwardsInput(), RoundedDouble.NaN)
            }, persistableDataModel.Waternets);
            AssertWaternetCreatorSettings(calculation.InputParameters, persistableDataModel.WaternetCreatorSettings, AssessmentSectionTestHelper.GetTestAssessmentLevel(), new[]
            {
                MacroStabilityInwardsExportStageType.Daily,
                MacroStabilityInwardsExportStageType.Extreme
            });
            AssertStates(calculation.InputParameters.SoilProfileUnderSurfaceLine, persistableDataModel.States);

            Assert.IsNull(persistableDataModel.AssessmentResults);
            Assert.IsNull(persistableDataModel.Decorations);
            Assert.IsNull(persistableDataModel.Loads);
            Assert.IsNull(persistableDataModel.NailPropertiesForSoils);
            Assert.IsNull(persistableDataModel.Reinforcements);
            Assert.IsNull(persistableDataModel.SoilCorrelations);
            Assert.IsNull(persistableDataModel.SoilVisualizations);
            Assert.IsNull(persistableDataModel.StateCorrelations);

            AssertStages(persistableDataModel.Stages, persistableDataModel.CalculationSettings, persistableDataModel.Geometry, persistableDataModel.SoilLayers,
                         persistableDataModel.Waternets, persistableDataModel.WaternetCreatorSettings, persistableDataModel.States);
        }
        public void Create_WithSoilProfile_ReturnsPersistableSoilCollection(MacroStabilityInwardsShearStrengthModel shearStrengthModel)
        {
            // Setup
            var soilProfile = new MacroStabilityInwardsSoilProfileUnderSurfaceLine(
                new[]
            {
                MacroStabilityInwardsSoilLayer2DTestFactory.CreateMacroStabilityInwardsSoilLayer2D(new[]
                {
                    MacroStabilityInwardsSoilLayer2DTestFactory.CreateMacroStabilityInwardsSoilLayer2D()
                })
            },
                Enumerable.Empty <IMacroStabilityInwardsPreconsolidationStress>());

            var registry = new MacroStabilityInwardsExportRegistry();

            IEnumerable <MacroStabilityInwardsSoilLayer2D> originalLayers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers);

            originalLayers.ForEachElementDo(layer => layer.Data.ShearStrengthModel = shearStrengthModel);

            // Call
            PersistableSoilCollection soilCollection = PersistableSoilCollectionFactory.Create(soilProfile, new IdFactory(), registry);

            // Assert
            IEnumerable <PersistableSoil> actualSoils = soilCollection.Soils;

            PersistableDataModelTestHelper.AssertPersistableSoils(originalLayers, actualSoils);

            Assert.AreEqual(actualSoils.Count(), registry.Soils.Count);
            for (var i = 0; i < originalLayers.Count(); i++)
            {
                KeyValuePair <MacroStabilityInwardsSoilLayer2D, string> registrySoil = registry.Soils.ElementAt(i);
                Assert.AreSame(originalLayers.ElementAt(i), registrySoil.Key);
                Assert.AreEqual(actualSoils.ElementAt(i).Id, registrySoil.Value);
            }
        }
        /// <summary>
        /// Creates a new instance of <see cref="PersistableSoilCollection"/>.
        /// </summary>
        /// <param name="soilProfile">The soil profile to use.</param>
        /// <param name="idFactory">The factory for creating IDs.</param>
        /// <param name="registry">The persistence registry.</param>
        /// <returns>The created <see cref="PersistableSoilCollection"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when any parameter is <c>null</c>.</exception>
        /// <exception cref="InvalidEnumArgumentException">Thrown when
        /// <see cref="MacroStabilityInwardsShearStrengthModel"/> has an invalid value.</exception>
        /// <exception cref="NotSupportedException">Thrown when <see cref="MacroStabilityInwardsShearStrengthModel"/>
        /// has a valid value but is not supported.</exception>
        public static PersistableSoilCollection Create(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfile,
                                                       IdFactory idFactory, MacroStabilityInwardsExportRegistry registry)
        {
            if (soilProfile == null)
            {
                throw new ArgumentNullException(nameof(soilProfile));
            }

            if (idFactory == null)
            {
                throw new ArgumentNullException(nameof(idFactory));
            }

            if (registry == null)
            {
                throw new ArgumentNullException(nameof(registry));
            }

            return(new PersistableSoilCollection
            {
                Soils = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers)
                        .Select(l => Create(l, idFactory, registry))
                        .ToArray()
            });
        }
Пример #4
0
        public void GetLayersRecursively_LayersNull_ReturnsEmptyCollection()
        {
            // Call
            IEnumerable <MacroStabilityInwardsSoilLayer2D> layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(null);

            // Assert
            CollectionAssert.IsEmpty(layers);
        }
        private static PersistableGeometry CreateGeometry(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfile, MacroStabilityInwardsExportStageType stageType,
                                                          IdFactory idFactory, MacroStabilityInwardsExportRegistry registry)
        {
            var geometry = new PersistableGeometry
            {
                Id     = idFactory.Create(),
                Layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers)
                         .Select(l => CreateLayer(l, stageType, idFactory, registry))
                         .ToArray()
            };

            registry.AddGeometry(stageType, geometry.Id);

            return(geometry);
        }
Пример #6
0
        private static PersistableSoilLayerCollection CreateSoilLayerCollection(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfile,
                                                                                MacroStabilityInwardsExportStageType stageType, IdFactory idFactory,
                                                                                MacroStabilityInwardsExportRegistry registry)
        {
            var soilLayerCollection = new PersistableSoilLayerCollection
            {
                Id         = idFactory.Create(),
                SoilLayers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers)
                             .Select(l => Create(l, stageType, registry))
                             .ToArray()
            };

            registry.AddSoilLayer(stageType, soilLayerCollection.Id);

            return(soilLayerCollection);
        }
        /// <summary>
        /// Asserts whether the <see cref="PersistableState"/> contains the data
        /// that is representative for the <paramref name="soilProfile"/>.
        /// </summary>
        /// <param name="soilProfile">The input that contains the original data.</param>
        /// <param name="states">The <see cref="PersistableState"/>
        /// that needs to be asserted.</param>
        /// <exception cref="AssertionException">Thrown when the data in <paramref name="states"/>
        /// is not correct.</exception>
        public static void AssertStates(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfile, IEnumerable <PersistableState> states)
        {
            Assert.AreEqual(1, states.Count());

            IEnumerable <MacroStabilityInwardsSoilLayer2D> layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers);

            for (var i = 0; i < states.Count(); i++)
            {
                PersistableState state = states.ElementAt(i);

                Assert.IsNotNull(state.Id);
                CollectionAssert.IsEmpty(state.StateLines);

                AssertPopStatePoints(layers, state.StatePoints.Where(sp => sp.Stress.StateType == PersistableStateType.Pop));
                AssertYieldStressStatePoints(layers, soilProfile.PreconsolidationStresses, state.StatePoints.Where(sp => sp.Stress.StateType == PersistableStateType.YieldStress));
            }
        }
Пример #8
0
        /// <summary>
        /// Indicator whether a <paramref name="soilProfile"/> has valid state points.
        /// </summary>
        /// <param name="soilProfile">The <see cref="IMacroStabilityInwardsSoilProfileUnderSurfaceLine"/> to get the state points from.</param>
        /// <returns><c>true</c> when every layer in <paramref name="soilProfile"/> has max. 1 state point; <c>false</c> otherwise.</returns>
        /// <exception cref="ArgumentNullException">Thrown when <paramref name="soilProfile"/> is <c>null</c>.</exception>
        public static bool HasValidStatePoints(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfile)
        {
            if (soilProfile == null)
            {
                throw new ArgumentNullException(nameof(soilProfile));
            }

            MacroStabilityInwardsSoilLayer2D[] layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers).ToArray();

            Dictionary <IMacroStabilityInwardsPreconsolidationStress, MacroStabilityInwardsSoilLayer2D> stressesWithLayers =
                soilProfile.PreconsolidationStresses.ToDictionary(pcs => pcs, pcs => GetLayerForPreconsolidationStress(layers, pcs));

            IEnumerable <IGrouping <MacroStabilityInwardsSoilLayer2D, IMacroStabilityInwardsPreconsolidationStress> > duplicateLayers =
                stressesWithLayers.ToLookup(pair => pair.Value, pair => pair.Key).Where(x => x.Count() > 1);

            return(!duplicateLayers.Any() &&
                   stressesWithLayers.All(pair => pair.Value != null) &&
                   !stressesWithLayers.Any(stressWithLayer => stressWithLayer.Value.Data.UsePop && HasValidPop(stressWithLayer.Value.Data.Pop)));
        }
        private void ValidateData()
        {
            if (Math.Abs(calculation.InputParameters.MaximumSliceWidth - 1) > 1e-3)
            {
                LogWarning(string.Format(Resources.MacroStabilityInwardsCalculationExporter_ValidateData_DGeoSuite_only_supports_MaximumSliceWidth_one_but_calculation_has_MaximumSliceWidth_0,
                                         calculation.InputParameters.MaximumSliceWidth.ToString(null, CultureInfo.CurrentCulture)));
            }

            MacroStabilityInwardsSoilLayer2D[] layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(calculation.InputParameters.SoilProfileUnderSurfaceLine.Layers).ToArray();
            if (layers.Count(l => l.Data.IsAquifer) > 1)
            {
                LogWarning(Resources.MacroStabilityInwardsCalculationExporter_ValidateData_Multiple_aquifer_layers_not_supported_no_aquifer_layer_exported);
            }

            if (!PersistableStateHelper.HasValidStatePoints(calculation.InputParameters.SoilProfileUnderSurfaceLine))
            {
                LogWarning(Resources.MacroStabilityInwardsCalculationExporter_ValidateData_Multiple_stress_points_not_supported_no_stress_points_exported);
            }
        }
        public void Create_WithValidData_ReturnsNull()
        {
            // Setup
            var soilProfile = new MacroStabilityInwardsSoilProfileUnderSurfaceLine(new[]
            {
                MacroStabilityInwardsSoilLayer2DTestFactory.CreateMacroStabilityInwardsSoilLayer2D(new[]
                {
                    MacroStabilityInwardsSoilLayer2DTestFactory.CreateMacroStabilityInwardsSoilLayer2D()
                })
            }, Enumerable.Empty <IMacroStabilityInwardsPreconsolidationStress>());

            var registry = new MacroStabilityInwardsExportRegistry();

            // Call
            IEnumerable <PersistableGeometry> geometries = PersistableGeometryFactory.Create(soilProfile, new IdFactory(), registry);

            // Assert
            IEnumerable <MacroStabilityInwardsSoilLayer2D> layersRecursively = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers);

            PersistableDataModelTestHelper.AssertPersistableGeometry(layersRecursively, geometries);
            AssertRegistry(registry, geometries, layersRecursively);
        }
Пример #11
0
        private static PersistableState Create(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfile, MacroStabilityInwardsExportStageType stageType,
                                               IdFactory idFactory, MacroStabilityInwardsExportRegistry registry)
        {
            MacroStabilityInwardsSoilLayer2D[] layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfile.Layers).ToArray();

            var statePoints = new List <PersistableStatePoint>();

            if (PersistableStateHelper.HasValidStatePoints(soilProfile))
            {
                statePoints.AddRange(layers.Where(l => l.Data.UsePop && PersistableStateHelper.HasValidPop(l.Data.Pop))
                                     .Select(l => CreatePOPStatePoint(l, stageType, idFactory, registry))
                                     .ToArray());

                var preconsolidationStressPoints = new List <PersistableStatePoint>();

                foreach (IMacroStabilityInwardsPreconsolidationStress preconsolidationStress in soilProfile.PreconsolidationStresses)
                {
                    MacroStabilityInwardsSoilLayer2D layer = PersistableStateHelper.GetLayerForPreconsolidationStress(layers, preconsolidationStress);
                    if (layer != null)
                    {
                        preconsolidationStressPoints.Add(
                            CreateYieldStressStatePoint(layer, preconsolidationStress, stageType, idFactory, registry));
                    }
                }

                statePoints.AddRange(preconsolidationStressPoints);
            }

            var state = new PersistableState
            {
                Id          = idFactory.Create(),
                StateLines  = Enumerable.Empty <PersistableStateLine>(),
                StatePoints = statePoints
            };

            registry.AddState(stageType, state.Id);

            return(state);
        }
Пример #12
0
        /// <summary>
        /// Creates a new <see cref="PersistableWaternetCreatorSettings"/>.
        /// </summary>
        /// <param name="input">The input to use.</param>
        /// <param name="idFactory">The factory for creating IDs.</param>
        /// <param name="registry">The persistence registry.</param>
        /// <param name="stageType">The stage type.</param>
        /// <returns>The created <see cref="PersistableWaternetCreatorSettings"/>.</returns>
        /// <exception cref="InvalidEnumArgumentException">Thrown when <see cref="IMacroStabilityInwardsWaternetInput.DikeSoilScenario"/>
        /// has an invalid value for <see cref="MacroStabilityInwardsDikeSoilScenario"/>.</exception>
        /// <exception cref="NotSupportedException">Thrown when <see cref="IMacroStabilityInwardsWaternetInput.DikeSoilScenario"/>
        /// is not supported.</exception>
        private static PersistableWaternetCreatorSettings Create(IMacroStabilityInwardsWaternetInput input, IdFactory idFactory, MacroStabilityInwardsExportRegistry registry,
                                                                 MacroStabilityInwardsExportStageType stageType)
        {
            bool isDitchPresent          = IsDitchPresent(input.SurfaceLine);
            var  waternetCreatorSettings = new PersistableWaternetCreatorSettings
            {
                Id = idFactory.Create(),
                InitialLevelEmbankmentTopWaterSide = input.MinimumLevelPhreaticLineAtDikeTopRiver,
                InitialLevelEmbankmentTopLandSide  = input.MinimumLevelPhreaticLineAtDikeTopPolder,
                AdjustForUplift = input.AdjustPhreaticLine3And4ForUplift,
                PleistoceneLeakageLengthOutwards = input.LeakageLengthOutwardsPhreaticLine3,
                PleistoceneLeakageLengthInwards  = input.LeakageLengthInwardsPhreaticLine3,
                AquiferLayerInsideAquitardLeakageLengthOutwards = input.LeakageLengthOutwardsPhreaticLine4,
                AquiferLayerInsideAquitardLeakageLengthInwards  = input.LeakageLengthInwardsPhreaticLine4,
                AquitardHeadWaterSide         = input.PiezometricHeadPhreaticLine2Outwards,
                AquitardHeadLandSide          = input.PiezometricHeadPhreaticLine2Inwards,
                MeanWaterLevel                = input.WaterLevelRiverAverage,
                IsDrainageConstructionPresent = input.DrainageConstructionPresent,
                DrainageConstruction          = new PersistablePoint(input.XCoordinateDrainageConstruction, input.ZCoordinateDrainageConstruction),
                IsDitchPresent                = isDitchPresent,
                DitchCharacteristics          = CreateDitchCharacteristics(input.SurfaceLine, isDitchPresent),
                EmbankmentCharacteristics     = CreateEmbankmentCharacteristics(input.SurfaceLine),
                EmbankmentSoilScenario        = CreateEmbankmentSoilScenario(input.DikeSoilScenario),
                IsAquiferLayerInsideAquitard  = false
            };

            IEnumerable <MacroStabilityInwardsSoilLayer2D> aquiferLayers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(input.SoilProfileUnderSurfaceLine.Layers)
                                                                           .Where(l => l.Data.IsAquifer);

            if (aquiferLayers.Count() == 1)
            {
                waternetCreatorSettings.AquiferLayerId = registry.GeometryLayers[stageType][aquiferLayers.Single()];
            }

            registry.AddWaternetCreatorSettings(stageType, waternetCreatorSettings.Id);

            return(waternetCreatorSettings);
        }
        /// <summary>
        /// Asserts whether <paramref name="actual"/> corresponds to <paramref name="soilProfileUnderSurface"/>,
        /// <paramref name="expectedName"/> and <paramref name="mapDataShouldContainAreas"/>.
        /// </summary>
        /// <param name="soilProfileUnderSurface">The <see cref="IMacroStabilityInwardsSoilProfileUnderSurfaceLine"/>
        /// that should be represented as series in <paramref name="actual"/>.</param>
        /// <param name="expectedName">The expected name of <paramref name="actual"/>.</param>
        /// <param name="mapDataShouldContainAreas">Indicator whether areas should be present.</param>
        /// <param name="actual">The actual <see cref="ChartData"/>.</param>
        /// <exception cref="AssertionException">Thrown when <paramref name="actual"/> does not correspond
        /// to <paramref name="soilProfileUnderSurface"/>, <paramref name="expectedName"/> or
        /// <paramref name="mapDataShouldContainAreas"/>.</exception>
        public static void AssertSoilProfileChartData(IMacroStabilityInwardsSoilProfileUnderSurfaceLine soilProfileUnderSurface,
                                                      string expectedName,
                                                      bool mapDataShouldContainAreas,
                                                      ChartData actual)
        {
            Assert.IsInstanceOf <ChartDataCollection>(actual);
            var soilProfileChartData = (ChartDataCollection)actual;

            MacroStabilityInwardsSoilLayer2D[] layers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(soilProfileUnderSurface?.Layers).ToArray();
            int expectedLayerCount = layers.Length;

            Assert.AreEqual(expectedLayerCount, soilProfileChartData.Collection.Count());
            Assert.AreEqual(expectedName, soilProfileChartData.Name);

            for (var i = 0; i < expectedLayerCount; i++)
            {
                var chartMultipleAreaData = soilProfileChartData.Collection.ElementAt(i) as ChartMultipleAreaData;

                Assert.IsNotNull(chartMultipleAreaData);
                Assert.AreEqual(layers.ElementAt(i).Data.MaterialName, chartMultipleAreaData.Name);
                Assert.AreEqual(mapDataShouldContainAreas, chartMultipleAreaData.Areas.Any());
            }
        }
        /// <summary>
        /// Asserts whether the <see cref="PersistableSoilLayerCollection"/> contains the data
        /// that is representative for the <paramref name="layers"/>.
        /// </summary>
        /// <param name="layers">The layers that contain the original data.</param>
        /// <param name="soilLayerCollections">The <see cref="PersistableSoilLayerCollection"/>
        /// that needs to be asserted.</param>
        /// <param name="soils">The soils that are used.</param>
        /// <param name="geometries">The geometries that are used.</param>
        /// <exception cref="AssertionException">Thrown when the data in <paramref name="soilLayerCollections"/>
        /// is not correct.</exception>
        public static void AssertPersistableSoilLayers(IEnumerable <MacroStabilityInwardsSoilLayer2D> layers, IEnumerable <PersistableSoilLayerCollection> soilLayerCollections,
                                                       IEnumerable <PersistableSoil> soils, IEnumerable <PersistableGeometry> geometries)
        {
            Assert.AreEqual(2, soilLayerCollections.Count());

            IEnumerable <MacroStabilityInwardsSoilLayer2D> originalLayers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(layers);

            for (var i = 0; i < soilLayerCollections.Count(); i++)
            {
                PersistableSoilLayerCollection soilLayerCollection = soilLayerCollections.ElementAt(i);

                Assert.IsNotNull(soilLayerCollection.Id);
                Assert.AreEqual(originalLayers.Count(), soilLayerCollection.SoilLayers.Count());

                for (var j = 0; j < originalLayers.Count(); j++)
                {
                    PersistableSoilLayer persistableSoilLayer = soilLayerCollection.SoilLayers.ElementAt(j);

                    Assert.AreEqual(soils.ElementAt(j).Id, persistableSoilLayer.SoilId);
                    Assert.AreEqual(geometries.ElementAt(i).Layers.ElementAt(j).Id, persistableSoilLayer.LayerId);
                }
            }
        }
Пример #15
0
 private IEnumerable <MacroStabilityInwardsSoilLayer2D> GetSoilLayers()
 {
     return(MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(data.InputParameters.SoilProfileUnderSurfaceLine?.Layers));
 }
Пример #16
0
        public void GetLayersRecursively_WithNestedLayers_ReturnsAllTopLevelAndNestedLayers()
        {
            // Setup
            var nestedLayer1 = new MacroStabilityInwardsSoilLayer2D(
                new Ring(new List <Point2D>
            {
                new Point2D(4.0, 2.0),
                new Point2D(0.0, 2.5)
            }));

            var topLevelLayer1 = new MacroStabilityInwardsSoilLayer2D(
                new Ring(new List <Point2D>
            {
                new Point2D(0.0, 1.0),
                new Point2D(2.0, 4.0)
            }),
                new MacroStabilityInwardsSoilLayerData(),
                new[]
            {
                nestedLayer1
            });

            var doubleNestedLayer = new MacroStabilityInwardsSoilLayer2D(
                new Ring(new List <Point2D>
            {
                new Point2D(4.0, 2.0),
                new Point2D(0.0, 2.5)
            }));

            var nestedLayer2 = new MacroStabilityInwardsSoilLayer2D(
                new Ring(new List <Point2D>
            {
                new Point2D(4.0, 2.0),
                new Point2D(0.0, 2.5)
            }),
                new MacroStabilityInwardsSoilLayerData(),
                new[]
            {
                doubleNestedLayer
            });

            var topLevelLayer2 = new MacroStabilityInwardsSoilLayer2D(
                new Ring(new List <Point2D>
            {
                new Point2D(3.0, 1.0),
                new Point2D(8.0, 3.0)
            }),
                new MacroStabilityInwardsSoilLayerData(),
                new[]
            {
                nestedLayer2
            });

            MacroStabilityInwardsSoilLayer2D[] layers =
            {
                topLevelLayer1,
                topLevelLayer2
            };

            // Call
            IEnumerable <MacroStabilityInwardsSoilLayer2D> flatLayers = MacroStabilityInwardsSoilProfile2DLayersHelper.GetLayersRecursively(layers);

            // Assert
            CollectionAssert.AreEqual(new[]
            {
                topLevelLayer1,
                nestedLayer1,
                topLevelLayer2,
                nestedLayer2,
                doubleNestedLayer
            }, flatLayers);
        }