Matrix assembly and CPU single core execution #1753
-
Hi,
Thanks in advance, all help is very much appreciated. I'll append the generation code below. n resembles the grid size in each dimension (d). #include<ginkgo/ginkgo.hpp>
#include<iostream>
#include<chrono>
#include<map>
#include<fstream>
// implementation using matrix_data -> uses AoS
template <class MatrixType, typename CoefficientFunction, typename BoundaryTypeFunction, class ExecutorType>
std::unique_ptr<MatrixType> diffusion_matrix_matrix_data(const size_t n, const size_t d,
CoefficientFunction diffusion_coefficient,
BoundaryTypeFunction dirichlet_boundary,
ExecutorType exec)
{
// relevant types
// using MatrixEntry = double;
using mtx = MatrixType;
// prepare grid information
std::vector<std::size_t> sizes(d + 1, 1);
for (int i = 1; i <= d; ++i)
sizes[i] = sizes[i - 1] * n;
double mesh_size = 1.0 / n;
int N = sizes[d];
// create matrix entries
// gko::matrix_data<double,size_t> mtx_data{gko::dim<2,size_t>(N,N)};
gko::matrix_data<> mtx_data{gko::dim<2>(N)};
//gko::matrix_data<> mtx_data{gko::dim<2>{N}};
for (std::size_t index = 0; index < sizes[d]; index++) /// each grid cell
{
// create multiindex from row number ///fancy way of doing 3(=d) for loops over n -> more powerful: works for all d
std::vector<std::size_t> multiindex(d, 0);
auto copiedindex = index;
for (int i = d - 1; i >= 0; i--)
{
multiindex[i] = copiedindex / sizes[i];
copiedindex = copiedindex % sizes[i];
// the current cell
std::vector<double> center_position(d);
for (int i = 0; i < d; ++i)
center_position[i] = multiindex[i] * mesh_size;
double center_coefficient = diffusion_coefficient(center_position);
double center_matrix_entry = 0.0;
// loop over all neighbors
for (int i = 0; i < d; i++)
{
// down neighbor
if (multiindex[i] > 0)
{
// we have a neighbor cell
std::vector<double> neighbor_position(center_position);
neighbor_position[i] -= mesh_size;
double neighbor_coefficient = diffusion_coefficient(neighbor_position);
double harmonic_average = 2.0 / ((1.0 / neighbor_coefficient) + (1.0 / center_coefficient));
mtx_data.nonzeros.emplace_back(index, index - sizes[i], -harmonic_average); ///matrix_data usage
center_matrix_entry += harmonic_average;
}
else
{
// current cell is on the boundary in this direction
std::vector<double> neighbor_position(center_position);
neighbor_position[i] = 0.0;
if (dirichlet_boundary(neighbor_position))
center_matrix_entry += center_coefficient * 2.0;
}
// up neighbor
if (multiindex[i] < n - 1)
{
// we have a neighbor cell
std::vector<double> neighbor_position(center_position);
neighbor_position[i] += mesh_size;
double neighbor_coefficient = diffusion_coefficient(neighbor_position);
double harmonic_average = 2.0 / ((1.0 / neighbor_coefficient) + (1.0 / center_coefficient));
mtx_data.nonzeros.emplace_back(index, index + sizes[i], -harmonic_average); ///matrix_data usage
center_matrix_entry += harmonic_average;
}
else
{
// current cell is on the boundary in this direction
std::vector<double> neighbor_position(center_position);
neighbor_position[i] = 1.0;
if (dirichlet_boundary(neighbor_position))
center_matrix_entry += center_coefficient * 2.0;
}
}
// finally the diagonal entry
mtx_data.nonzeros.emplace_back(index, index, center_matrix_entry); ///matrix_data usage
}
// create matrix from data
auto pA = mtx::create(exec);
pA->read(mtx_data); ///matrix_data usage
return pA;
} The auto mtx_assembly_data = gko::matrix_assembly_data<>{gko::dim<2>(N)};
(...)
mtx_assembly_data.set_value(index, index - sizes[i], -harmonic_average);
(...)
mtx_assembly_data.set_value(index, index + sizes[i], -harmonic_average);
(...)
mtx_assembly_data.set_value(index, index, center_matrix_entry);
(...)
auto pA = mtx::create(exec);
pA->read(mtx_assembly_data.get_ordered_data()); Find the full file here. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 3 replies
-
Hi @Ben90001, thanks for your interest in comparing Ginkgo to Dune-ISTL. I will try to answer your questions one-by-one:
As I mentioned in 2. you can also try out the I think your matrix generation code looks fine, it's similar to what we use for example in our benchmarks. I've also worked a bit with Dune in my past, so feel free to ask any other questions regarding interfacing GInkgo and Dune. |
Beta Was this translation helpful? Give feedback.
Hi @Ben90001, thanks for your interest in comparing Ginkgo to Dune-ISTL. I will try to answer your questions one-by-one:
ReferenceExecutor
would be the best option. If you want to run on the full CPU, then you would need to use theOmpExecutor
. You can also use theOmpExecutor
to run on a single core by setting the environment variableOMP_NUM_THREADS=1
. I would assume t…