RVector TravelTimeDijkstraModelling::createGradientModel(double lBound,
                                                         double uBound){
    if (verbose_) std::cout << "Creating Gradient model ..." << std::endl;

    RVector appSlowness(getApparentSlowness());

    double smi = median(appSlowness);
    if (smi < lBound) smi = lBound * 1.1;

    double sma = max(appSlowness) / 2.0;
    if (uBound > 0.0 && sma > uBound) sma = uBound * 0.9;

    Index nModel = regionManager().parameterCount();

    RVector zmid(nModel);
    Mesh paraDomain(regionManager().paraDomain());

    int dim = paraDomain.dim() - 1;

    for (Index i = 0; i < paraDomain.cellCount() ; i++) {
        zmid[i] = paraDomain.cell(i).center()[dim];
    }

    double zmi = min(zmid);
    double zma = max(zmid);

    RVector gradModel(nModel);

    for (Index i = 0; i < gradModel.size(); i++) {
        gradModel[i] = smi * std::exp((zmid[i] - zmi) / (zma - zmi) * std::log(sma / smi));
    }

    return gradModel;
}
HarmonicModelling::HarmonicModelling( size_t nh, const RVector & tvec, bool verbose )
: ModellingBase( verbose ),
    t_( tvec ), tMin_( min( tvec ) ), tMax_( max( tvec ) ), nh_( nh ), np_( 2 * nh + 2 ) {

    regionManager().setParameterCount( np_ );
    A_.clear();
    nt_ = tvec.size();

    //! constant vector of 1 -- offset
    RVector one( nt_, 1.0 );
    A_.push_back( one ); //! const

    //! vector linearly ascending from 0 (tmin) to 1 (tmax) -- drift
    double tMin = min( tvec ), tMax = max( tvec );
    RVector tOne( ( t_ - tMin ) / ( tMax - tMin ) ); //** wieso nicht so:
//    RVector tOne( ( t_ - tMin_ ) / ( tMax_ - tMin_ ) );

    A_.push_back( tOne );

    //! harmonic functions cos/sin( n pi t )
    for ( size_t j = 1 ; j <= nh_ ; j++ ){
        one = cos( tOne * PI2 * j );
        A_.push_back( one );
        one = sin( tOne * PI2 * j );
        A_.push_back( one );
    }
}