示例#1
0
CollOfScalar EquelleRuntimeCPU::solveForUpdate(const CollOfScalar& residual) const
{
    Eigen::SparseMatrix<double, Eigen::RowMajor> matr = residual.derivative()[0];

    CollOfScalar::V du = CollOfScalar::V::Zero(residual.size());

    Opm::time::StopWatch clock;
    clock.start();

    // solve(n, # nonzero values ("val"), ptr to col indices
    // ("col_ind"), ptr to row locations in val array ("row_ind")
    // (these two may be swapped, not sure about the naming convention
    // here...), array of actual values ("val") (I guess... '*sa'...),
    // rhs, solution)
    Opm::LinearSolverInterface::LinearSolverReport rep
        = linsolver_.solve(matr.rows(), matr.nonZeros(),
                           matr.outerIndexPtr(), matr.innerIndexPtr(), matr.valuePtr(),
                           residual.value().data(), du.data());

    if (verbose_ > 2) {
        std::cout << "        solveForUpdate: Linear solver took: " << clock.secsSinceLast() << " seconds." << std::endl;
    }
    if (!rep.converged) {
        OPM_THROW(std::runtime_error, "Linear solver convergence failure.");
    }
    return du;
}
示例#2
0
CollOfScalar EquelleRuntimeCPU::singlePrimaryVariable(const CollOfScalar& initial_values)
{
    std::vector<int> block_pattern;
    block_pattern.push_back(initial_values.size());
    // Syntax below is: CollOfScalar::variable(block index, initialized from, block structure)
    return CollOfScalar::variable(0, initial_values.value(), block_pattern);
}
示例#3
0
void EquelleRuntimeCPU::output(const String& tag, const CollOfScalar& vals)
{
    if (output_to_file_) {
        int count = -1;
        auto it = outputcount_.find(tag);
        if (it == outputcount_.end()) {
            count = 0;
            outputcount_[tag] = 1; // should contain the count to be used next time for same tag.
        } else {
            count = outputcount_[tag];
            ++outputcount_[tag];
        }
        std::ostringstream fname;
        fname << tag << "-" << std::setw(5) << std::setfill('0') << count << ".output";
        std::ofstream file(fname.str().c_str());
        if (!file) {
            OPM_THROW(std::runtime_error, "Failed to open " << fname.str());
        }
        file.precision(16);
        std::copy(vals.value().data(), vals.value().data() + vals.size(), std::ostream_iterator<double>(file, "\n"));
    } else {
        std::cout << tag << " =\n";
        for (int i = 0; i < vals.size(); ++i) {
            std::cout << std::setw(15) << std::left << ( vals.value()[i] ) << " ";
        }
        std::cout << std::endl;
    }
}
CollOfScalar EquelleRuntimeCUDA::operatorOn(const CollOfScalar& data_in,
					    const CollOfIndices<codim>& from_set,
					    const CollOfIndices<codim>& to_set) {

    if ( data_in.size() != from_set.size()) {
	OPM_THROW(std::logic_error, "data_in (size " << data_in.size() << ") and from_set (size " << from_set.size() << ") have to be of the same size in On function for CollOfScalar.");
    }
    //if ( to_set.size() > from_set.size() ) {
    //	OPM_THROW(std::runtime_error, "To_set (size " << to_set.size() << ") has to be a subset of from_set (size " << from_set.size() << ")");
    //}

    return dev_grid_.operatorOn(data_in, from_set, to_set);
}
CollOfScalar EquelleRuntimeCUDA::operatorExtend(const CollOfScalar& data_in,
						const CollOfIndices<codim>& from_set,
						const CollOfIndices<codim>& to_set) const {
    
    if (data_in.size() != from_set.size() ) {
	OPM_THROW(std::runtime_error, "data_in (size " << data_in.size() << ") and from_set (size " << from_set.size() << ") have to be of the same size in Extend function."); 
    }
    if (from_set.size() > to_set.size() ) {
	OPM_THROW(std::runtime_error, "From_set (size " << from_set.size() << ") has to be a subset of to_set (size " << to_set.size() << ")");
    }
    
    return dev_grid_.operatorExtend(data_in, from_set, to_set);
}
示例#6
0
/// This function is not provided by AutoDiffBlock, so we must add it here.
inline CollOfScalar sqrt(const CollOfScalar& x)
{
    // d(sqrt(x))/dy = 1/(2*sqrt(x)) * dx/dy

    const auto& xjac = x.derivative();
    if (xjac.empty()) {
        return CollOfScalar(sqrt(x.value()));
    }
    const int num_blocks = xjac.size();
    std::vector<CollOfScalar::M> jac(num_blocks);
    const auto sqrt_x = sqrt(x.value());
    const CollOfScalar::M one_over_two_sqrt_x((0.5/sqrt_x).matrix().asDiagonal());
    for (int block = 0; block < num_blocks; ++block) {
        jac[block] = one_over_two_sqrt_x * xjac[block];
    }
    return CollOfScalar::ADB::function(sqrt_x, jac);
}
示例#7
0
CollOfScalar EquelleRuntimeCPU::divergence(const CollOfScalar& face_fluxes) const
{
    if (face_fluxes.size() == ops_.internal_faces.size()) {
        // This is actually a hack, the compiler should know to emit interiorDivergence()
        // eventually, but as a temporary measure we do this.
        return interiorDivergence(face_fluxes);
    }
    return ops_.fulldiv * face_fluxes;//.matrix();
}
示例#8
0
int compare(CollOfScalar scal, double sol[], 
	    int sol_size,
	    std::string test) 
{ 
    // Test size:
    if ( scal.size() != sol_size ) {
	std::cout << "Error in valsOnGrid.cpp - testing " << test << "\n";
	std::cout << "\tThe collection is of wrong size!\n";
	std::cout << "\tSize is " << scal.size() << " but should be " << sol_size << "\n";
	return 1;
    }
    
    // Testing indices
    std::vector<double> host = scal.copyToHost();
    std::cout << "CollOfScalar " << test << " is the following:\n";
    bool correct = true;
    for (int i = 0; i < host.size(); ++i) {
	std::cout << host[i] << " ";
	if (i < sol_size) {
	    //if (host[i] != sol[i]) {
	    if ( fabs(host[i] - sol[i]) > 1000*std::numeric_limits<double>::epsilon() ) {
		std::cout << "(<- " << sol[i] << ") ";
		correct = false;
	    }
	}
    }
    if (correct) {
	std::cout << "\n\tThis is correct\n";
    } else {
	std::cout << "\n\tThis is wrong\n";
	std::cout << "Error in valsOnGrid.cpp - testing " << test << "\n";
	std::cout << "\tThe indices in the collection is wrong\n";
	return 1;
    }

    return 0;

}
示例#9
0
/// This operator is not provided by AutoDiffBlock, so we must add it here.
inline CollOfScalar operator/(const Scalar& s, const CollOfScalar& x)
{
    return CollOfScalar::V::Constant(x.size(), s) / x;
}
示例#10
0
/// This operator is not provided by AutoDiffBlock, so we must add it here.
inline CollOfScalar operator/(const CollOfScalar& x, const Scalar& s)
{
    return x / CollOfScalar::V::Constant(x.size(), s);
}
示例#11
0
Scalar EquelleRuntimeCPU::maxReduce(const CollOfScalar& x) const
{
    return x.value().maxCoeff();
}
示例#12
0
/// This operator is not provided by AutoDiffBlock, so we must add it here.
inline CollOfScalar operator-(const CollOfScalar& x)
{
    return CollOfScalar::V::Zero(x.size()) - x;
}
示例#13
0
/// This operator is not provided by AutoDiffBlock, so we must add it here.
inline CollOfBool operator==(const CollOfScalar& x, const Scalar& s)
{
    return x.value() == s;
}
示例#14
0
/// This operator is not provided by AutoDiffBlock, so we must add it here.
inline CollOfBool operator==(const CollOfScalar& x, const CollOfScalar& y)
{
    return x.value() == y.value();
}
示例#15
0
/// This operator is not provided by AutoDiffBlock, so we must add it here.
inline CollOfBool operator==(const Scalar& s, const CollOfScalar& x)
{
    return s == x.value();
}
示例#16
0
CollOfScalar EquelleRuntimeCUDA::newtonSolve(const ResidualFunctor& rescomp,
                                            const CollOfScalar& u_initialguess)
{
    Opm::time::StopWatch clock;
    clock.start();

    // Set up Newton loop.
 
    // Define the primary variable
    CollOfScalar u = CollOfScalar(u_initialguess, true);
 
    if (verbose_ > 2) {
        output("Initial u", u);
        output("    newtonSolve: norm (initial u)", twoNorm(u));
    }
    CollOfScalar residual = rescomp(u);   
    if (verbose_ > 2) {
        output("Initial residual", residual);
        output("    newtonSolve: norm (initial residual)", twoNorm(residual));
    }

    int iter = 0;

    // Debugging output not specified in Equelle.
    if (verbose_ > 1) {
        std::cout << "    newtonSolve: iter = " << iter << " (max = " << max_iter_
		  << "), norm(residual) = " << twoNorm(residual)
                  << " (tol = " << abs_res_tol_ << ")" << std::endl;
    }

    CollOfScalar du;

    // Execute newton loop until residual is small or we have used too many iterations.
    while ( (twoNorm(residual) > abs_res_tol_) && (iter < max_iter_) ) {
	
	if ( solver_.getSolver() == CPU ) {
	    du = serialSolveForUpdate(residual);
	}
	else {
	    // Solve linear equations for du, apply update.
	    du = solver_.solve(residual.derivative(),
			       residual.value(),
			       verbose_);
	}

	// du is a constant, hence, u is still a primary variable with an identity
	// matrix as its derivative.
	u = u - du;

        // Recompute residual.
        residual = rescomp(u);

        if (verbose_ > 2) {
            // Debugging output not specified in Equelle.
            output("u", u);
            output("    newtonSolve: norm(u)", twoNorm(u));
            output("residual", residual);
            output("    newtonSolve: norm(residual)", twoNorm(residual));
        }

        ++iter;

        // Debugging output not specified in Equelle.
        if (verbose_ > 1) {
            std::cout << "    newtonSolve: iter = " << iter << " (max = " << max_iter_
		      << "), norm(residual) = " << twoNorm(residual)
                      << " (tol = " << abs_res_tol_ << ")" << std::endl;
        }

    }
    if (verbose_ > 0) {
        if (twoNorm(residual) > abs_res_tol_) {
            std::cout << "Newton solver failed to converge in " << max_iter_ << " iterations" << std::endl;
        } else {
            std::cout << "Newton solver converged in " << iter << " iterations" << std::endl;
        }
    }

    if (verbose_ > 1) {
        std::cout << "Newton solver took: " << clock.secsSinceLast() << " seconds." << std::endl;
    }

    return CollOfScalar(u.value());
}
示例#17
0
Scalar EquelleRuntimeCPU::sumReduce(const CollOfScalar& x) const
{
    return x.value().sum();
}
示例#18
0
Scalar EquelleRuntimeCPU::prodReduce(const CollOfScalar& x) const
{
    return x.value().prod();
}
示例#19
0
double EquelleRuntimeCPU::twoNorm(const CollOfScalar& vals) const
{
    return vals.value().matrix().norm();
}