Beispiel #1
0
 public OdeSolver(OdeIntegrationFct func, double y0, double x0, double x1, double end)
 {
     func_ = func;
     y0_   = y0;
     x0_   = x0;
     x1_   = x1;
     end_  = end;
 }
Beispiel #2
0
        public Concentrating1dMesher(double start, double end, int size,
                                     List <Tuple <double?, double?, bool> > cPoints,
                                     double tol = 1e-8)
            : base(size)
        {
            Utils.QL_REQUIRE(end > start, () => "end must be larger than start");

            List <double?> points = new List <double?>(), betas = new List <double?>();

            foreach (Tuple <double?, double?, bool> iter in cPoints)
            {
                points.Add(iter.Item1);
                betas.Add((iter.Item2 * (end - start)) * (iter.Item2 * (end - start)));
            }

            // get scaling factor a so that y(1) = end
            double aInit = 0.0;

            for (int i = 0; i < points.Count; ++i)
            {
                double c1 = Utils.Asinh((start - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault());
                double c2 = Utils.Asinh((end - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault());
                aInit += (c2 - c1) / points.Count;
            }

            OdeIntegrationFct fct = new OdeIntegrationFct(points, betas, tol);
            double            a   = new Brent().solve(
                new OdeSolver(fct, start, 0.0, 1.0, end),
                tol, aInit, 0.1 * aInit);

            // solve ODE for all grid points
            Vector x = new Vector(size), y = new Vector(size);

            x[0] = 0.0;
            y[0] = start;
            double dx = 1.0 / (size - 1);

            for (int i = 1; i < size; ++i)
            {
                x[i] = i * dx;
                y[i] = fct.solve(a, y[i - 1], x[i - 1], x[i]);
            }

            // eliminate numerical noise and ensure y(1) = end
            double dy = y[y.Count - 1] - end;

            for (int i = 1; i < size; ++i)
            {
                y[i] -= i * dx * dy;
            }

            LinearInterpolation odeSolution = new LinearInterpolation(x, x.Count, y);

            // ensure required points are part of the grid
            List <Pair <double?, double?> > w =
                new InitializedList <Pair <double?, double?> >(1, new Pair <double?, double?>(0.0, 0.0));

            for (int i = 0; i < points.Count; ++i)
            {
                if (cPoints[i].Item3 && points[i] > start && points[i] < end)
                {
                    int j = y.distance(y[0], y.BinarySearch(points[i].Value));

                    double e = new Brent().solve(
                        new OdeSolver2(odeSolution.value, points[i].Value),
                        Const.QL_EPSILON, x[j], 0.5 / size);

                    w.Add(new Pair <double?, double?>(Math.Min(x[size - 2], x[j]), e));
                }
            }
            w.Add(new Pair <double?, double?>(1.0, 1.0));
            w = w.OrderBy(xx => xx.first).Distinct(new equal_on_first()).ToList();

            List <double> u = new List <double>(w.Count), z = new List <double>(w.Count);

            for (int i = 0; i < w.Count; ++i)
            {
                u[i] = w[i].first.GetValueOrDefault();
                z[i] = w[i].second.GetValueOrDefault();
            }
            LinearInterpolation transform = new LinearInterpolation(u, u.Count, z);

            for (int i = 0; i < size; ++i)
            {
                locations_[i] = odeSolution.value(transform.value(i * dx));
            }

            for (int i = 0; i < size - 1; ++i)
            {
                dplus_[i] = dminus_[i + 1] = locations_[i + 1] - locations_[i];
            }
            dplus_[dplus_.Count] = null;
            dminus_[0]           = null;
        }