using System; using System.Collections.Generic; // Class name: // // Description: // The layers and waternet lines are supposed to go from top to bottom // // Copyright (c) 2008-2010 Deltares // // Date ID Modification // 2008-08-11 Best Created // ======================================================================================================================= namespace Deltares.Stability.Calculation.Inner { public class TVertical { // Input private double[][] FDegreeOfConsolidationSoil; private TPoints[] FFreaticLine; private double FFreaticlevel = 0; private double FGammaWater = 0; private TInterfaceCalls FInterfaceCalls = null; private int FNLayers = 0; private int FNWaternetLines = 0; private TPoints[][] FPLLines; private TPoints[] FPreconStressLine; private List FSoilBuild = new List(); private List FSoilData = new List(); private double FSoillevel = 0; private TPoints[] FSurfaceLine; private List FWaterLines = new List(); private List FWaternetBuild = new List(); private double FXCoordinate = 0; private double FZCoordinate = 0; public TVertical() : base() { // FInterfaceCalls := TInterfaceCalls.Create; } public TInterfaceCalls InterfaceCalls { get { return FInterfaceCalls; } set { FInterfaceCalls = value; } } public List WaternetBuild { get { return FWaternetBuild; } } public List WaterLines { get { return FWaterLines; } } public TPoints[][] PLLines { get { return FPLLines; } set { FPLLines = value; } } public TPoints[] FreaticLine { get { return FFreaticLine; } set { FFreaticLine = value; } } public TPoints[] SurfaceLine { get { return FSurfaceLine; } set { FSurfaceLine = value; } } public TPoints[] PreconStressLine { get { return FPreconStressLine; } set { FPreconStressLine = value; } } public List SoilData { get { return FSoilData; } } public double XCoordinate { get { return FXCoordinate; } set { FXCoordinate = value; } } public double ZCoordinate { get { return FZCoordinate; } set { FZCoordinate = value; } } public double GammaWater { get { return FGammaWater; } set { FGammaWater = value; } } public double[][] DegreeOfConsolidationSoil { get { return FDegreeOfConsolidationSoil; } set { FDegreeOfConsolidationSoil = value; } } // values after FillVertical public double Freaticlevel { get { return FFreaticlevel; } set { FFreaticlevel = value; } } public double SoilLevel { get { return FSoillevel; } set { FSoillevel = value; } } // Input // ======================================================================================================================= // Date ID Modification // 2010-05-19 Best Created // Layernumber itself added // ======================================================================================================================= public int[] DetermineSoilsAbove(double AZCoor, int ALayerNumber) { int[] result; int i; int j; int LNDim; bool LFound; LNDim = 0; // The layer itself might be connected for degree of consolidation LNDim++; result = new int[LNDim]; result[LNDim - 1] = ALayerNumber; for (i = 0; i < FSoilBuild.Count; i++) { if ((FSoilBuild[i].Bottomlevel > AZCoor)) { // see if the layer is already found LFound = false; for (j = 0; j < LNDim; j++) { if ((result[j] == FSoilBuild[i].LayerNumber)) { LFound = true; break; } } // If not add the layer if (!LFound) { LNDim++; result = new int[LNDim]; result[LNDim - 1] = FSoilBuild[i].LayerNumber; } } // If } // end; return result; } // ======================================================================================================================= // Date ID Modification // 2010-04-20 Created // ======================================================================================================================= public void SetlengthWaternetBuild(int ADimension) {} // ======================================================================================================================= // Date ID Modification // 2010-04-20 Created // ======================================================================================================================= // From interface // ======================================================================================================================= // Date ID Modification // 2008-08-11 Best Created // ======================================================================================================================= public void FillVertical() { var LVerticalData = new TVerticalData(); FInterfaceCalls.DetermineVerticalData(FXCoordinate, FZCoordinate, ref LVerticalData); FNWaternetLines = FWaternetBuild.Count; //@ Unsupported function or procedure: 'Copy' FSoilBuild.Clear(); FSoilBuild.AddRange(LVerticalData.SoilData); FNLayers = FSoilBuild.Count; FSoillevel = MStabDatafunctions.ZTopAtSurface(FXCoordinate, FSurfaceLine); LVerticalData.SoilData = null; } // ======================================================================================================================= // Date ID Modification // 2010-04-20 Created // ======================================================================================================================= public void sortWaternetBuild() { for (int i = 0; i < FWaternetBuild.Count; i++) { for (int j = i; j < FWaternetBuild.Count; j++) { if (WaternetBuild[i].LineLevel < WaternetBuild[j].LineLevel) { Swapwaternetbuild(WaternetBuild, i, j); } } } } // ======================================================================================================================= // Date ID Modification // 2008-08-12 Best Created // ======================================================================================================================= // utility functions // ======================================================================================================================= // Date ID Modification // 2008-08-11 Best Created // ======================================================================================================================= public double DetermineEffectiveStress(double Az) { int InLayer = DetermineLayerNumber(Az); // total stress - PorePressure return (DetermineTotalstress(Az) - (DetermineWaternetStress(Az) + DetermineDegreeOfConsolidationSoilStress(Az, InLayer))); } public double DeterminePreLoadEffectiveStress(double AZbot, double AZTop) { return (DeterminePreLoadStress(AZbot, AZTop) - (DetermineWaternetStress(AZbot))); } public double DetermineTotalstress(double AZ) { double result; int LLayer; double lTop; double LBottom; double LSom; int LSoilNumber; double LWeight; LLayer = 0; LSom = 0; if ((FNLayers > 0)) { while ((LLayer < FNLayers)) { if ((FSoilBuild[LLayer].Toplevel > AZ)) { lTop = FSoilBuild[LLayer].Toplevel; LBottom = FSoilBuild[LLayer].Bottomlevel; LSoilNumber = FSoilBuild[LLayer].Soilnumber; if ((LBottom < AZ)) { LBottom = AZ; if (LBottom > lTop) { LBottom = lTop; } } LWeight = DetermineWeightFromlayer(lTop, LBottom, LSoilNumber); LSom = LSom + LWeight; } LLayer++; } // See if there is water on the surface LSom = LSom + DeterminePoreOnSurface(); } result = LSom; return result; } public double DeterminePreLoadStress(double AZBot, double AZTop) { double result; int LLayer; double LTop; double LBottom; double LSom; int LSoilNumber; double LWeight; LLayer = 0; LSom = 0; if ((FNLayers > 0)) { while ((LLayer < FNLayers)) { if ((FSoilBuild[LLayer].Toplevel > AZBot)) { LTop = FSoilBuild[LLayer].Toplevel; LTop = Math.Min(LTop, AZTop); LBottom = FSoilBuild[LLayer].Bottomlevel; LSoilNumber = FSoilBuild[LLayer].Soilnumber; if ((LBottom < AZBot)) { LBottom = AZBot; } if (LBottom > LTop) { LBottom = LTop; } LWeight = DetermineWeightFromlayer(LTop, LBottom, LSoilNumber); LSom = LSom + LWeight; } LLayer++; } } result = LSom; return result; } public double DetermineEffectivePassiveForce(double AY, double AK0) { const double CRad = Math.PI/180; double LSom = 0; if ((FNLayers > 0)) { bool ready = true; int LLayer = FNLayers - 1; while (ready && LLayer >= 0) { double LYTop = FSoilBuild[LLayer].Toplevel; double LYBottom = FSoilBuild[LLayer].Bottomlevel; // If bottom of the layer is below the point wanted then ready} ready = LYBottom <= AY; if (ready) { LYBottom = AY; if (LYBottom > LYTop) { LYBottom = LYTop; } } if (Math.Abs(LYTop - LYBottom) > Constants.CEpsMin) { double effTop = DetermineTotalstress(LYTop) - DetermineWaternetStress(LYTop); double effBot = DetermineTotalstress(LYBottom) - DetermineWaternetStress(LYBottom); LSom = LSom + 0.5*(effTop + effBot)*Math.Abs(LYTop - LYBottom)*(1 - Math.Sin(SoilData[FSoilBuild[LLayer].Soilnumber].Phi*CRad)); } LLayer--; } if (ready) { return LSom; } } return 0; } // ======================================================================================================================= // Date ID Modification // 2008-08-07 Best Created // ======================================================================================================================= public bool NextWaterLineIsFound(double LLastZCoor, ref double LZ, ref double LZHead) { bool result; bool LFirstfound; LFirstfound = false; if ((FFreaticlevel > LLastZCoor)) { LZ = FFreaticlevel; LZHead = FFreaticlevel; LFirstfound = true; for (int i = 0; i < FWaternetBuild.Count; i++) { if ((WaternetBuild[i].LineLevel > LLastZCoor)) { if ((WaternetBuild[i].LineLevel < LZ)) { LZ = WaternetBuild[i].LineLevel; LZHead = WaternetBuild[i].Raiselevel; } } } } result = LFirstfound; return result; } // ======================================================================================================================= // Date ID Modification // 2008-08-11 Best Created // ======================================================================================================================= public double DetermineWaternetStress(double AZ) { double result; int i; double LHeadTop; double LHeadBot; double LZTop; double LZBot; // Initialize LZTop = FFreaticlevel; LHeadTop = FFreaticlevel; LZBot = FFreaticlevel; LHeadBot = FFreaticlevel; if ((AZ > FFreaticlevel)) { // Dry so no pore pressure result = 0; } else { // Az lies below the freatic level if ((FNWaternetLines > 0)) { if ((AZ <= WaternetBuild[FNWaternetLines - 1].LineLevel)) { // Az below the bottom water net line result = (WaternetBuild[FNWaternetLines - 1].Raiselevel - AZ)*FGammaWater; } else { for (i = 0; i < FNWaternetLines; i++) { if ((AZ < WaternetBuild[i].LineLevel)) { LZTop = WaternetBuild[i].LineLevel; LHeadTop = WaternetBuild[i].Raiselevel; } if ((AZ >= WaternetBuild[i].LineLevel)) { // The first waternet below AZ is the bottomnet line LZBot = WaternetBuild[i].LineLevel; LHeadBot = WaternetBuild[i].Raiselevel; break; } } // After break result = Math.Max(0, (MStabDatafunctions.LinInpolY(LZTop, LHeadTop, LZBot, LHeadBot, AZ) - AZ))*FGammaWater; } } else { // No waterlines only phreatic level result = (FFreaticlevel - AZ)*FGammaWater; } } return result; } // ======================================================================================================================= // Date ID Modification // 2010-05-19 Created // ======================================================================================================================= public int DetermineLayerNumber(double AZ) { int result; result = GetLayerNumberFomPoint(AZ); return result; } // ======================================================================================================================= // Date ID Modification // 2008-08-11 Best Created // ======================================================================================================================= public void DetermineTopAndBottomFromLayer(double AZ, ref double AZTop, ref double AZBottom) { int i; for (i = 0; i < FNLayers; i++) { if ((FSoilBuild[i].Toplevel >= AZ) && (FSoilBuild[i].Bottomlevel <= AZ)) { AZTop = FSoilBuild[i].Toplevel; AZBottom = FSoilBuild[i].Bottomlevel; } } } // ======================================================================================================================= // Date ID Modification // 2008-08-12 Best Created // ======================================================================================================================= public double DeterminePoreOnSurface() { double result; result = 0; if ((FNLayers > 0)) { // See if there is water on the surface if ((FFreaticlevel > FSoilBuild[0].Toplevel)) { result = (FFreaticlevel - FSoilBuild[0].Toplevel)*FGammaWater; } } return result; } public double DetermineDegreeOfConsolidationSoilStress(double AZ, int AInLayer) { double result; int LLayer; int LLayerNumberFromPoint; int LLayerNumberOnPoint; double LZTop; double LZBottom; double LDOC; double LWeight; double LSom; int LSoilNumber; LSom = 0; LLayerNumberOnPoint = AInLayer; if ((LLayerNumberOnPoint >= AInLayer)) { LLayer = 0; if ((FNLayers > 0)) { while ((LLayer < FNLayers) && (FSoilBuild[LLayer].Toplevel > AZ)) { LLayerNumberFromPoint = FSoilBuild[LLayer].LayerNumber; LDOC = DegreeOfConsolidationSoil[LLayerNumberFromPoint][LLayerNumberOnPoint]; if ((LDOC < 100)) { // Only excess pore if different from 100 // Determine weight ofsoil LSoilNumber = FSoilBuild[LLayer].Soilnumber; LZTop = FSoilBuild[LLayer].Toplevel; LZBottom = FSoilBuild[LLayer].Bottomlevel; if ((LZBottom < AZ)) { LZBottom = AZ; } LWeight = DetermineEffectiveWeightFromlayer(LZTop, LZBottom, LSoilNumber); LSom = LSom + (1 - LDOC/100.0)*LWeight; } LLayer++; } } } result = LSom; return result; } // ======================================================================================================================= // Date ID Modification // 2008-08-12 Best Created // ======================================================================================================================= public double DeterminePoreFromVertQuake(double Az, double AQuakeStress, double ADOCEarthquake, double AVertEarthquakeFactor) { double LCalclevel; double result; result = 0; // Water above the slice does not add in acceleration LCalclevel = Math.Min(FSoillevel, FFreaticlevel); // Due to earth quake the hydrostatic pore pressure changes if ((LCalclevel > Az)) { result = (LCalclevel - Az)*FGammaWater*AVertEarthquakeFactor; } // invloed aanpassingen aardbevingen result = result + AQuakeStress*(1.0 - ADOCEarthquake/100.0); return result; } // ======================================================================================================================= // Date ID Modification // 2008-08-12 Best Created // ======================================================================================================================= public double DeterminCentreOfGravity(double AZ) { double result; int LLayer; double lTop; double LBottom; double LWeightSom; double LMomentSom; int LSoilNumber; double LWeight; double LMoment; LLayer = 0; result = 0; LWeightSom = 0; LMomentSom = 0; if ((FNLayers > 0)) { while ((LLayer < FNLayers) && (FSoilBuild[LLayer].Toplevel > AZ)) { lTop = FSoilBuild[LLayer].Toplevel; LBottom = FSoilBuild[LLayer].Bottomlevel; LSoilNumber = FSoilBuild[LLayer].Soilnumber; if ((LBottom < AZ)) { LBottom = AZ; } LMoment = DetermineMomentFromlayer(lTop, LBottom, LSoilNumber); LMomentSom = LMomentSom + LMoment; LWeight = DetermineWeightFromlayer(lTop, LBottom, LSoilNumber); LWeightSom = LWeightSom + LWeight; LLayer++; } } if ((LWeightSom > 0)) { result = LMomentSom/LWeightSom; } return result; } // ======================================================================================================================= // Date ID Modification // 2010-04-15 Created // ======================================================================================================================= public void FillVerticalWithWaterData() { bool FreaticIsOnWaterLine = false; double LXCoor = 0; int LnWaterlines = 0; int NIntersections = 0; var ZCoors = new double[0]; double LZRaise = 0; LXCoor = FXCoordinate; if ((FFreaticLine != null)) { Freaticlevel = MStabDatafunctions.ZTopAtSurface(LXCoor, FFreaticLine); } // First put the freatic line in the waternetlines LnWaterlines = 1; // see if waternetlines are used for (int i = 0; i < FWaterLines.Count; i++) { if ((LXCoor >= WaterLines[i].MinX) && (LXCoor <= WaterLines[i].MaxX)) { if ((WaterLines[i].PLLineNumber >= 0)) { NIntersections = 0; LZRaise = MStabDatafunctions.FindIntersectionsWithPLLine(LXCoor, PLLines[WaterLines[i].PLLineNumber]); MStabDatafunctions.FindIntersectionsWithWateline(LXCoor, WaterLines[i].Waterline, ref NIntersections, ref ZCoors); for (int j = 0; j < NIntersections; j++) { if ((Math.Abs(ZCoors[j] - Freaticlevel) < 0.011) && (Math.Abs(LZRaise - Freaticlevel) < 0.011)) { FreaticIsOnWaterLine = true; } WaternetBuild.Add(new TWaternetRecord(ZCoors[j], LZRaise)); } LnWaterlines = LnWaterlines + NIntersections; } } } if (!FreaticIsOnWaterLine) { WaternetBuild.Add(new TWaternetRecord(Freaticlevel, Freaticlevel)); } sortWaternetBuild(); } private void Swapwaternetbuild(List list, int index1, int index2) { TWaternetRecord temp = list[index1]; list[index1] = list[index2]; list[index2] = temp; } private double DetermineWeightFromlayer(double ATop, double ABottom, int ASoilNumber) { double result; if ((FFreaticlevel <= ABottom)) { // Dry result = (ATop - ABottom)*SoilData[ASoilNumber].GamDry; } else { if ((FFreaticlevel >= ATop)) { // Wet result = (ATop - ABottom)*SoilData[ASoilNumber].GamWet; } else { // In between result = (FFreaticlevel - ABottom)*SoilData[ASoilNumber].GamWet; result = result + (ATop - FFreaticlevel)*SoilData[ASoilNumber].GamDry; } } return result; } // ======================================================================================================================= // Date ID Modification // 2010-05-19 Created // ======================================================================================================================= private double DetermineEffectiveWeightFromlayer(double ATop, double ABottom, int ASoilNumber) { double result; if ((FFreaticlevel <= ABottom)) { // Dry result = (ATop - ABottom)*SoilData[ASoilNumber].GamDry; } else { if ((FFreaticlevel >= ATop)) { // Wet result = (ATop - ABottom)*(SoilData[ASoilNumber].GamWet - FGammaWater); } else { // In between result = (FFreaticlevel - ABottom)*(SoilData[ASoilNumber].GamWet - FGammaWater); result = result + (ATop - FFreaticlevel)*SoilData[ASoilNumber].GamDry; } } return result; } // ======================================================================================================================= // Description Determine moment around 0 // // Date ID Modification // 2008-08-12 Best Created // ======================================================================================================================= private double DetermineMomentFromlayer(double ATop, double ABottom, int ASoilNumber) { double result; double LDz; if ((FFreaticlevel <= ABottom)) { // Dry LDz = ATop - ABottom; // arm to 0 ax | massa | result = (ATop - 0.5*LDz)*LDz*SoilData[ASoilNumber].GamDry; } else { if ((FFreaticlevel >= ATop)) { // Wet LDz = ATop - ABottom; result = (ATop - 0.5*LDz)*LDz*SoilData[ASoilNumber].GamWet; } else { // In between LDz = ATop - FFreaticlevel; result = (ATop - 0.5*LDz)*LDz*SoilData[ASoilNumber].GamDry; LDz = FFreaticlevel - ABottom; result = result + (FFreaticlevel - 0.5*LDz)*LDz*SoilData[ASoilNumber].GamWet; } } return result; } private int GetLayerNumberFomPoint(double AZ) { int result; int i; result = -1; for (i = 0; i < FNLayers; i++) { if ((FSoilBuild[i].Toplevel >= AZ) && (FSoilBuild[i].Bottomlevel <= AZ)) { result = FSoilBuild[i].LayerNumber; break; } } return result; } } // end TVertical }