/// <summary>
    /// This procedure contains the user code. Input parameters are provided as regular arguments,
    /// Output parameters as ref arguments. You don't have to assign output parameters,
    /// they will have a default value.
    /// </summary>


    private void RunScript(List <object> Goals, bool Reset, bool Step, ref object A, ref object B, ref object C, ref object D, ref object E, ref object F)
    {
        // <Custom code>
        if (Reset)
        {
            PS      = new KangarooSolver.PhysicalSystem();
            counter = 0;
            GoalList.Clear();
            foreach (IGoal G in Goals)      //Assign indexes to the particles in each Goal:
            {
                PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                GoalList.Add(G);
            }
        }
        if (Step)
        {
            PS.SimpleStep(GoalList);
            counter++;
        }


        A = PS.GetOutput(GoalList);
        B = counter;
        C = PS.GetAllMoves(GoalList);
        D = PS.GetAllWeightings(GoalList);
        E = PS.GetPositionArray();

        var Names = new List <String> [PS.ParticleCount()];

        for (int i = 0; i < PS.ParticleCount(); i++)
        {
            Names[i] = new List <String>();
        }

        for (int i = 0; i < GoalList.Count; i++)
        {
            var  FullName = GoalList[i].ToString();
            Char splitter = '.';
            var  Name     = FullName.Split(splitter);
            if (Name[0] != "KangarooSolver")
            {
                Name = FullName.Split('_', '+');
            }
            var G = GoalList[i] as IGoal;

            for (int j = 0; j < G.PIndex.Count(); j++)
            {
                Names[G.PIndex[j]].Add(Name[2]);
            }
        }


        F = Names;
        // </Custom code>
    }
    /// <summary>
    /// This procedure contains the user code. Input parameters are provided as regular arguments,
    /// Output parameters as ref arguments. You don't have to assign output parameters,
    /// they will have a default value.
    /// </summary>
    private void RunScript(List <object> Goals, bool Reset, bool Step, ref object A, ref object B)
    {
        if (Reset)
        {
            PS      = new KangarooSolver.PhysicalSystem();
            counter = 0;
            GoalList.Clear();
            foreach (IGoal G in Goals)      //Assign indexes to the particles in each Goal:
            {
                PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                GoalList.Add(G);
            }
        }
        if (Step)
        {
            PS.Step(GoalList, true, 1);
            counter++;
        }

        A = PS.GetOutput(GoalList);
        B = counter;
    }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //-----------------------------------------------------------------INPUT----------------------------------------------------------------------------//

            List<IGoal> permanentGoals = new List<IGoal>();
            DA.GetDataList(0, permanentGoals);

            List<IGoal> loadGoals = new List<IGoal>();
            DA.GetDataList(1, loadGoals);

            double fStart = 1.0;
            DA.GetData(2, ref fStart);

            double fStep = 0.1;
            DA.GetData(3, ref fStep);

            double angle = 15.0;
            DA.GetData(4, ref angle);
            angle *= Math.PI / 180.0;

            double displ = 2.0;
            DA.GetData(5, ref displ);

            double threshold = 1e-15;
            DA.GetData(6, ref threshold);

            int equilibriumIter = 100;
            DA.GetData(7, ref equilibriumIter);

            bool opt = false;
            DA.GetData(8, ref opt);

            int maxIterations = 1000;


            //--------------------------------------------------------------CALCULATE----------------------------------------------------------------------------//

            //-------------------VALUES TO STORE----------------------------//
            //Position lists
            List<Point3d> initialPositions = new List<Point3d>();
            List<Point3d> previousPositions = new List<Point3d>();
            List<Point3d> currentPositions = new List<Point3d>();
            DataTree<Point3d> vertexPositions = new DataTree<Point3d>();

            //Goal output lists
            List<object> previousGOutput = new List<object>();
            List<object> currentGOutput = new List<object>();
            DataTree<object> outputGoals = new DataTree<object>();

            //Load factors and displacements
            List<double> loadfactors = new List<double>();
            List<double> displacementsRMS = new List<double>();


            //-------------------K2 PHYSICAL SYSTEM----------------------------//
            //Initialise Kangaroo solver
            var PS = new KangarooSolver.PhysicalSystem();
            var GoalList = new List<IGoal>();

            //Assign indexes to the particles in each Goal
            foreach (IGoal pG in permanentGoals)
            {
                PS.AssignPIndex(pG, 0.01);
                GoalList.Add(pG);
            }

            foreach (IGoal lG in loadGoals)
            {
                PS.AssignPIndex(lG, 0.01);
                GoalList.Add(lG);
            }

            //Store initial loads
            List<Vector3d> initialLoads = new List<Vector3d>();
            for (int i = 0; i < loadGoals.Count; i++)
            {
                initialLoads.Add(loadGoals[i].Move[0]);
            }


            //-------------------INITIALISE VALUE LISTS----------------------------//
            //Initial vertex positions
            Point3d[] initPos = PS.GetPositionArray();
            foreach (Point3d pt in initPos)
            {
                initialPositions.Add(pt);
                previousPositions.Add(pt);
                currentPositions.Add(pt);
            }

            //Initial goal output
            List<object> initGOutput = PS.GetOutput(GoalList);
            for (int i = 0; i < permanentGoals.Count; i++)
            {
                previousGOutput.Add(initGOutput[i]);
                currentGOutput.Add(initGOutput[i]);
            }


            //-------------------LOAD INCREMENT LOOP----------------------------//
            bool run = true;
            int iter = 0;

            double LF;
            double BLF = 0.0;
            double preRMS = 0.0;

            while (run && iter < maxIterations)
            {
                LF = fStart + (fStep * iter);
                loadfactors.Add(LF);

                //Scale load goals in each iteration
                for (int i = 0; i < loadGoals.Count; i++)
                {
                    int index = GoalList.Count - loadGoals.Count + i;
                    Vector3d scaledLoad = initialLoads[i] * LF;
                    GoalList[index] = new KangarooSolver.Goals.Unary(GoalList[index].PIndex[0], scaledLoad);
                }


                //Solve equilibrium for given load increment
                int counter = 0;
                do
                {
                    PS.Step(GoalList, true, threshold);
                    counter++;
                } while (PS.GetvSum() > threshold && counter < equilibriumIter);



                //Update value lists
                GH_Path path = new GH_Path(iter);

                //Get new equilibrium positions and update position lists
                Point3d[] newPositions = PS.GetPositionArray();

                for (int k = 0; k < initialPositions.Count; k++)
                {
                    previousPositions[k] = currentPositions[k];
                    currentPositions[k] = newPositions[k];

                    if (opt)
                    {
                        vertexPositions.Add(newPositions[k], path);
                    }
                }

                //Get new goal output and update goal output lists
                List<object> newGOutput = PS.GetOutput(GoalList);
                for (int m = 0; m < permanentGoals.Count; m++)
                {
                    previousGOutput[m] = currentGOutput[m];
                    currentGOutput[m] = newGOutput[m];

                    if (opt)
                    {
                        outputGoals.Add(newGOutput[m], path);
                    }
                }



                //Does buckling occur?
                List<Vector3d> nodalDisplacements = calcDisplacement(currentPositions, initialPositions);
                double curRMS = calcDisplacementsRMS(nodalDisplacements);
                displacementsRMS.Add(curRMS);

                bool buckled = isBuckled(curRMS, preRMS, iter, fStart, fStep, angle);
                bool deflected = isDeflectionTooBig(nodalDisplacements, displ);

                if (buckled || deflected)
                {
                    run = false;
                    BLF = LF - fStep;
                }

                //Update
                preRMS = curRMS;
                iter++;
            }


            //-----------------------FLAG BUCKLED STATE----------------------------//
            if (BLF >= 1.0)
            {
                this.Message = "Works!";
            }
            else
            {
                this.Message = "Buckles!";
            }


            //-----------------------WARNING----------------------------//
            //If the maximum number of iterations has been reached
            if (iter == maxIterations)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Buckling did not occur within " + maxIterations + " load increments. Adjust load-step");
            }


            //-----------------------UPDATE VALUE LISTS----------------------------//
            //If opt is false then add results from last two iterations
            if (!opt)
            {
                for (int i = 0; i < currentPositions.Count; i++)
                {
                    vertexPositions.Add(previousPositions[i], new GH_Path(0));
                    vertexPositions.Add(currentPositions[i], new GH_Path(1));
                }

                for (int j = 0; j < currentGOutput.Count; j++)
                {
                    outputGoals.Add(previousGOutput[j], new GH_Path(0));
                    outputGoals.Add(currentGOutput[j], new GH_Path(1));
                }

            }


            //---------------------------------------------------------------OUTPUT-------------------------------------------------------------------------------//

            DA.SetData(0, BLF);
            DA.SetDataList(1, loadfactors);
            DA.SetDataList(2, displacementsRMS);
            DA.SetDataTree(3, vertexPositions);
            DA.SetDataTree(4, outputGoals);
        }
