コード例 #1
0
ファイル: HSolveActiveSetup.cpp プロジェクト: csiki/MOOSE
void HSolveActive::createLookupTables()
{
    std::set< Id > caSet;
    std::set< Id > vSet;
    vector< Id > caGate;
    vector< Id > vGate;
    map< Id, unsigned int > gateSpecies;

    for ( unsigned int ig = 0; ig < gateId_.size(); ++ig )
        if ( gCaDepend_[ ig ] )
            caSet.insert( gateId_[ ig ] );
        else
            vSet.insert( gateId_[ ig ] );

    caGate.insert( caGate.end(), caSet.begin(), caSet.end() );
    vGate.insert( vGate.end(), vSet.begin(), vSet.end() );

    for ( unsigned int ig = 0; ig < caGate.size(); ++ig )
        gateSpecies[ caGate[ ig ] ] = ig;
    for ( unsigned int ig = 0; ig < vGate.size(); ++ig )
        gateSpecies[ vGate[ ig ] ] = ig;

    /*
     * Finding the smallest xmin and largest xmax across all gates' lookup
     * tables.
     *
     * # of divs is determined by finding the smallest dx (highest density).
     */
    vMin_ = numeric_limits< double >::max();
    vMax_ = numeric_limits< double >::min();
    double vDx = numeric_limits< double >::max();
    caMin_ = numeric_limits< double >::max();
    caMax_ = numeric_limits< double >::min();
    double caDx = numeric_limits< double >::max();

    double min;
    double max;
    unsigned int divs;
    double dx;

    for ( unsigned int ig = 0; ig < caGate.size(); ++ig )
    {
        min = Field< double >::get( caGate[ ig ], "min" );
        max = Field< double >::get( caGate[ ig ], "max" );
        divs = Field< unsigned int >::get( caGate[ ig ], "divs" );
        dx = ( max - min ) / divs;

        if ( min < caMin_ )
            caMin_ = min;
        if ( max > caMax_ )
            caMax_ = max;
        if ( dx < caDx )
            caDx = dx;
    }
    double caDiv = ( caMax_ - caMin_ ) / caDx;
    caDiv_ = static_cast< int >( caDiv + 0.5 ); // Round-off to nearest int.

    for ( unsigned int ig = 0; ig < vGate.size(); ++ig )
    {
        min = Field< double >::get( vGate[ ig ], "min" );
        max = Field< double >::get( vGate[ ig ], "max" );
        divs = Field< unsigned int >::get( vGate[ ig ], "divs" );
        dx = ( max - min ) / divs;

        if ( min < vMin_ )
            vMin_ = min;
        if ( max > vMax_ )
            vMax_ = max;
        if ( dx < vDx )
            vDx = dx;
    }
    double vDiv = ( vMax_ - vMin_ ) / vDx;
    vDiv_ = static_cast< int >( vDiv + 0.5 ); // Round-off to nearest int.

    caTable_ = LookupTable( caMin_, caMax_, caDiv_, caGate.size() );
    vTable_ = LookupTable( vMin_, vMax_, vDiv_, vGate.size() );

    gpu_ = GpuLookupTable(&vMin_, &vMax_, &vDiv_, vGate.size());
    //gpu_.setupTable(&vMin_);

    vector< double > A, B;
    vector< double >::iterator ia, ib;
    // double a, b;
    //~ int AMode, BMode;
    //~ bool interpolate;

    // Calcium-dependent lookup tables
    HSolveUtils::Grid caGrid( caMin_, caMax_, caDiv_ );
    //~ if ( !caGate.empty() ) {
    //~ grid.resize( 1 + caDiv_ );
    //~ double dca = ( caMax_ - caMin_ ) / caDiv_;
    //~ for ( int igrid = 0; igrid <= caDiv_; ++igrid )
    //~ grid[ igrid ] = caMin_ + igrid * dca;
    //~ }

    for ( unsigned int ig = 0; ig < caGate.size(); ++ig )
    {
        HSolveUtils::rates( caGate[ ig ], caGrid, A, B );
        //~ HSolveUtils::modes( caGate[ ig ], AMode, BMode );
        //~ interpolate = ( AMode == 1 ) || ( BMode == 1 );

        ia = A.begin();
        ib = B.begin();
        for ( unsigned int igrid = 0; igrid < caGrid.size(); ++igrid )
        {
            // Use one of the optimized forms below, instead of A and B
            // directly. Also updated reinit() accordingly (for gate state).
//            a = *ia;
//            b = *ib;

            // *ia = ( 2.0 - dt_ * b ) / ( 2.0 + dt_ * b );
            // *ib = dt_ * a / ( 1.0 + dt_ * b / 2.0 );
            // *ia = dt_ * a;
            // *ib = 1.0 + dt_ * b / 2.0;
            ++ia, ++ib;
        }

        //~ caTable_.addColumns( ig, A, B, interpolate );
        caTable_.addColumns( ig, A, B );
    }

    // Voltage-dependent lookup tables
    HSolveUtils::Grid vGrid( vMin_, vMax_, vDiv_ );
    //~ if ( !vGate.empty() ) {
    //~ grid.resize( 1 + vDiv_ );
    //~ double dv = ( vMax_ - vMin_ ) / vDiv_;
    //~ for ( int igrid = 0; igrid <= vDiv_; ++igrid )
    //~ grid[ igrid ] = vMin_ + igrid * dv;
    //~ }

    for ( unsigned int ig = 0; ig < vGate.size(); ++ig )
    {
        //~ interpolate = HSolveUtils::get< HHGate, bool >( vGate[ ig ], "useInterpolation" );
        HSolveUtils::rates( vGate[ ig ], vGrid, A, B );
        //~ HSolveUtils::modes( vGate[ ig ], AMode, BMode );
        //~ interpolate = ( AMode == 1 ) || ( BMode == 1 );

        ia = A.begin();
        ib = B.begin();
        for ( unsigned int igrid = 0; igrid < vGrid.size(); ++igrid )
        {
            // Use one of the optimized forms below, instead of A and B
            // directly. Also updated reinit() accordingly (for gate state).
//            a = *ia;
//            b = *ib;

            // *ia = ( 2.0 - dt_ * b ) / ( 2.0 + dt_ * b );
            // *ib = dt_ * a / ( 1.0 + dt_ * b / 2.0 );
            // *ia = dt_ * a;
            // *ib = 1.0 + dt_ * b / 2.0;
            ++ia, ++ib;
        }

        //~ vTable_.addColumns( ig, A, B, interpolate );
        vTable_.addColumns( ig, A, B );
        // Appending new column to lookupTable in GPU memory. 
        // The &A[0] is just to get a pointer to the A array. CUDA doesnt support std::vectors
        gpu_.addColumns(ig, &A[0], &B[0]);

    }

    // double X[999];
    // double Y[999];
    // for (int i=0; i<999; i++)
    // {
    //     X[i] = i;
    //     Y[i] = 1.0;
    // }
    // double X[] = {0.0, 0.0, 0.0, 0.0};
    // double Y[] = {1.0, 2.0, 3.0, 4.0};
    // gpu_.lookup(X, Y, 4);

    column_.reserve( gateId_.size() );
    GpuColumn_.reserve( gateId_.size() );

    for ( unsigned int ig = 0; ig < gateId_.size(); ++ig )
    {
        unsigned int species = gateSpecies[ gateId_[ ig ] ];

        LookupColumn column;
        if ( gCaDepend_[ ig ] )
            caTable_.column( species, column );
        else
            vTable_.column( species, column );

        column_.push_back( column );

        GpuColumn_.push_back(2*species);
    }

    ///////////////////!!!!!!!!!!
    unsigned int maxN = *( max_element( caCount_.begin(), caCount_.end() ) );
    caRowCompt_.resize( maxN );
    for ( unsigned int ichan = 0; ichan < channel_.size(); ++ichan )
    {
        if ( channel_[ ichan ].Zpower_ > 0.0 )
        {
            int index = caDependIndex_[ ichan ];
            if ( index == -1 )
                caRow_.push_back( 0 );
            else
                caRow_.push_back( &caRowCompt_[ index ] );
        }
    }

    gpu_.sayHi();
}
コード例 #2
0
    FdmHestonVarianceMesher::FdmHestonVarianceMesher(
        Size size,
        const boost::shared_ptr<HestonProcess> & process,
        Time maturity, Size tAvgSteps, Real epsilon)
        : Fdm1dMesher(size) {

        std::vector<Real> vGrid(size, 0.0), pGrid(size, 0.0);
        const Real df  = 4*process->theta()*process->kappa()/
                            square<Real>()(process->sigma());
        try {
            std::multiset<std::pair<Real, Real> > grid;
            
            for (Size l=1; l<=tAvgSteps; ++l) {
                const Real t = (maturity*l)/tAvgSteps;
                const Real ncp = 4*process->kappa()*std::exp(-process->kappa()*t)
                    /(square<Real>()(process->sigma())
                    *(1-std::exp(-process->kappa()*t)))*process->v0();
                const Real k = square<Real>()(process->sigma())
                    *(1-std::exp(-process->kappa()*t))/(4*process->kappa());

                const Real qMin = 0.0; // v_min = 0.0;
                const Real qMax = std::max(process->v0(),
                    k*InverseNonCentralChiSquareDistribution(
                                            df, ncp, 1000,  1e-8)(1-epsilon));

                const Real minVStep=(qMax-qMin)/(50*size);
                Real ps,p = 0.0;

                Real vTmp = qMin;
                grid.insert(std::pair<Real, Real>(qMin, epsilon));
                
                for (Size i=1; i < size; ++i) {
                    ps = (1 - epsilon - p)/(size-i);
                    p += ps;
                    const Real tmp = k*InverseNonCentralChiSquareDistribution(
                        df, ncp, 1000, 1e-8)(p);

                    const Real vx = std::max(vTmp+minVStep, tmp);
                    p = NonCentralChiSquareDistribution(df, ncp)(vx/k);
                    vTmp=vx;
                    grid.insert(std::pair<Real, Real>(vx, p));
                }
            }
            QL_REQUIRE(grid.size() == size*tAvgSteps, 
                       "something wrong with the grid size");
            
            std::vector<std::pair<Real, Real> > tp(grid.begin(), grid.end());

            for (Size i=0; i < size; ++i) {
                const Size b = (i*tp.size())/size;
                const Size e = ((i+1)*tp.size())/size;
                for (Size j=b; j < e; ++j) {
                    vGrid[i]+=tp[j].first/(e-b);
                    pGrid[i]+=tp[j].second/(e-b);
                }
            }
        } 
        catch (const Error&) {
            // use default mesh
            const Real vol = process->sigma()*
                std::sqrt(process->theta()/(2*process->kappa()));

            const Real mean = process->theta();
            const Real upperBound = std::max(process->v0()+4*vol, mean+4*vol);
            const Real lowerBound
                = std::max(0.0, std::min(process->v0()-4*vol, mean-4*vol));

            for (Size i=0; i < size; ++i) {
                pGrid[i] = i/(size-1.0);
                vGrid[i] = lowerBound + i*(upperBound-lowerBound)/(size-1.0);
            }
        }

        Real skewHint = ((process->kappa() != 0.0) 
                ? std::max(1.0, process->sigma()/process->kappa()) : 1.0);

        std::sort(pGrid.begin(), pGrid.end());
        volaEstimate_ = GaussLobattoIntegral(100000, 1e-4)(
            boost::function1<Real, Real>(
                compose(std::ptr_fun<Real, Real>(std::sqrt),
                        LinearInterpolation(pGrid.begin(), pGrid.end(),
                        vGrid.begin()))),
            pGrid.front(), pGrid.back())*std::pow(skewHint, 1.5);
        
        const Real v0 = process->v0();
        for (Size i=1; i<vGrid.size(); ++i) {
            if (vGrid[i-1] <= v0 && vGrid[i] >= v0) {
                if (std::fabs(vGrid[i-1] - v0) < std::fabs(vGrid[i] - v0))
                    vGrid[i-1] = v0;
                else
                    vGrid[i] = v0;
            }
        }

        std::copy(vGrid.begin(), vGrid.end(), locations_.begin());

        for (Size i=0; i < size-1; ++i) {
            dminus_[i+1] = dplus_[i] = vGrid[i+1] - vGrid[i];
        }
        dplus_.back() = dminus_.front() = Null<Real>();
    }