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(); }
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>(); }