Example #1
0
void CRocheLobe_FF::ComputeRadii(const double pot_surface, const double separation, const double q, const double P)
{
    // Compute the radii for the pixels and corners:
    for(unsigned int i = 0; i < pixel_radii.size(); i++)
        pixel_radii[i] = ComputeRadius(pot_surface, separation, q, P, pixel_theta[i], pixel_phi[i]);

    for(unsigned int i = 0; i < corner_radii.size(); i++)
        corner_radii[i] = ComputeRadius(pot_surface, separation, q, P, corner_theta[i], corner_phi[i]);
}
Example #2
0
void CRocheLobe_FF::preRender(double & max_flux)
{
    if (!mModelReady)
        Init();

    // See if the user change the tesselation
    const unsigned int n_sides = pow(2, mParams["n_side_power"].getValue());
    if(mParams["n_side_power"].isDirty())
    {
        Init();
    }

    const double T_eff_pole = mParams["T_eff_pole"].getValue();
    const double von_zeipel_beta = mParams["von_zeipel_beta"].getValue();
    const double separation = mParams["separation"].getValue();
    const double q = mParams["q"].getValue();
    const double P = mParams["P"].getValue();
    const double F = mParams["F"].getValue();

    //printf("%lf %lf %lf %lf", q, P, F, separation);
    // First find the position of L1 point on the axis
    double r_L1 = separation * ComputeRL1(q, P);
    // Potential at L1 point
    double pot_L1, dpot_L1;
    ComputePotential(pot_L1, dpot_L1, r_L1, PI/2., 0.0, separation, q, P);
    // Potential at F surface
    double pot_surface = (pot_L1 + 0.5*q*q/(1.+q))/F - 0.5*q*q/(1.+q);

    // Compute r_pole
    double r_pole = ComputeRadius(pot_surface, separation, q, P, 0.0, 0.0);

    // Compute gravity at pole
    double g_pole, tempx, tempy, tempz;
    ComputeGravity(separation, q, P, r_pole, 0.0, 0.0, tempx, tempy, tempz, g_pole);

    // Compute Radii for all Healpix pixels
    ComputeRadii(pot_surface, separation, q, P);
    // Compute Gravity for all Healpix pixels
    ComputeGravity(separation, q, P);

    bool feature_dirty = false;
    for(auto feature: mFeatures)
        feature_dirty |= feature->isDirty();

    if(feature_dirty || mParams["T_eff_pole"].isDirty() || mParams["von_zeipel_beta"].isDirty())
        VonZeipelTemperatures(T_eff_pole, g_pole, von_zeipel_beta);

    for(auto feature: mFeatures)
        feature->apply(this);


    TemperatureToFlux(mPixelTemperatures, mFluxTexture, mWavelength, max_flux);

    GenerateVBO(n_pixels, n_sides, mVBOData);

}
Example #3
0
/// Computes the geometry of the spherical Healpix surface
void CRocheLobe_FF::GenerateModel(vector<vec3> & vbo_data,
        vector<unsigned int> & elements)
{
    const double T_eff_pole = mParams["T_eff_pole"].getValue();
    const double von_zeipel_beta = mParams["von_zeipel_beta"].getValue();
    const unsigned int n_sides = pow(2, mParams["n_side_power"].getValue());
    const double separation = mParams["separation"].getValue();
    const double q = mParams["q"].getValue();
    const double P = mParams["P"].getValue();
    const double F = mParams["F"].getValue();
    // Generate a unit Healpix sphere
    GenerateHealpixSphere(n_pixels, n_sides);

    // recomputing the sphereoid is very expensive. Make use of the dirty flags
    // to only compute that which is absolutely necessary.
    double r_L1 = separation * ComputeRL1(q, P);
    // Potential at L1 point
    double pot_L1, dpot_L1;
    ComputePotential(pot_L1, dpot_L1, r_L1, PI/2., 0.0, separation, q, P);
    // Potential at F surface
    double pot_surface = (pot_L1 + 0.5*q*q/(1.+q))/F - 0.5*q*q/(1.+q);
    // Compute r_pole
    double r_pole = ComputeRadius(pot_surface, separation, q, P, 0.0, 0.0);
    // Compute gravity at pole
    double g_pole, tempx, tempy, tempz;
    ComputeGravity(separation, q, P, r_pole, 0.0, 0.0, tempx, tempy, tempz, g_pole);
    // Compute Radii for all Healpix pixels
    ComputeRadii(pot_surface, separation, q, P);
    // Compute Gravity for all Healpix pixels
    ComputeGravity(separation, q, P);
    // Compute Temperatures for all Healpix pixels
    VonZeipelTemperatures(T_eff_pole, g_pole, von_zeipel_beta);

    for(auto feature: mFeatures)
        feature->apply(this);

    // Find the maximum temperature
    double max_temperature = 0;
    for(unsigned int i = 0; i < mPixelTemperatures.size(); i++)
    {
        if(mPixelTemperatures[i] > max_temperature)
            max_temperature = mPixelTemperatures[i];
    }

    // Convert temperatures to fluxes.
    TemperatureToFlux(mPixelTemperatures, mFluxTexture, mWavelength, max_temperature);

    GenerateVBO(n_pixels, n_sides, vbo_data);

    // Create the lookup indicies.
    GenerateHealpixVBOIndicies(n_pixels, elements);

}
Example #4
0
ConformalMap<Real>::ConformalMap (int numPoints,
    const Vector3<Real>* points, int numTriangles, const int* indices,
    int punctureTriangle)
{
    // Construct a vertex-triangle-edge representation of mesh.
    BasicMesh mesh(numPoints, points, numTriangles, indices);
    int numEdges = mesh.GetNumEdges();
    const BasicMesh::Edge* edges = mesh.GetEdges();
    const BasicMesh::Triangle* triangles = mesh.GetTriangles();

    mPlanes = new1<Vector2<Real> >(numPoints);
    mSpheres = new1<Vector3<Real> >(numPoints);

    // Construct sparse matrix A nondiagonal entries.
    typename LinearSystem<Real>::SparseMatrix AMat;
    int i, e, t, v0, v1, v2;
    Real value = (Real)0;
    for (e = 0; e < numEdges; ++e)
    {
        const BasicMesh::Edge& edge = edges[e];
        v0 = edge.V[0];
        v1 = edge.V[1];

        Vector3<Real> E0, E1;

        const BasicMesh::Triangle& T0 = triangles[edge.T[0]];
        for (i = 0; i < 3; ++i)
        {
            v2 = T0.V[i];
            if (v2 != v0 && v2 != v1)
            {
                E0 = points[v0] - points[v2];
                E1 = points[v1] - points[v2];
                value = E0.Dot(E1)/E0.Cross(E1).Length();
            }
        }

        const BasicMesh::Triangle& T1 = triangles[edge.T[1]];
        for (i = 0; i < 3; ++i)
        {
            v2 = T1.V[i];
            if (v2 != v0 && v2 != v1)
            {
                E0 = points[v0] - points[v2];
                E1 = points[v1] - points[v2];
                value += E0.Dot(E1)/E0.Cross(E1).Length();
            }
        }

        value *= -(Real)0.5;
        AMat[std::make_pair(v0, v1)] = value;
    }

    // Aonstruct sparse matrix A diagonal entries.
    Real* tmp = new1<Real>(numPoints);
    memset(tmp, 0, numPoints*sizeof(Real));
    typename LinearSystem<Real>::SparseMatrix::iterator iter = AMat.begin();
    typename LinearSystem<Real>::SparseMatrix::iterator end = AMat.end();
    for (/**/; iter != end; ++iter)
    {
        v0 = iter->first.first;
        v1 = iter->first.second;
        value = iter->second;
        assertion(v0 != v1, "Unexpected condition\n");
        tmp[v0] -= value;
        tmp[v1] -= value;
    }
    for (int v = 0; v < numPoints; ++v)
    {
        AMat[std::make_pair(v, v)] = tmp[v];
    }

    assertion(numPoints + numEdges == (int)AMat.size(),
        "Mismatch in sizes\n");

    // Construct column vector B (happens to be sparse).
    const BasicMesh::Triangle& tri = triangles[punctureTriangle];
    v0 = tri.V[0];
    v1 = tri.V[1];
    v2 = tri.V[2];
    Vector3<Real> V0 = points[v0];
    Vector3<Real> V1 = points[v1];
    Vector3<Real> V2 = points[v2];
    Vector3<Real> E10 = V1 - V0;
    Vector3<Real> E20 = V2 - V0;
    Vector3<Real> E12 = V1 - V2;
    Vector3<Real> cross = E20.Cross(E10);
    Real len10 = E10.Length();
    Real invLen10 = ((Real)1)/len10;
    Real twoArea = cross.Length();
    Real invLenCross = ((Real)1)/twoArea;
    Real invProd = invLen10*invLenCross;
    Real re0 = -invLen10;
    Real im0 = invProd*E12.Dot(E10);
    Real re1 = invLen10;
    Real im1 = invProd*E20.Dot(E10);
    Real re2 = (Real)0;
    Real im2 = -len10*invLenCross;

    // Solve sparse system for real parts.
    memset(tmp, 0, numPoints*sizeof(Real));
    tmp[v0] = re0;
    tmp[v1] = re1;
    tmp[v2] = re2;
    Real* result = new1<Real>(numPoints);
    bool solved = LinearSystem<Real>().SolveSymmetricCG(numPoints, AMat, tmp,
        result);
    assertion(solved, "Failed to solve linear system\n");
    WM5_UNUSED(solved);
    for (i = 0; i < numPoints; ++i)
    {
        mPlanes[i].X() = result[i];
    }

    // Solve sparse system for imaginary parts.
    memset(tmp, 0, numPoints*sizeof(Real));
    tmp[v0] = -im0;
    tmp[v1] = -im1;
    tmp[v2] = -im2;
    solved = LinearSystem<Real>().SolveSymmetricCG(numPoints, AMat, tmp,
        result);
    assertion(solved, "Failed to solve linear system\n");
    for (i = 0; i < numPoints; ++i)
    {
        mPlanes[i].Y() = result[i];
    }
    delete1(tmp);
    delete1(result);

    // Scale to [-1,1]^2 for numerical conditioning in later steps.
    Real fmin = mPlanes[0].X(), fmax = fmin;
    for (i = 0; i < numPoints; i++)
    {
        if (mPlanes[i].X() < fmin)
        {
            fmin = mPlanes[i].X();
        }
        else if (mPlanes[i].X() > fmax)
        {
            fmax = mPlanes[i].X();
        }
        if (mPlanes[i].Y() < fmin)
        {
            fmin = mPlanes[i].Y();
        }
        else if (mPlanes[i].Y() > fmax)
        {
            fmax = mPlanes[i].Y();
        }
    }
    Real halfRange = ((Real)0.5)*(fmax - fmin);
    Real invHalfRange = ((Real)1)/halfRange;
    for (i = 0; i < numPoints; ++i)
    {
        mPlanes[i].X() = -(Real)1 + invHalfRange*(mPlanes[i].X() - fmin);
        mPlanes[i].Y() = -(Real)1 + invHalfRange*(mPlanes[i].Y() - fmin);
    }

    // Map plane points to sphere using inverse stereographic projection.
    // The main issue is selecting a translation in (x,y) and a radius of
    // the projection sphere.  Both factors strongly influence the final
    // result.

    // Use the average as the south pole.  The points tend to be clustered
    // approximately in the middle of the conformally mapped punctured
    // triangle, so the average is a good choice to place the pole.
    Vector2<Real> origin((Real)0 ,(Real)0 );
    for (i = 0; i < numPoints; ++i)
    {
        origin += mPlanes[i];
    }
    origin /= (Real)numPoints;
    for (i = 0; i < numPoints; ++i)
    {
        mPlanes[i] -= origin;
    }

    mPlaneMin = mPlanes[0];
    mPlaneMax = mPlanes[0];
    for (i = 1; i < numPoints; ++i)
    {
        if (mPlanes[i].X() < mPlaneMin.X())
        {
            mPlaneMin.X() = mPlanes[i].X();
        }
        else if (mPlanes[i].X() > mPlaneMax.X())
        {
            mPlaneMax.X() = mPlanes[i].X();
        }

        if (mPlanes[i].Y() < mPlaneMin.Y())
        {
            mPlaneMin.Y() = mPlanes[i].Y();
        }
        else if (mPlanes[i].Y() > mPlaneMax.Y())
        {
            mPlaneMax.Y() = mPlanes[i].Y();
        }
    }

    // Select the radius of the sphere so that the projected punctured
    // triangle has an area whose fraction of total spherical area is the
    // same fraction as the area of the punctured triangle to the total area
    // of the original triangle mesh.
    Real twoTotalArea = (Real)0;
    for (t = 0; t < numTriangles; ++t)
    {
        const BasicMesh::Triangle& T0 = triangles[t];
        const Vector3<Real>& V0 = points[T0.V[0]];
        const Vector3<Real>& V1 = points[T0.V[1]];
        const Vector3<Real>& V2 = points[T0.V[2]];
        Vector3<Real> E0 = V1 - V0, E1 = V2 - V0;
        twoTotalArea += E0.Cross(E1).Length();
    }
    mRadius = ComputeRadius(mPlanes[v0], mPlanes[v1], mPlanes[v2],
        twoArea/twoTotalArea);
    Real radiusSqr = mRadius*mRadius;

    // Inverse stereographic projection to obtain sphere coordinates.  The
    // sphere is centered at the origin and has radius 1.
    for (i = 0; i < numPoints; i++)
    {
        Real rSqr = mPlanes[i].SquaredLength();
        Real mult = ((Real)1)/(rSqr + radiusSqr);
        Real x = ((Real)2)*mult*radiusSqr*mPlanes[i].X();
        Real y = ((Real)2)*mult*radiusSqr*mPlanes[i].Y();
        Real z = mult*mRadius*(rSqr - radiusSqr);
        mSpheres[i] = Vector3<Real>(x,y,z)/mRadius;
    }
}