Created
February 5, 2016 02:49
-
-
Save boykov/029761defa77ff5cd5f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Python.h> | |
#include <numpy/arrayobject.h> | |
#include <complex.h> | |
#include "ioAHMED.h" | |
#include "timeAHMED.h" | |
#include "vec3d.h" | |
#include "cmplx.h" | |
#include "bemcluster.h" | |
#include "bemblcluster.h" | |
#include "matgen_omp.h" | |
#include "H.h" // HCholesky | |
#include "solvers.h" // PCG | |
#include "bemmatrix.h" | |
using namespace AHMED; | |
class MATGENKERNEL{ | |
public: | |
//! Constructor for initialization | |
MATGENKERNEL(const vec3d* vectors, const unsigned* op_perm, dcomp (*kernel)(unsigned , unsigned )) | |
: vectors_(vectors), op_perm_(op_perm), kernel_(kernel) { } | |
void cmpbl(const unsigned b1, const unsigned n1, const unsigned b2, const unsigned n2, | |
dcomp* pt) const { | |
#pragma omp critical (matgen_prog) | |
{ | |
for(unsigned j=b2; j<b2+n2; ++j) | |
for(unsigned i=b1; i<b1+n1; ++i) | |
*pt++ = (*kernel_)(op_perm_[i]+1, op_perm_[j]+1); | |
} | |
} | |
//! returns expected size of the matrix entries | |
double scale (const unsigned /*b1*/, const unsigned /*n1*/, | |
const unsigned /*b2*/, const unsigned /*n2*/) const { | |
return 1.; | |
} | |
private: | |
dcomp (*kernel_)(unsigned , unsigned ); | |
const vec3d* vectors_; | |
const unsigned* op_perm_; | |
}; | |
double eps_matgen; //!< relative accuracy | |
double eps_aggl; //!< relative accuracy | |
double eps_gmres; //!< relative accuracy | |
unsigned steps_gmres; | |
double eta; //!< control parameter for admissibility condition | |
unsigned bmin; //!< minimal size of a cluster | |
unsigned rankmax; //!< maximal blockwise rank | |
unsigned nVectors; | |
vec3d* vectors; | |
dcomp *solution; | |
static PyObject *py_kernel = NULL; | |
dcomp (*kernel)(unsigned i, unsigned j); | |
static PyObject * | |
set_kernel(PyObject *dummy, PyObject *args) | |
{ | |
PyObject *result = NULL; | |
PyObject *temp; | |
if (PyArg_ParseTuple(args, "O:set_kernel", &temp)) { | |
if (!PyCallable_Check(temp)) { | |
PyErr_SetString(PyExc_TypeError, "parameter must be callable"); | |
return NULL; | |
} | |
Py_XINCREF(temp); /* Add a reference to new callback */ | |
Py_XDECREF(py_kernel); /* Dispose of previous callback */ | |
py_kernel = temp; /* Remember new callback */ | |
/* Boilerplate to return "None" */ | |
Py_INCREF(Py_None); | |
result = Py_None; | |
} | |
return result; | |
}; | |
dcomp | |
callback_kernel(unsigned i, unsigned j) | |
{ | |
double C_result_imag,C_result_real; | |
PyObject *arglist; | |
PyObject *result; | |
arglist = Py_BuildValue("(ii)", i, j); | |
result = PyObject_CallObject(py_kernel, arglist); | |
Py_DECREF(arglist); | |
C_result_real = PyComplex_RealAsDouble(result); | |
C_result_imag = PyComplex_ImagAsDouble(result); | |
return dcomp(C_result_real, C_result_imag); | |
}; | |
static PyObject *py_vectorb = NULL; | |
dcomp (*vectorb)(unsigned i); | |
static PyObject * | |
set_vectorb(PyObject *dummy, PyObject *args) | |
{ | |
PyObject *result = NULL; | |
PyObject *temp; | |
if (PyArg_ParseTuple(args, "O:set_vectorb", &temp)) { | |
if (!PyCallable_Check(temp)) { | |
PyErr_SetString(PyExc_TypeError, "parameter must be callable"); | |
return NULL; | |
} | |
Py_XINCREF(temp); /* Add a reference to new callback */ | |
Py_XDECREF(py_vectorb); /* Dispose of previous callback */ | |
py_vectorb = temp; /* Remember new callback */ | |
/* Boilerplate to return "None" */ | |
Py_INCREF(Py_None); | |
result = Py_None; | |
} | |
return result; | |
}; | |
dcomp | |
callback_vectorb(unsigned i) | |
{ | |
double C_result_imag,C_result_real; | |
PyObject *arglist; | |
PyObject *result; | |
arglist = Py_BuildValue("(i)", i); | |
result = PyObject_CallObject(py_vectorb, arglist); | |
Py_DECREF(arglist); | |
C_result_real = PyComplex_RealAsDouble(result); | |
C_result_imag = PyComplex_ImagAsDouble(result); | |
return dcomp(C_result_real, C_result_imag); | |
}; | |
static PyObject * | |
set_Hmatrix(PyObject *dummy, PyObject *args) | |
{ | |
if (!PyArg_ParseTuple(args, "dddidii", &eps_matgen, &eps_aggl, &eps_gmres, &steps_gmres, &eta, &bmin, &rankmax)) | |
return NULL; | |
return Py_None; | |
} | |
static PyObject * | |
set_points(PyObject *dummy, PyObject *args) | |
{ | |
PyArrayObject *points; | |
NpyIter *points_iter; | |
NpyIter_IterNextFunc *points_iternext; | |
double ** points_dataptr; | |
unsigned i; | |
if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &points)) | |
return NULL; | |
points_iter = NpyIter_New(points, NPY_ITER_READONLY, NPY_KEEPORDER, | |
NPY_NO_CASTING, NULL); | |
if (points_iter == NULL) | |
goto fail; | |
points_iternext = NpyIter_GetIterNext(points_iter, NULL); | |
if (points_iternext == NULL) { | |
NpyIter_Deallocate(points_iter); | |
goto fail; | |
} | |
points_dataptr = (double **) NpyIter_GetDataPtrArray(points_iter); | |
nVectors = points->dimensions[0]; | |
vectors = new vec3d[nVectors]; | |
i = 0; | |
do { | |
vectors[i][0] = **points_dataptr; | |
points_iternext(points_iter); | |
vectors[i][1] = **points_dataptr; | |
points_iternext(points_iter); | |
vectors[i][2] = **points_dataptr; | |
i++; | |
} while(points_iternext(points_iter)); | |
return Py_None; | |
fail: | |
return NULL; | |
} | |
static PyObject * | |
get_q(PyObject *dummy, PyObject *args) | |
{ | |
PyArrayObject *q; | |
NpyIter *q_iter; | |
NpyIter_IterNextFunc *q_iternext; | |
dcomp ** q_dataptr; | |
unsigned i; | |
if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &q)) | |
return NULL; | |
q_iter = NpyIter_New(q, NPY_ITER_READONLY, NPY_KEEPORDER, | |
NPY_NO_CASTING, NULL); | |
if (q_iter == NULL) | |
goto fail; | |
q_iternext = NpyIter_GetIterNext(q_iter, NULL); | |
if (q_iternext == NULL) { | |
NpyIter_Deallocate(q_iter); | |
goto fail; | |
} | |
q_dataptr = (dcomp **) NpyIter_GetDataPtrArray(q_iter); | |
nVectors = q->dimensions[0]; | |
vectors = new vec3d[nVectors]; | |
i = 0; | |
do { | |
**q_dataptr = solution[i]; | |
i++; | |
} while(q_iternext(q_iter)); | |
return Py_None; | |
fail: | |
return NULL; | |
} | |
static PyObject * | |
solve_slae(PyObject *dummy, PyObject *args) | |
{ | |
Perm vecPerm(nVectors); | |
bemcluster<vec3d>* clTreeVec = | |
new bemcluster<vec3d>(vectors, vecPerm.op_perm, 0, nVectors); | |
clTreeVec->createClusterTree(bmin, vecPerm.op_perm, vecPerm.po_perm); | |
const unsigned nClustersPan = clTreeVec->getncl(); | |
std::cout << "done, " << nClustersPan << " clusters -- "; | |
std::cout << inMB(nClustersPan * sizeof(bemcluster<vec3d>)) << " MB." << std::endl; | |
bemblcluster<vec3d,vec3d>* blclTreeVec = | |
new bemblcluster<vec3d,vec3d>(clTreeVec, clTreeVec); | |
unsigned nblcksVec = 0; | |
blclTreeVec->subdivide(clTreeVec,clTreeVec, eta * eta, nblcksVec); | |
std::cout << "done, " << nblcksVec << " blocks -- "; | |
std::cout << inMB(blclTreeVec->size()) << " MB." << std::endl; | |
RealTimer timer; | |
kernel = &callback_kernel; | |
MATGENKERNEL MatGen(vectors, vecPerm.op_perm, kernel); | |
BEMMatrix<vec3d,vec3d> A(nVectors, blclTreeVec); | |
matgenGeH_omp(MatGen, nblcksVec, A.blclTree, eps_matgen, rankmax, A.blcks); | |
{ | |
const double allmem = sizeH(A.blclTree, A.blcks); | |
io::displayInfo(allmem, nVectors, timer.current(), sizeof(dcomp)); | |
} | |
// std::cout << "Agglomerating matrix ... " << std::flush; | |
// timer.restart(); | |
// agglH(A.blclTree, A.blcks, eps_aggl, rankmax); | |
// std::cout << "done." << std::endl; | |
// { | |
// const double allmem = sizeH(A.blclTree, A.blcks); | |
// io::displayInfo(allmem, nVectors, timer.current(), sizeof(dcomp)); | |
// } | |
dcomp *b = new dcomp[nVectors]; | |
unsigned i = 0; | |
do { | |
b[i] = callback_vectorb(vecPerm.op_perm[i] + 1); | |
i++; | |
} while( i < nVectors ); | |
dcomp *x = new dcomp[nVectors]; | |
std::fill_n(x, nVectors, dcomp(0.,0.)); | |
double acc = eps_gmres; | |
unsigned steps = steps_gmres; | |
if (GMRes(A, b, x, acc, 100, steps)) | |
std::cout << "GMRes: iteration did not converge."; | |
else | |
std::cout << "GMRes converged to " << acc << " in " | |
<< steps << " steps."; | |
std::cout << " Solution took " << timer << "." << std::endl; | |
solution = new dcomp[nVectors]; | |
i = 0; | |
do { | |
solution[i] = x[vecPerm.po_perm[i]]; | |
i++; | |
} while( i < nVectors ); | |
delete clTreeVec; | |
return Py_None; | |
} | |
static PyObject * | |
internal(PyObject *dummy, PyObject *args) | |
{ | |
PyArrayObject *in_array; | |
NpyIter *in_iter; | |
NpyIter_IterNextFunc *in_iternext; | |
double ** in_dataptr; | |
if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &in_array)) | |
return NULL; | |
in_iter = NpyIter_New(in_array, NPY_ITER_READONLY, NPY_KEEPORDER, | |
NPY_NO_CASTING, NULL); | |
in_iternext = NpyIter_GetIterNext(in_iter, NULL); | |
in_dataptr = (double **) NpyIter_GetDataPtrArray(in_iter); | |
**in_dataptr = eps_matgen; | |
in_iternext(in_iter); | |
**in_dataptr = eps_aggl; | |
in_iternext(in_iter); | |
**in_dataptr = eps_gmres; | |
in_iternext(in_iter); | |
**in_dataptr = steps_gmres; | |
in_iternext(in_iter); | |
**in_dataptr = eta; | |
in_iternext(in_iter); | |
**in_dataptr = bmin; | |
in_iternext(in_iter); | |
**in_dataptr = rankmax; | |
in_iternext(in_iter); | |
NpyIter_Deallocate(in_iter); | |
return Py_None; | |
} | |
char slaeahmed_set_Hmatrix_doc[] = "..."; | |
char slaeahmed_set_points_doc[] = "..."; | |
char slaeahmed_get_q_doc[] = "..."; | |
char slaeahmed_internal_doc[] = "..."; | |
char slaeahmed_solve_slae_doc[] = "..."; | |
char slaeahmed_set_kernel_doc[] = "..."; | |
char slaeahmed_set_vectorb_doc[] = "..."; | |
static PyMethodDef slaeahmed_methods[] = { | |
{"set_kernel", | |
set_kernel, | |
METH_VARARGS, | |
slaeahmed_set_kernel_doc}, | |
{"set_vectorb", | |
set_vectorb, | |
METH_VARARGS, | |
slaeahmed_set_vectorb_doc}, | |
{"set_points", | |
set_points, | |
METH_VARARGS, | |
slaeahmed_set_points_doc}, | |
{"get_q", | |
get_q, | |
METH_VARARGS, | |
slaeahmed_get_q_doc}, | |
{"set_Hmatrix", | |
set_Hmatrix, | |
METH_VARARGS, | |
slaeahmed_set_Hmatrix_doc}, | |
{"internal", | |
internal, | |
METH_VARARGS, | |
slaeahmed_internal_doc}, | |
{"solve_slae", | |
solve_slae, | |
METH_VARARGS, | |
slaeahmed_solve_slae_doc}, | |
{NULL, NULL} | |
}; | |
char slaeahmed_doc[] = "..."; | |
PyMODINIT_FUNC initslaeahmed() | |
{ | |
Py_InitModule3("slaeahmed", slaeahmed_methods, slaeahmed_doc); | |
import_array(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment