FlexuralCompressionFiberPosition FlexuralCompressionFiberPosition; //stored value for iteration

        private double phiFactorDifferenceCalculation(double phi)
        {
            double P_nIter = phiP_n / phi;

            IStrainCompatibilityAnalysisResult nominalResult = this.GetNominalMomentResult(P_nIter, FlexuralCompressionFiberPosition);
            ConcreteCompressionStrengthResult  result        = new ConcreteCompressionStrengthResult(nominalResult, FlexuralCompressionFiberPosition, this.Section.Material.beta1);
            StrengthReductionFactorFactory     f             = new StrengthReductionFactorFactory();
            FlexuralFailureModeClassification  failureMode   = f.GetFlexuralFailureMode(result.epsilon_t, result.epsilon_ty);
            double phiActual = f.Get_phiFlexureAndAxial(failureMode, ConfinementReinforcementType, result.epsilon_t, result.epsilon_ty);

            return(phi - phiActual);
        }
        public ConcreteCompressionStrengthResult GetDesignMomentWithCompressionStrength(double phiP_n,
                                                                                        FlexuralCompressionFiberPosition FlexuralCompressionFiberPosition,
                                                                                        bool CapAxialForceAtMaximum = true)
        {
            this.phiP_n = phiP_n; //store value for iteration
            this.FlexuralCompressionFiberPosition = FlexuralCompressionFiberPosition;
            double P_o = GetMaximumForce();
            StrengthReductionFactorFactory f = new StrengthReductionFactorFactory();
            double phiAxial  = f.Get_phiFlexureAndAxial(FlexuralFailureModeClassification.CompressionControlled, ConfinementReinforcementType, 0, 0);
            double phiP_nMax = phiAxial * P_o;

            if (phiP_n > phiP_nMax)
            {
                if (CapAxialForceAtMaximum == false)
                {
                    throw new Exception("Axial forces exceeds maximum axial force.");
                }
                else
                {
                    phiP_n = phiP_n;
                }
            }

            //Estimate resistance factor to adjust from phiP_n to P_n
            double phiMin = 0.65;
            double phiMax = 0.9;

            double ConvergenceTolerance      = 0.0001;
            double targetPhiFactorDifference = 0.0;
            //Find P_n by guessing a phi-factor and calculating the result
            double phiIterated = RootFinding.Brent(new FunctionOfOneVariable(phiFactorDifferenceCalculation), phiMax, phiMin, ConvergenceTolerance, targetPhiFactorDifference);
            double P_nActual   = phiP_n / phiIterated;

            //Calculate final results using the estimated value of phi
            IStrainCompatibilityAnalysisResult nominalResult = this.GetNominalMomentResult(P_nActual, FlexuralCompressionFiberPosition);
            ConcreteCompressionStrengthResult  result        = new ConcreteCompressionStrengthResult(nominalResult, FlexuralCompressionFiberPosition, this.Section.Material.beta1);
            FlexuralFailureModeClassification  failureMode   = f.GetFlexuralFailureMode(result.epsilon_t, result.epsilon_ty);
            double phiFinal = f.Get_phiFlexureAndAxial(failureMode, ConfinementReinforcementType, result.epsilon_t, result.epsilon_ty);
            double phiM_n   = phiFinal * nominalResult.Moment;

            result.phiM_n = phiM_n;
            result.FlexuralFailureModeClassification = failureMode;
            return(result);
        }
        public List <PMPair> GetPMPairs(FlexuralCompressionFiberPosition CompressionFiberPosition, int NumberOfSteps = 50, bool IncludeResistanceFactor = true)
        {
            List <PMPair> Pairs = new List <PMPair>();
            List <SectionAnalysisResult> SectionResults = GetInteractionResults(CompressionFiberPosition, NumberOfSteps);

            foreach (var thisDistibutionResult in SectionResults)
            {
                IStrainCompatibilityAnalysisResult nominalResult = GetResult(thisDistibutionResult);
                ConcreteCompressionStrengthResult  result        = new ConcreteCompressionStrengthResult(nominalResult, CompressionFiberPosition, this.Section.Material.beta1);

                StrengthReductionFactorFactory    f           = new StrengthReductionFactorFactory();
                FlexuralFailureModeClassification failureMode = f.GetFlexuralFailureMode(result.epsilon_t, result.epsilon_ty);
                double phi;
                if (IncludeResistanceFactor == true)
                {
                    phi = f.Get_phiFlexureAndAxial(failureMode, ConfinementReinforcementType, result.epsilon_t, result.epsilon_ty);
                }
                else
                {
                    phi = 1.0;
                }

                double SignFactor = 1.0;
                //if (CompressionFiberPosition == FlexuralCompressionFiberPosition.Bottom)
                //{
                //    SignFactor = -1.0;
                //}
                double P        = thisDistibutionResult.AxialForce * phi;
                double M        = thisDistibutionResult.Moment * phi * SignFactor;
                PMPair thisPair = new PMPair(P, M);
                Pairs.Add(thisPair);
            }

            if (IncludeResistanceFactor == true)
            {
                List <PMPair> TruncatedPairs = TruncateInteractionDiagram(Pairs, CompressionFiberPosition);
                return(TruncatedPairs);
            }
            else
            {
                return(Pairs);
            }
        }