Пример #4
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            bool           reset = false;
            List <Point3d> FixedPoint = new List <Point3d>();
            List <Curve>   BoundaryCurves = new List <Curve>();
            double         SpringStrength = 1, PullStrengthM = 1, PullStrengthC = 1;

            DA.GetData <Mesh>(0, ref M);          //获取第0个输入值
            DA.GetData <Mesh>(1, ref TargetMesh); //获取第0个输入值
            //DA.GetDataList<Point3d>(1, FV);
            DA.GetDataList <Curve>(2, BoundaryCurves);
            //DA.GetDataList<Line>(1, FL);
            // DA.GetData<int>(2, ref restLength);
            DA.GetData <double>(3, ref PullStrengthM);
            DA.GetData <double>(4, ref PullStrengthC);
            DA.GetData <double>(5, ref SpringStrength);
            DA.GetData <bool>(6, ref reset);
            DA.GetDataList <Point3d>(7, FixedPoint);

            //内部计算过程start

            //initialize the solver

            if (reset || initialized == false)
            {
                #region reset
                counter     = 0;
                PS          = new KangarooSolver.PhysicalSystem();
                Goals       = new List <IGoal>();
                initialized = true;
                //get the Mesh points and boundary status
                //数组转列表
                List <Point3d> Pts      = new List <Point3d>(M.Vertices.ToPoint3dArray());
                List <Point3d> NakedPts = new List <Point3d>();
                //var IndexList = Enumerable.Range(0, PS.ParticleCount()).ToList();
                List <int> Is      = new List <int>();
                List <int> NakedIs = new List <int>();
                bool[]     Naked   = M.GetNakedEdgePointStatus();

                for (int i = 0; i < M.Vertices.Count; i++)
                {
                    PS.AddParticle(Pts[i], 1); //add a particle for every mesh vertex
                    Is.Add(i);
                    if (Naked[i])
                    //{ Goals.Add(new KangarooSolver.Goals.Anchor(i, Pts[i], 10000)); }// fix the boundaries strongly in place
                    {
                        NakedPts.Add(Pts[i]);
                        NakedIs.Add(i);
                    }
                }
                //Goals.Add(new KangarooSolver.Goals.OnCurve(NakedPts, BoundaryCurves[0], PullStrengthC));
                Goals.Add(new KangarooSolver.Goals.OnCurve(NakedIs, BoundaryCurves[0], PullStrengthC));
                //Goals.Add(new KangarooSolver.Goals.OnMesh(Pts, TargetMesh, 1));
                Goals.Add(new KangarooSolver.Goals.OnMesh(Is, TargetMesh, PullStrengthM));
                double sum_length = 0;
                for (int i = 0; i < M.TopologyEdges.Count; i++)
                {
                    Line   line   = M.TopologyEdges.EdgeLine(i);
                    double length = line.Length;
                    sum_length += length;
                }
                double average_length = sum_length / M.TopologyEdges.Count;
                for (int i = 0; i < M.TopologyEdges.Count; i++)
                {
                    var Ends = M.TopologyEdges.GetTopologyVertices(i);

                    int Start = M.TopologyVertices.MeshVertexIndices(Ends.I)[0];
                    int End   = M.TopologyVertices.MeshVertexIndices(Ends.J)[0];
                    //for each edge, a spring with rest length average_length, and strength 1
                    //Goals.Add(new KangarooSolver.Goals.Spring(Pts[Start], Pts[End], average_length, 1));
                    Goals.Add(new KangarooSolver.Goals.Spring(Start, End, average_length, SpringStrength));
                }
                for (int j = 0; j < FixedPoint.Count; j++)
                {
                    int index = PS.FindParticleIndex(FixedPoint[j], threshold, true);
                    Goals.Add(new KangarooSolver.Goals.Anchor(index, FixedPoint[j], 10000));
                }// fix the boundaries strongly in place
                 // foreach (IGoal G in Goals)
                 //  {
                 //     PS.AssignPIndex(G, 0.01);
                 // }
                 //GH_ObjectWrapper ow=new GH_ObjectWrapper(M);
                 //var gl = new KangarooSolver.Goals.Locator(ow);
                 // Goals.Add(gl);
                 //foreach (IGoal G in Goals) //Assign indexes to the particles in each Goal:
                 //{
                 //    PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                 //    GoalList.Add(G);
                 //}
                #endregion
            }
            else
            {
                /*
                 * else
                 * {
                 *  int count = Springs.Count;
                 *
                 *  for (int i = 0; i < count; i++)
                 *  {
                 *      Spring S = Springs[i] as Spring;
                 *      Point3d Start = PS.GetPosition(S.PIndex[0]);
                 *      Point3d End = PS.GetPosition(S.PIndex[1]);
                 *
                 *      double LineLength = Start.DistanceTo(End);
                 *      if (LineLength > splitLength)
                 *      {
                 *          Point3d MidPt = 0.5 * (Start + End);
                 *          PS.AddParticle(MidPt, 1);
                 *          int newParticleIndex = PS.ParticleCount() - 1;
                 *          int endIndex = S.PIndex[1];
                 *          //set the end of the original spring to be the newly created midpoint
                 *          //and make a new spring from the midpoint to the original endpoint
                 *          S.PIndex[1] = newParticleIndex;
                 *          S.RestLength = 0.5 * LineLength;
                 *          Spring otherHalf = new Spring(newParticleIndex, endIndex, 0.5 * LineLength, 1);
                 *          Springs[i] = S;
                 *          Springs.Add(otherHalf);
                 *      }
                 *      else
                 *      {
                 *          S.RestLength += increment;
                 *          Springs[i] = S;
                 *      }
                 *  }
                 */


                //Step forward, using these goals, with multi-threading on, and stopping if the threshold is reached
                if (counter == 0 || (PS.GetvSum() > threshold && counter < 100))
                {
                    PS.Step(Goals, true, threshold);
                    double sum = PS.GetvSum();
                    counter++;
                }
                //内部计算过程end
                //Output the mesh, and how many iterations it took to converge
                //object Out = PS.GetOutput(GoalList);
                //DA.SetData(0, Out);
                M.Vertices.Clear();
                M.Vertices.AddVertices(PS.GetPositions());
            }
            DA.SetData(0, M);
            List <Point3d> pout = new List <Point3d>();
            pout = PS.GetPositions().ToList();
            DA.SetDataList(1, pout); //输出第一个输出值
            DA.SetData(2, counter);
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            Mesh           TargetMesh = new Mesh();
            List <Point3d> Points = new List <Point3d>();
            double         PullStrengthM = 100, CollideStrength = 1;
            double         radius = 1;
            bool           reset = true;
            double         k_SpecialPoint = 1, g_SpecialPoint = 1, k_SpecialCurve = 1, g_SpecialCurve = 1,
                           k_ReferCurve = 1, g_ReferCurve = 1, k_ReferSurface = 1, g_ReferSurface = 1;
            List <Point3d> SpecialPoints      = new List <Point3d>();
            List <Curve>   SpecialCurves      = new List <Curve>();
            List <Curve>   ReferCurves        = new List <Curve>();
            List <Point3d> ReferCurvePoints   = new List <Point3d>();
            List <Surface> ReferSurfaces      = new List <Surface>();
            List <Point3d> ReferSurfacePoints = new List <Point3d>();

            DA.GetData <Mesh>(0, ref TargetMesh); //获取第0个输入值
            DA.GetDataList <Point3d>(1, Points);
            DA.GetData <double>(2, ref PullStrengthM);
            DA.GetData <double>(3, ref CollideStrength);
            DA.GetData <double>(4, ref radius);
            //暂无
            DA.GetData <double>(6, ref threshold);
            DA.GetData <double>(7, ref subIteration);
            DA.GetData <double>(8, ref maxIteration);
            DA.GetData <bool>(9, ref reset);
            DA.GetDataList <Point3d>(10, SpecialPoints);
            DA.GetData <double>(11, ref k_SpecialPoint);
            DA.GetData <double>(12, ref g_SpecialPoint);
            DA.GetDataList <Curve>(13, SpecialCurves);
            DA.GetData <double>(14, ref k_SpecialCurve);
            DA.GetData <double>(15, ref g_SpecialCurve);
            DA.GetDataList <Curve>(16, ReferCurves);
            DA.GetDataList <Point3d>(17, ReferCurvePoints);
            DA.GetData <double>(18, ref k_ReferCurve);
            DA.GetData <double>(19, ref g_ReferCurve);
            DA.GetDataList <Surface>(20, ReferSurfaces);
            DA.GetDataList <Point3d>(21, ReferSurfacePoints);
            DA.GetData <double>(22, ref k_ReferSurface);
            DA.GetData <double>(23, ref g_ReferSurface);
            //内部计算过程start

            //initialize the solver

            if (reset || initialized == false)
            {
                #region reset

                counter     = 0;
                PS          = new KangarooSolver.PhysicalSystem();
                Goals       = new List <IGoal>();
                initialized = true;
                //var IndexList = Enumerable.Range(0, PS.ParticleCount()).ToList();
                //Goals.Add(new KangarooSolver.Goals.OnCurve(NakedPts, BoundaryCurves[0], PullStrengthC));
                //Goals.Add(new KangarooSolver.Goals.OnMesh(Pts, TargetMesh, 1));
                Goals.Add(new KangarooSolver.Goals.OnMesh(Points, TargetMesh, PullStrengthM));
                Goals.Add(new KangarooSolver.Goals.SphereCollide_wqs(Points, radius, CollideStrength,
                                                                     SpecialPoints, k_SpecialPoint, g_SpecialPoint,
                                                                     SpecialCurves, k_SpecialCurve, g_SpecialCurve,
                                                                     ReferCurves, ReferCurvePoints, k_ReferCurve, g_ReferCurve,
                                                                     ReferSurfaces, ReferSurfacePoints, k_ReferSurface, g_ReferSurface
                                                                     ));
                //public SphereCollide_wqs(List<Point3d> V, List<Point3d> SV, double radius, double k, double kSV0, double gSV0)
                //GoalList = new List<IGoal>();
                foreach (IGoal G in Goals)      //Assign indexes to the particles in each Goal:
                {
                    PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                    //GoalList.Add(G);
                }
                #endregion
            }
            else
            {
                //Step forward, using these goals, with multi-threading on, and stopping if the threshold is reached
                if (counter == 0 || (PS.GetvSum() > threshold && counter < 100))
                {
                    for (int i = 0; i < subIteration; i += 1)
                    {
                        PS.Step(Goals, true, threshold);
                        counter++;
                    }
                    double sum = PS.GetvSum();
                }
                //内部计算过程end
                //Output the mesh, and how many iterations it took to converge
            }
            List <Point3d> pout = new List <Point3d>();
            pout = PS.GetPositions().ToList();
            DA.SetDataList(0, pout); //输出第一个输出值
            DA.SetData(1, counter);
            List <double> brs = SphereCollide_wqs.brs;
            DA.SetDataList(2, brs); //输出气泡半径
            List <Point3d> pp = Goals[1].PPos.ToList();
            DA.SetDataList(3, pp);  //输出第一个输出值
        }
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object can be used to retrieve data from input parameters and
        /// to store data in output parameters.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            double         threshold = 1e-3, subIteration = 10, maxIteration = 100;
            Mesh           TargetMesh = new Mesh();
            List <Point3d> Points = new List <Point3d>();
            List <Curve>   BoundaryCurves = new List <Curve>();
            List <IGoal>   CurvePull = new List <IGoal>();
            List <IGoal>   MeshSpring = new List <IGoal>();
            double         PullStrengthM = 1, SpringStiffness = 1, PullStrengthC = 1;
            int            row = 1, column = 1;
            bool           reset = false, bRing = false;

            DA.GetData <Mesh>(0, ref TargetMesh); //获取第0个输入值
            DA.GetDataList <Point3d>(1, Points);
            //DA.GetDataList<Curve >(2, BoundaryCurves);
            DA.GetDataList <IGoal>(2, MeshSpring);
            DA.GetDataList <IGoal>(3, CurvePull);
            DA.GetData <double>(4, ref SpringStiffness);
            DA.GetData <double>(5, ref PullStrengthM);
            //DA.GetData<double>(5, ref PullStrengthC);
            DA.GetData <int>(6, ref row);
            column = Points.Count / row;
            DA.GetData <double>(7, ref threshold);
            DA.GetData <double>(8, ref subIteration);
            DA.GetData <double>(9, ref maxIteration);
            DA.GetData <bool>(10, ref reset);
            DA.GetData <bool>(11, ref bRing);
            //内部计算过程start
            //initialize the solver

            if (reset || initialized == false)
            {
                counter     = 0;
                PS          = new KangarooSolver.PhysicalSystem();
                Goals       = new List <IGoal>();
                initialized = true;
                //grids = new List<List<Point3d>>();
                //indexs = new List<int>();
                for (int i = 0; i < row; i++)
                {
                    //List<Point3d> ps = new List<Point3d>();
                    for (int j = 0; j < column; j++)
                    {
                        PS.AddParticle(Points[i * column + j], 1);
                    }
                }
                //拉取到目标mesh
                Goals.Add(new KangarooSolver.Goals.OnMesh(Points, TargetMesh, PullStrengthM));
                //裸露点拉到边界线
                Goals.AddRange(CurvePull);
                Goals.AddRange(MeshSpring);
                //List<IGoal> GoalList = new List<IGoal>();
                foreach (IGoal G in Goals)      //Assign indexes to the particles in each Goal:
                {
                    PS.AssignPIndex(G, 0.0001); // the second argument is the tolerance distance below which points combine into a single particle
                }
                numIGoal_in = 1 + CurvePull.Count + MeshSpring.Count;
            }
            else
            {
                //前numIGoal_in个目标不变,而杆长弹簧力跟节点位置有关
                Goals  = Goals.GetRange(0, numIGoal_in);
                Points = PS.GetPositions().ToList();
                grids  = new List <List <Point3d> >();
                for (int i = 0; i < row; i++)
                {
                    List <Point3d> ps = new List <Point3d>();
                    for (int j = 0; j < column; j++)
                    {
                        ps.Add(Points[(i * column + j)]);
                        PS.AddParticle(Points[i * column + j], 1);
                        if (bRing && j == column - 1)
                        {
                            ps.Add(Points[(i * column)]);
                        }
                    }
                    grids.Add(ps);
                }
                List <double>         length_row    = new List <double>();
                List <double>         length_column = new List <double>();
                List <List <double> > gridLengths   = new List <List <double> >();
                //计算各条多线段的长度
                for (int i = 0; i < row; i++)
                {
                    double        sumLength = 0;
                    List <double> lengths   = new List <double>();
                    for (int j = 0; j < grids[i].Count - 1; j++)
                    {
                        double length = grids[i][j].DistanceTo(grids[i][j + 1]);;
                        lengths.Add(length);
                        sumLength += length;
                    }
                    //边界线上的多线段长度之和直接固定为首次的结果就好了,避免重叠后导致长度边长
                    gridLengths.Add(lengths);
                    if (counter == 0)
                    {
                        if (i == 0)
                        {
                            length_row_start = sumLength;
                        }
                        if (i == row - 1)
                        {
                            length_row_end = sumLength;
                        }
                    }
                    else
                    {
                        if (i == 0)
                        {
                            sumLength = length_row_start;
                        }
                        if (i == row - 1)
                        {
                            sumLength = length_row_end;
                        }
                    }
                    length_row.Add(sumLength);
                }
                List <double> length_row2    = length_row.GetRange(1, row - 2);
                double        length_row_sum = (length_row.Sum() + length_row2.Sum()) / 2;
                for (int j = 0; j < grids[0].Count; j++)
                {
                    double sumLength = 0;
                    for (int i = 0; i < row - 1; i++)
                    {
                        double length = grids[i][j].DistanceTo(grids[i + 1][j]);
                        sumLength += length;
                    }
                    if (counter == 0)
                    {
                        if (j == 0)
                        {
                            length_column_start = sumLength;
                        }
                        if (j == column - 1)
                        {
                            length_column_end = sumLength;
                        }
                    }
                    else
                    {
                        if (j == 0)
                        {
                            sumLength = length_column_start;
                        }
                        if (j == row - 1)
                        {
                            sumLength = length_column_end;
                        }
                    }
                    length_column.Add(sumLength);
                }
                List <double> length_column2    = length_column.GetRange(1, column - 2);
                double        length_column_sum = (length_column.Sum() + length_column2.Sum()) / 2;
                //弹簧
                for (int i = 0; i < row; i++)
                {
                    for (int j = 0; j < grids[i].Count - 1; j++)
                    {
                        double relativeLength = (length_column[j] + length_column[j + 1]) / 2 / length_column_sum;
                        if (bRing && j == grids[i].Count - 2)
                        {
                            Goals.Add(new KangarooSolver.Goals.Spring(
                                          i * column + j, i * column, relativeLength * length_row[i] * factor, SpringStiffness * length_row.Sum() / row / length_row[i]));
                        }
                        else
                        {
                            Goals.Add(new KangarooSolver.Goals.Spring(
                                          i * column + j, i * column + j + 1, relativeLength * length_row[i] * factor, SpringStiffness * length_row.Sum() / row / length_row[i]));
                        }
                    }
                }
                //弹簧
                for (int j = 0; j < column; j++)
                {
                    for (int i = 0; i < row - 1; i++)
                    {
                        double relativeLength = (length_row[i] + length_row[i + 1]) / 2 / length_row_sum;
                        Goals.Add(new KangarooSolver.Goals.Spring(
                                      (i + 1) * column + j, i * column + j, relativeLength * length_column[j] * factor, SpringStiffness * length_column.Sum() / column / length_column[j]));
                    }
                }
                //Step forward, using these goals, with multi-threading on, and stopping if the threshold is reached
                PS = new KangarooSolver.PhysicalSystem();
                for (int i = 0; i < row; i++)
                {
                    //List<Point3d> ps = new List<Point3d>();
                    for (int j = 0; j < column; j++)
                    {
                        PS.AddParticle(Points[i * column + j], 1);
                    }
                }
                if (counter == 0 || (vSum > threshold && counter < maxIteration))
                {
                    for (int i = 0; i < subIteration; i += 1)
                    {
                        PS.Step(Goals, true, threshold);
                        counter++;
                    }
                    vSum = PS.GetvSum();
                }
                //内部计算过程end
                //Output the mesh, and how many iterations it took to converge
            }
            List <Point3d> pout = PS.GetPositions().ToList();

            DA.SetDataList(0, pout); //输出第一个输出值
            DA.SetData(1, counter);
            //List<double> ars = SphereCollide_wqs.ars;
            //DA.SetDataList(2, ars); //输出第一个输出值
            //List<Point3d> pp = Goals[1].PPos.ToList();
            // DA.SetDataList(3, pout); //输出第一个输出值
        }
