// Copyright (C) Stichting Deltares 2018. All rights reserved. // // This file is part of the application DAM - UI. // // DAM - UI is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // // All names, logos, and references to "Deltares" are registered trademarks of // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. using System; using System.Collections.Generic; using Deltares.Dam.Data; using Deltares.Dam.Data.DamEngineIo; using Deltares.DamEngine.Io; using Deltares.DamEngine.Io.XmlInput; using Deltares.Geometry; using Deltares.Geotechnics; using Deltares.Geotechnics.Soils; using Deltares.Geotechnics.SurfaceLines; using Deltares.Standard.EventPublisher; using KellermanSoftware.CompareNetObjects; using NUnit.Framework; using Location = Deltares.Dam.Data.Location; using Segment = Deltares.Dam.Data.Segment; using Soil = Deltares.Geotechnics.Soils.Soil; using SoilProfile1D = Deltares.Geotechnics.Soils.SoilProfile1D; using Deltares.Dam.Data.Sensors; namespace Deltares.Dam.Tests.DamEngineIo { [TestFixture] public class FillXmlInputFromDamUiTests { const AnalysisType expectedAnalysisType = AnalysisType.AdaptGeometry; const AnalysisType notExpectedAnalysisType = AnalysisType.NoAdaption; [Test] public void CanWriteAndReadDamProjectDataToXmlFile() { const string inputFilename = "InputFile.xml"; DamProject.ProjectMap = "test project map"; DamProjectData expectedDamProjectData = CreateExampleDamProjectData(); // Write input file Input input = FillXmlInputFromDamUi.CreateInput(expectedDamProjectData); DamXmlSerialization.SaveInputAsXmlFile(inputFilename, input); // Init static that is to be loaded with not expected value DamProjectCalculationSpecification.SelectedAnalysisType = notExpectedAnalysisType; // Load input file input = DamXmlSerialization.LoadInputFromXmlFile(inputFilename); DamProjectData actualDamProjectData = FillDamUiFromXmlInput.CreateDamProjectData(input); CompareDamProjectData(actualDamProjectData, expectedDamProjectData); } [Test] public void CanWriteAndReadDamProjectDataToXmlString() { DataEventPublisher.IsDataEventPublishStopped = true; DamProjectData expectedDamProjectData = CreateExampleDamProjectData(); // Write input string Input input = FillXmlInputFromDamUi.CreateInput(expectedDamProjectData); string inputXml = DamXmlSerialization.SaveInputAsXmlString(input); // Init static that is to be loaded with not expected value DamProjectCalculationSpecification.SelectedAnalysisType = notExpectedAnalysisType; // Load input string input = DamXmlSerialization.LoadInputFromXmlString(inputXml); DamProjectData actualDamProjectData = FillDamUiFromXmlInput.CreateDamProjectData(input); CompareDamProjectData(actualDamProjectData, expectedDamProjectData); } private DamProjectData CreateExampleDamProjectData() { var damProjectData = new DamProjectData(); DamProject.ProjectMap = @"D:\TestDamFolder\Sub"; FillAnalysisSpecification(damProjectData); FillStabilityParameters(damProjectData); damProjectData.WaterBoard = new WaterBoard(); damProjectData.WaterBoard.Dikes = new List(); damProjectData.WaterBoard.Dikes.Add(new Dike()); damProjectData.MaxCalculationCores = 3; Dike dike = damProjectData.WaterBoard.Dikes[0]; var surfaceLines = CreateSurfaceLines(); FillSoils(dike); FillAquiferSoils(dike.SoilList); FillSoilProfiles1D(dike); FillSegments(damProjectData); AddLocations(dike, surfaceLines, damProjectData.WaterBoard.Segments); foreach (LocationJob locationJob in damProjectData.LocationJobs) { locationJob.Run = true; } FillInputTimeSeries(damProjectData); FillSensorData(damProjectData); return damProjectData; } private void FillSensorData(DamProjectData damProjectData) { damProjectData.SensorData = new SensorData(); // SensorLocations, Sensors and SensorGroups are automatically created var sensorData = damProjectData.SensorData; var sensor1 = new Data.Sensors.Sensor() { ID = 1, RelativeLocation = 12.2, Type = SensorType.WaterLevel, PLLineMappings = new[] { PLLineType.PL1 } }; sensorData.Sensors.Add(sensor1); var sensor2 = new Data.Sensors.Sensor() { ID = 2, RelativeLocation = 24.2, Type = SensorType.PolderLevel, PLLineMappings = new[] { PLLineType.PL1 } }; sensorData.Sensors.Add(sensor2); var sensorGroup1 = new Group() { ID = 1, SensorArray = new Data.Sensors.Sensor[] { sensor1, sensor2 } }; sensorData.SensorGroups.Add(sensorGroup1); var sensorLocation1 = new Data.Sensors.SensorLocation() { Location = damProjectData.WaterBoard.Dikes[0].Locations[0], Group = sensorGroup1, SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.LocationData, SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.LocationData, SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.Sensor, SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor, SourceTypePl3 = DataSourceTypeSensors.Sensor, SourceTypePl4 = DataSourceTypeSensors.Sensor, SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.LocationData, SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.LocationData }; damProjectData.WaterBoard.Dikes[0].Locations[0].SensorData = sensorLocation1; sensorData.SensorLocations.Add(sensorLocation1); var sensor3 = new Data.Sensors.Sensor() { ID = 3, RelativeLocation = 8.8, Type = SensorType.PiezometricHead, PLLineMappings = new[] { PLLineType.PL3, PLLineType.PL4 } }; sensorData.Sensors.Add(sensor3); var sensorGroup2 = new Group() { ID = 2, SensorArray = new Data.Sensors.Sensor[] { sensor3 } }; sensorData.SensorGroups.Add(sensorGroup2); var sensorLocation2 = new Data.Sensors.SensorLocation() { Location = damProjectData.WaterBoard.Dikes[0].Locations[0], Group = sensorGroup1, SourceTypePl1PlLineOffsetBelowDikeTopAtRiver = DataSourceTypeSensors.LocationData, SourceTypePl1PlLineOffsetBelowDikeTopAtPolder = DataSourceTypeSensors.LocationData, SourceTypePl1WaterLevelAtPolder = DataSourceTypeSensors.Sensor, SourceTypePl1WaterLevelAtRiver = DataSourceTypeSensors.Sensor, SourceTypePl3 = DataSourceTypeSensors.Sensor, SourceTypePl4 = DataSourceTypeSensors.Sensor, SourceTypePl1PlLineOffsetBelowDikeToeAtPolder = DataSourceTypeSensors.LocationData, SourceTypePl1PlLineOffsetBelowShoulderBaseInside = DataSourceTypeSensors.LocationData }; damProjectData.WaterBoard.Dikes[0].Locations[2].SensorData = sensorLocation2; sensorData.SensorLocations.Add(sensorLocation2); } private void FillInputTimeSeries(DamProjectData damProjectData) { const int timeSeriesCount = 2; const int timeEntriesCount = 3; const string idWaterLevel = "WaterLevel"; const string idWaterPressure = "WaterPressure"; damProjectData.InputTimeSerieCollection = new TimeSerieCollection(); for (int i = 0; i < timeSeriesCount; i++) { string locationId = String.Format("location{0}", i); var timeSerie = damProjectData.InputTimeSerieCollection.AddNewSeries(locationId); timeSerie.ParameterId = (i % 2 == 0) ? idWaterLevel : idWaterPressure; timeSerie.ForecastDateTime = DateTime.Now; timeSerie.Type = "instantaneous"; timeSerie.StartDateTime = new DateTime(2012, 12, 31); timeSerie.EndDateTime = new DateTime(2012, 12, 31, 1, 0, 0); timeSerie.MissVal = -9999.0; timeSerie.LongName = timeSerie.LocationId + "long"; timeSerie.StationName = String.Format("station{0}", i); timeSerie.Units = "m"; timeSerie.SourceOrganisation = String.Format("organisation{0}", i); timeSerie.SourceSystem = String.Format("system{0}", i); timeSerie.FileDescription = String.Format("filedescription{0}", i); timeSerie.Region = String.Format("region{0}", i); if ((i % 2 == 0)) { timeSerie.TimeStep.Multiplier = 3600; timeSerie.TimeStep.Unit = TimeStepUnit.Second; } else { timeSerie.TimeStep.Divider = 24; timeSerie.TimeStep.Unit = TimeStepUnit.Day; } for (int j = 0; j < timeEntriesCount; j++) { Stochast stochastValue = new Stochast() { Mean = 1.0 * j, Distribution = j, StandardDeviation = 0.1 * j }; timeSerie.Entries.Add(new TimeSerieEntry { DateTime = new DateTime(2012, 12, 31, 1, j * 10, 0), Value = j, Flag = 1, BasisFileName = String.Format("BasisFileName{0}", i), RelativeCalculationPathName = String.Format("RelativeCalculationPathName{0}", i), StochastValue = stochastValue }); } } } private void FillAquiferSoils(SoilList soilList) { for (int i = 0; i < soilList.Soils.Count; i++) { // All even indeces are set to true, all odd indices are set to false soilList.AquiferDictionary.Add(soilList.Soils[i], (i % 2) == 0); } } private static void FillAnalysisSpecification(DamProjectData damProjectData) { damProjectData.DamProjectType = DamProjectType.Design; damProjectData.DamProjectCalculationSpecification = new DamProjectCalculationSpecification(); DamProjectCalculationSpecification.SelectedAnalysisType = expectedAnalysisType; var calculationSpecification = new DamFailureMechanismeCalculationSpecification(); calculationSpecification.FailureMechanismSystemType = FailureMechanismSystemType.Piping; calculationSpecification.CalculationModel = PipingModelType.Bligh; damProjectData.DamProjectCalculationSpecification.DamCalculationSpecifications.Add(calculationSpecification); } private static void FillStabilityParameters(DamProjectData damProjectData) { // Note: DamProjectCalculationSpecification created and filled by FillAnalysisSpecification var curspec = damProjectData.DamProjectCalculationSpecification.CurrentSpecification; curspec.FailureMechanismeParamatersMStab = new FailureMechanismeParamatersMStab { MStabParameters = new MStabParameters { SearchMethod = MStabSearchMethod.Grid, SlipCircleDefinition = new SlipCircleDefinition { GridSizeDetermination = GridSizeDetermination.Specified, BishopGridHorizontalPointCount = 4, BishopGridHorizontalPointDistance = 1.2, BishopGridVerticalPointCount = 5, BishopGridVerticalPointDistance = 1.1, BishopTangentLinesDefinition = TangentLinesDefinition.Specified, BishopTangentLinesDistance = 0.25, UpliftVanLeftGridHorizontalPointCount = 6, UpliftVanLeftGridHorizontalPointDistance = 0.7, UpliftVanLeftGridVerticalPointCount = 3, UpliftVanLeftGridVerticalPointDistance = 1.3, UpliftVanRightGridHorizontalPointCount = 8, UpliftVanRightGridHorizontalPointDistance = 1.76, UpliftVanRightGridVerticalPointCount = 11, UpliftVanRightGridVerticalPointDistance = 0.14, UpliftVanTangentLinesDefinition = TangentLinesDefinition.OnBoundaryLines, UpliftVanTangentLinesDistance = 0.01 } } }; } private void FillSoils(Dike dike) { const int soilCount = 3; dike.SoilList = new SoilList(); for (int i = 0; i < soilCount; i++) { Soil soil = new Soil() { Name = String.Format("Soil {0}", i) }; soil.AbovePhreaticLevel = 7 + 0.1 * i; soil.BelowPhreaticLevel = 8 + 0.1 * i; soil.DryUnitWeight = 9 + 0.1 * i; soil.BeddingAngle = 18 + 0.1 * i; soil.DiameterD70 = 19 + 0.1 * i; soil.DiameterD90 = 20 + 0.1 * i; soil.PermeabKx = 21 + 0.1 * i; soil.WhitesConstant = 22 + 0.1 * i; soil.ShearStrengthModel = ShearStrengthModel.CuCalculated; soil.UseDefaultShearStrengthModel = false; soil.Cohesion = 23 + 0.1 * i; soil.FrictionAngle = 24 + 0.1 * i; soil.OCR = 25 + 0.1 * i; soil.RestSlope = 26 + 0.1 * i; soil.DilatancyType = DilatancyType.MinusPhi; soil.SoilType = ConversionHelper.ConvertToSoilType(i); dike.SoilList.Add(soil); } } private static void AddLocations(Dike dike, List surfaceLines, IList segments) { const int locationCount = 3; for (int i = 0; i < locationCount; i++) { var location = new Location(); location.Name = "Location " + (i + 1).ToString(); location.XSoilGeometry2DOrigin = 1.0 * i + 0.01; location.SoildatabaseName = "ASoildb.mdb"; location.PLLineCreationMethod = (PLLineCreationMethod) i; location.IntrusionVerticalWaterPressure = (IntrusionVerticalWaterPressureType) i; location.PolderLevel = 1.0 * i + 0.11; location.PolderLevelLow = 1.0 * i + 0.09; location.DampingFactorPL4 = 1.0 * i + 0.12; location.DampingFactorPL3 = 1.0 * i + 0.13; location.PenetrationLength = 1.0 * i + 0.14; location.PlLineOffsetBelowDikeCrestMiddle = 1.0 * i + 0.15; location.UsePlLineOffsetFactorBelowShoulderCrest = true; location.PlLineOffsetFactorBelowShoulderCrest = 1.0 * i + 0.16; location.PlLineOffsetDryBelowDikeCrestMiddle = 1.0 * i + 0.17; location.UsePlLineOffsetDryFactorBelowShoulderCrest = true; location.PlLineOffsetDryFactorBelowShoulderCrest = 1.0 * i + 0.18; location.SlopeDampingPiezometricHeightPolderSide = 1.0 * i + 0.19; location.PlLineOffsetBelowDikeTopAtRiver = 1.0 * i + 0.20; location.PlLineOffsetBelowDikeTopAtPolder = 1.0 * i + 0.21; location.PlLineOffsetBelowShoulderBaseInside = 1.0 * i + 0.22; location.PlLineOffsetBelowDikeToeAtPolder = 1.0 * i + 0.23; location.PLLineOffsetDryBelowDikeTopAtRiver = 1.0 * i + 0.24; location.PLLineOffsetDryBelowDikeTopAtPolder = 1.0 * i + 0.25; location.PLLineOffsetDryBelowShoulderBaseInside = 1.0 * i + 0.26; location.PLLineOffsetDryBelowDikeToeAtPolder = 1.0 * i + 0.27; location.HeadPL2 = 1.0 * i + 0.28; location.HeadPl3 = 1.0 * i + 0.29; location.HeadPl4 = 1.0 * i + 0.30; location.DikeTableHeight = 1.0 * i + 0.31; location.BoezemLevelHbp = 1.0 * i + 0.32; location.BoezemLevelLbp = 1.0 * i + 0.33; location.BoezemLevelTp = 1.0 * i + 0.34; location.RwBankProtectionBottomLevel = 1.0 * i + 0.35; location.DredgingDepth = 1.0 * i + 0.36; location.DetrimentFactor = 1.0 * i + 0.37; location.DikeMaterialType = SoilType.Loam; location.LocalXZSurfaceLine2 = surfaceLines[i]; location.Segment = segments[i % 2]; // alternate between the 2 available segments for (int j = 0; j < 3; j++) { var designScenario = FillDesignScenario(i, j); location.Scenarios.Add(designScenario); } location.DikeEmbankmentMaterial = "DikeMat"; location.MapForSoilGeometries2D = "TestMap"; location.StabilityZoneType = MStabZonesType.NoZones; location.ForbiddenZoneFactor = 1.23; location.ZoneAreaRestSlopeCrestWidth = 8.23; location.TrafficLoad = 11.11; location.MinimalCircleDepth = 1.21; location.RedesignDikeHeight = false; location.RedesignDikeShoulder = false; location.ShoulderEmbankmentMaterial = "ShoulderMat" + (i + 1).ToString(); ; location.StabilityShoulderGrowSlope = 10.0 * i + 0.50; location.StabilityShoulderGrowDeltaX = 10.0 * i + 0.51; location.StabilitySlopeAdaptionDeltaX = 10.0 * i + 0.52; location.SlopeAdaptionStartCotangent = 10.0 * i + 0.53; location.SlopeAdaptionEndCotangent = 10.0 * i + 0.54; location.SlopeAdaptionStepCotangent = 10.0 * i + 0.55; location.UseNewDikeTopWidth = true; location.UseNewDikeSlopeInside = true; location.UseNewDikeSlopeOutside = true; location.UseNewShoulderTopSlope = true; location.UseNewShoulderBaseSlope = true; location.UseNewMaxHeightShoulderAsFraction = true; location.UseNewMinDistanceDikeToeStartDitch = true; location.UseNewDitchDefinition = true; location.NewDikeTopWidth = 10.0 * i + 0.56; location.NewDikeSlopeInside = 10.0 * i + 0.57; location.NewDikeSlopeOutside = 10.0 * i + 0.58; location.NewShoulderTopSlope = 10.0 * i + 0.59; location.NewShoulderBaseSlope = 10.0 * i + 0.60; location.NewMaxHeightShoulderAsFraction = 10.0 * i + 0.61; location.NewMinDistanceDikeToeStartDitch = 10.0 * i + 0.62; location.UseNewDitchDefinition = true; location.NewWidthDitchBottom = 10.0 * i + 0.63; location.NewSlopeAngleDitch = 10.0 * i + 0.64; location.NewDepthDitch = 10.0 * i + 0.65; location.StabilityDesignMethod = StabilityDesignMethod.SlopeAdaptionBeforeShoulderAdaption; // ModelFactors location.ModelFactors = new ModelFactors() { RequiredSafetyFactorPiping = 10.0 * i + 0.65, RequiredSafetyFactorStabilityInnerSlope = 10.0 * i + 0.66, RequiredSafetyFactorStabilityOuterSlope = 10.0 * i + 0.67, UpliftCriterionStability = 10.0 * i + 0.68, UpliftCriterionPiping = 10.0 * i + 0.69 }; dike.Locations.Add(location); } } private static Scenario FillDesignScenario(int locationIndex, int designScenarioIndex) { int factor = locationIndex * designScenarioIndex; var designScenario = new Scenario(); designScenario.LocationScenarioID = (designScenarioIndex + 1).ToString(); designScenario.RiverLevel = 1.0 * factor + 0.51; designScenario.RiverLevelLow = 1.0 * factor + 0.52; designScenario.DikeTableHeight = 1.0 * factor + 0.53; designScenario.PlLineOffsetBelowDikeTopAtRiver = 1.0 * factor + 0.54; designScenario.PlLineOffsetBelowDikeTopAtPolder = 1.0 * factor + 0.55; designScenario.PlLineOffsetBelowShoulderBaseInside = 1.0 * factor + 0.56; designScenario.PlLineOffsetBelowDikeToeAtPolder = 1.0 * factor + 0.57; designScenario.PlLineOffsetBelowDikeCrestMiddle = 1.0 * factor + 0.58; designScenario.UsePlLineOffsetBelowDikeCrestMiddle = true; designScenario.PlLineOffsetFactorBelowShoulderCrest = 1.0 * factor + 0.59; designScenario.UsePlLineOffsetFactorBelowShoulderCrest = true; designScenario.HeadPl3 = 1.0 * factor + 0.60; designScenario.HeadPl4 = 1.0 * factor + 0.61; designScenario.UpliftCriterionStability = 1.0 * factor + 0.62; designScenario.UpliftCriterionPiping = 1.0 * factor + 0.63; designScenario.RequiredSafetyFactorStabilityInnerSlope = 1.0 * factor + 0.64; designScenario.RequiredSafetyFactorStabilityOuterSlope = 1.0 * factor + 0.65; designScenario.RequiredSafetyFactorPiping = 1.0 * factor + 0.66; return designScenario; } private List CreateSurfaceLines() { var surfaceLines = new List(); const int surfaceLineCount = 3; for (int i = 0; i < surfaceLineCount; i++) { var surfaceLine = new SurfaceLine2(); surfaceLine.Name = String.Format("SurfaceLine {0}", i); surfaceLine.CharacteristicPoints.Geometry = surfaceLine.Geometry; AddPointsToSurfaceLines(surfaceLine); surfaceLines.Add(surfaceLine); } return surfaceLines; } private void AddPointsToSurfaceLines(SurfaceLine2 surfaceLine) { AddPointToSurfaceLine(surfaceLine, 0.0, 0.0, CharacteristicPointType.SurfaceLevelOutside); AddPointToSurfaceLine(surfaceLine, 2.0, 0.5, CharacteristicPointType.None); AddPointToSurfaceLine(surfaceLine, 4.0, 0.0, CharacteristicPointType.DikeToeAtRiver); AddPointToSurfaceLine(surfaceLine, 9.0, 5.0, CharacteristicPointType.DikeTopAtRiver); AddPointToSurfaceLine(surfaceLine, 10.0, 5.2, CharacteristicPointType.None); AddPointToSurfaceLine(surfaceLine, 13.0, 5.4, CharacteristicPointType.DikeTopAtPolder); AddPointToSurfaceLine(surfaceLine, 18.0, 1.0, CharacteristicPointType.DikeToeAtPolder); AddPointToSurfaceLine(surfaceLine, 24.0, 1.0, CharacteristicPointType.SurfaceLevelInside); } private void AddPointToSurfaceLine(SurfaceLine2 surfaceLine, double xCoordinate, double zCoordinate, CharacteristicPointType characteristicPointType) { var geometryPoint = new GeometryPoint() { X = xCoordinate, Y = 0.0, Z = zCoordinate, }; surfaceLine.AddCharacteristicPoint(geometryPoint, characteristicPointType); } private static void FillSoilProfiles1D(Dike dike) { dike.SoilProfiles = new List(); const int profilesCount = 2; for (int i = 0; i < profilesCount; i++) { var profile = new SoilProfile1D(); profile.Name = "Profile1D " + (i + 1).ToString(); profile.BottomLevel = -21.12 * (i + 1); const int layerCount = 3; for (int j = 0; j < layerCount; j++) { var layer = new SoilLayer1D { Id = "Layer" + (j + 1).ToString(), Soil = dike.SoilList.Soils[j], TopLevel = 1 * -j }; if (j < 2) { layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic; layer.IsAquifer = false; } else { layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Hydrostatic; layer.IsAquifer = true; } profile.Layers.Add(layer); } dike.SoilProfiles.Add(profile); } } private static void FillSegments(DamProjectData damProjectData) { var segmentCount = 2; Dike dike = damProjectData.WaterBoard.Dikes[0]; for (int i = 0; i < segmentCount; i++) { var segment = new Segment(); segment.Name = "Segment " + i.ToString(); var soilProfileProbability = new SoilGeometryProbability(); if (i == 0) { soilProfileProbability.SegmentFailureMechanismType = FailureMechanismSystemType.StabilityInside; soilProfileProbability.SoilGeometry2DName = "Profile2D " + (i + 1).ToString(); //TODO: soilProfileProbability.SoilProfile2D = FillDamUiFromXmlInput.FindSoilProfile2DByName(damProjectData.WaterBoard.Dikes[0]., // soilProfileProbability.SoilGeometry2DName); } else { soilProfileProbability.SegmentFailureMechanismType = FailureMechanismSystemType.Piping; string soilProfile1DName = "Profile1D " + (i + 1).ToString(); soilProfileProbability.SoilProfile = FillDamUiFromXmlInput.FindSoilProfile1DByName(dike.SoilProfiles, soilProfile1DName); } soilProfileProbability.Probability = 0.003 * (i + 1); segment.SoilProfileProbabilities.Add(soilProfileProbability); damProjectData.WaterBoard.Segments.Add(segment); } } private void CompareDamProjectData(DamProjectData actual, DamProjectData expected) { var compare = new CompareLogic { Config = { MaxDifferences = 10 } }; compare.Config.MembersToIgnore = new List { "SheetPilePoint", "SheetPilePointX", "SheetPilePointY", "SheetPilePointZ", "LocalXZSheetPilePoint", "SoilbaseDB", "SoildatabaseName", "WaterBoardJob", "LocationJobs", "SelectedLocationJobs", "PickSensors", "MapForSoilGeometries2D" }; var result = compare.Compare(expected, actual); Assert.AreEqual(0, result.Differences.Count, "Differences found read/write Input object"); } } }