Пример #7
0
        /// <summary>
        /// This is the method that actually does the work.
        /// </summary>
        /// <param name="DA">The DA object is used to retrieve from inputs and store in outputs.</param>
        protected override void SolveInstance(IGH_DataAccess DA)
        {
            //-----------------------------------------------------------------INPUT----------------------------------------------------------------------------//

            List <IGoal> permanentGoals = new List <IGoal>();

            DA.GetDataList(0, permanentGoals);

            List <IGoal> loadGoals = new List <IGoal>();

            DA.GetDataList(1, loadGoals);

            double fStart = 1.0;

            DA.GetData(2, ref fStart);

            double fStep = 0.1;

            DA.GetData(3, ref fStep);

            double angle = 15.0;

            DA.GetData(4, ref angle);
            angle *= Math.PI / 180.0;

            double displ = 2.0;

            DA.GetData(5, ref displ);

            double threshold = 1e-15;

            DA.GetData(6, ref threshold);

            int equilibriumIter = 100;

            DA.GetData(7, ref equilibriumIter);

            bool opt = false;

            DA.GetData(8, ref opt);

            int maxIterations = 1000;


            //--------------------------------------------------------------CALCULATE----------------------------------------------------------------------------//

            //-------------------VALUES TO STORE----------------------------//
            //Position lists
            List <Point3d>     initialPositions  = new List <Point3d>();
            List <Point3d>     previousPositions = new List <Point3d>();
            List <Point3d>     currentPositions  = new List <Point3d>();
            DataTree <Point3d> vertexPositions   = new DataTree <Point3d>();

            //Goal output lists
            List <object>     previousGOutput = new List <object>();
            List <object>     currentGOutput  = new List <object>();
            DataTree <object> outputGoals     = new DataTree <object>();

            //Load factors and displacements
            List <double> loadfactors      = new List <double>();
            List <double> displacementsRMS = new List <double>();


            //-------------------K2 PHYSICAL SYSTEM----------------------------//
            //Initialise Kangaroo solver
            var PS       = new KangarooSolver.PhysicalSystem();
            var GoalList = new List <IGoal>();

            //Assign indexes to the particles in each Goal
            foreach (IGoal pG in permanentGoals)
            {
                PS.AssignPIndex(pG, 0.01);
                GoalList.Add(pG);
            }

            foreach (IGoal lG in loadGoals)
            {
                PS.AssignPIndex(lG, 0.01);
                GoalList.Add(lG);
            }

            //Store initial loads
            List <Vector3d> initialLoads = new List <Vector3d>();

            for (int i = 0; i < loadGoals.Count; i++)
            {
                initialLoads.Add(loadGoals[i].Move[0]);
            }


            //-------------------INITIALISE VALUE LISTS----------------------------//
            //Initial vertex positions
            Point3d[] initPos = PS.GetPositionArray();
            foreach (Point3d pt in initPos)
            {
                initialPositions.Add(pt);
                previousPositions.Add(pt);
                currentPositions.Add(pt);
            }

            //Initial goal output
            List <object> initGOutput = PS.GetOutput(GoalList);

            for (int i = 0; i < permanentGoals.Count; i++)
            {
                previousGOutput.Add(initGOutput[i]);
                currentGOutput.Add(initGOutput[i]);
            }


            //-------------------LOAD INCREMENT LOOP----------------------------//
            bool run  = true;
            int  iter = 0;

            double LF;
            double BLF    = 0.0;
            double preRMS = 0.0;

            while (run && iter < maxIterations)
            {
                LF = fStart + (fStep * iter);
                loadfactors.Add(LF);

                //Scale load goals in each iteration
                for (int i = 0; i < loadGoals.Count; i++)
                {
                    int      index      = GoalList.Count - loadGoals.Count + i;
                    Vector3d scaledLoad = initialLoads[i] * LF;
                    GoalList[index] = new KangarooSolver.Goals.Unary(GoalList[index].PIndex[0], scaledLoad);
                }


                //Solve equilibrium for given load increment
                int counter = 0;
                do
                {
                    PS.Step(GoalList, true, threshold);
                    counter++;
                } while (PS.GetvSum() > threshold && counter < equilibriumIter);



                //Update value lists
                GH_Path path = new GH_Path(iter);

                //Get new equilibrium positions and update position lists
                Point3d[] newPositions = PS.GetPositionArray();

                for (int k = 0; k < initialPositions.Count; k++)
                {
                    previousPositions[k] = currentPositions[k];
                    currentPositions[k]  = newPositions[k];

                    if (opt)
                    {
                        vertexPositions.Add(newPositions[k], path);
                    }
                }

                //Get new goal output and update goal output lists
                List <object> newGOutput = PS.GetOutput(GoalList);
                for (int m = 0; m < permanentGoals.Count; m++)
                {
                    previousGOutput[m] = currentGOutput[m];
                    currentGOutput[m]  = newGOutput[m];

                    if (opt)
                    {
                        outputGoals.Add(newGOutput[m], path);
                    }
                }



                //Does buckling occur?
                List <Vector3d> nodalDisplacements = calcDisplacement(currentPositions, initialPositions);
                double          curRMS             = calcDisplacementsRMS(nodalDisplacements);
                displacementsRMS.Add(curRMS);

                bool buckled   = isBuckled(curRMS, preRMS, iter, fStart, fStep, angle);
                bool deflected = isDeflectionTooBig(nodalDisplacements, displ);

                if (buckled || deflected)
                {
                    run = false;
                    BLF = LF - fStep;
                }

                //Update
                preRMS = curRMS;
                iter++;
            }


            //-----------------------FLAG BUCKLED STATE----------------------------//
            if (BLF >= 1.0)
            {
                this.Message = "Works!";
            }
            else
            {
                this.Message = "Buckles!";
            }


            //-----------------------WARNING----------------------------//
            //If the maximum number of iterations has been reached
            if (iter == maxIterations)
            {
                this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "Buckling did not occur within " + maxIterations + " load increments. Adjust load-step");
            }


            //-----------------------UPDATE VALUE LISTS----------------------------//
            //If opt is false then add results from last two iterations
            if (!opt)
            {
                for (int i = 0; i < currentPositions.Count; i++)
                {
                    vertexPositions.Add(previousPositions[i], new GH_Path(0));
                    vertexPositions.Add(currentPositions[i], new GH_Path(1));
                }

                for (int j = 0; j < currentGOutput.Count; j++)
                {
                    outputGoals.Add(previousGOutput[j], new GH_Path(0));
                    outputGoals.Add(currentGOutput[j], new GH_Path(1));
                }
            }


            //---------------------------------------------------------------OUTPUT-------------------------------------------------------------------------------//

            DA.SetData(0, BLF);
            DA.SetDataList(1, loadfactors);
            DA.SetDataList(2, displacementsRMS);
            DA.SetDataTree(3, vertexPositions);
            DA.SetDataTree(4, outputGoals);
        }