1 /*
2   HMat-OSS (HMatrix library, open source software)
3 
4   Copyright (C) 2014-2015 Airbus Group SAS
5 
6   This program is free software; you can redistribute it and/or
7   modify it under the terms of the GNU General Public License
8   as published by the Free Software Foundation; either version 2
9   of the License, or (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 
20   http://github.com/jeromerobert/hmat-oss
21 */
22 
23 #include "config.h"
24 #include "hmat/hmat.h"
25 #include "coordinates.hpp"
26 #include "hmat_cpp_interface.hpp"
27 #include "default_engine.hpp"
28 #include "clustering.hpp"
29 #include "admissibility.hpp"
30 #include "c_wrapping.hpp"
31 #include "common/my_assert.h"
32 
33 using namespace hmat;
34 
hmat_create_clustering_median()35 hmat_clustering_algorithm_t * hmat_create_clustering_median()
36 {
37     return (hmat_clustering_algorithm_t*) new MedianBisectionAlgorithm();
38 }
39 
hmat_create_clustering_ntilesrecursive(int nTiles)40 hmat_clustering_algorithm_t * hmat_create_clustering_ntilesrecursive(int nTiles)
41 {
42     return (hmat_clustering_algorithm_t*) new NTilesRecursiveAlgorithm( nTiles );
43 }
44 
hmat_create_clustering_geometric()45 hmat_clustering_algorithm_t * hmat_create_clustering_geometric()
46 {
47     return (hmat_clustering_algorithm_t*) new GeometricBisectionAlgorithm();
48 }
49 
hmat_create_clustering_hybrid()50 hmat_clustering_algorithm_t * hmat_create_clustering_hybrid()
51 {
52     return (hmat_clustering_algorithm_t*) new HybridBisectionAlgorithm();
53 }
54 
hmat_delete_clustering(hmat_clustering_algorithm_t * algo)55 void hmat_delete_clustering(hmat_clustering_algorithm_t* algo)
56 {
57     delete (ClusteringAlgorithm*) algo;
58 }
59 
hmat_set_clustering_divider(hmat_clustering_algorithm_t * algo,int divider)60 void hmat_set_clustering_divider(hmat_clustering_algorithm_t* algo, int divider)
61 {
62     ((ClusteringAlgorithm*) algo)->setDivider(divider);
63 }
64 
65 hmat_clustering_algorithm_t*
hmat_create_clustering_max_dof(const hmat_clustering_algorithm_t * algo,int max_dof)66 hmat_create_clustering_max_dof(const hmat_clustering_algorithm_t* algo, int max_dof)
67 {
68   ClusteringAlgorithm* result = static_cast<const ClusteringAlgorithm*>((void*) algo)->clone();
69   result->setMaxLeafSize(max_dof);
70   return static_cast<hmat_clustering_algorithm_t*>((void*) result);
71 }
72 
hmat_create_clustering_span(const hmat_clustering_algorithm_t * algo,double ratio)73 hmat_clustering_algorithm_t* hmat_create_clustering_span(
74     const hmat_clustering_algorithm_t* algo, double ratio) {
75     SpanClusteringAlgorithm* result = new SpanClusteringAlgorithm(
76         *(reinterpret_cast<const ClusteringAlgorithm*>(algo)), ratio);
77     return reinterpret_cast<hmat_clustering_algorithm_t*>(result);
78 }
79 
80 hmat_clustering_algorithm_t*
hmat_create_void_clustering(const hmat_clustering_algorithm_t * algo)81 hmat_create_void_clustering(const hmat_clustering_algorithm_t* algo)
82 {
83   VoidClusteringAlgorithm* result = new VoidClusteringAlgorithm(*(static_cast<const ClusteringAlgorithm*>((void*) algo)));
84   return static_cast<hmat_clustering_algorithm_t*>((void*) result);
85 }
86 
87 hmat_clustering_algorithm_t*
hmat_create_shuffle_clustering(const hmat_clustering_algorithm_t * algo,int from_divider,int to_divider)88 hmat_create_shuffle_clustering(const hmat_clustering_algorithm_t* algo, int from_divider, int to_divider)
89 {
90   ShuffleClusteringAlgorithm* result = new ShuffleClusteringAlgorithm(*(static_cast<const ClusteringAlgorithm*>((void*) algo)), from_divider, to_divider);
91   return static_cast<hmat_clustering_algorithm_t*>((void*) result);
92 }
93 
hmat_create_cluster_tree(double * coord,int dimension,int size,hmat_clustering_algorithm_t * algo)94 hmat_cluster_tree_t * hmat_create_cluster_tree(double* coord, int dimension, int size, hmat_clustering_algorithm_t* algo)
95 {
96     struct hmat_cluster_tree_create_context_t ctx;
97     memset(&ctx, 0, sizeof(ctx));
98     ctx.coordinates = coord;
99     ctx.dimension = dimension;
100     ctx.number_of_points = size;
101     ctx.number_of_dof = ctx.number_of_points;
102     ctx.span_offsets = NULL;
103     ctx.spans = NULL;
104     ctx.group_index = NULL;
105     ClusterTreeBuilder builder(*reinterpret_cast<ClusteringAlgorithm*>(algo));
106     ctx.builder = reinterpret_cast<hmat_cluster_tree_builder_t*>(&builder);
107     return hmat_create_cluster_tree_generic(&ctx);
108 }
109 
hmat_create_cluster_tree_generic(struct hmat_cluster_tree_create_context_t * ctx)110 hmat_cluster_tree_t * hmat_create_cluster_tree_generic(struct hmat_cluster_tree_create_context_t * ctx) {
111     DofCoordinates dofs(ctx->coordinates, ctx->dimension, ctx->number_of_points, true,
112                         ctx->number_of_dof, ctx->span_offsets, ctx->spans);
113     ClusterTree * r = reinterpret_cast<const ClusterTreeBuilder*>(ctx->builder)->build(dofs, ctx->group_index);
114     return reinterpret_cast<hmat_cluster_tree_t *>(r);
115 }
116 
hmat_create_cluster_tree_builder(const hmat_clustering_algorithm_t * algo)117 hmat_cluster_tree_builder_t* hmat_create_cluster_tree_builder(const hmat_clustering_algorithm_t* algo)
118 {
119     ClusterTreeBuilder* result = new ClusterTreeBuilder(*static_cast<const ClusteringAlgorithm*>((void*) algo));
120     return static_cast<hmat_cluster_tree_builder_t*>((void*) result);
121 }
122 
123 /* Specify an algorithm for nodes at given depth and below */
hmat_cluster_tree_builder_add_algorithm(hmat_cluster_tree_builder_t * ctb,int level,const hmat_clustering_algorithm_t * algo)124 void hmat_cluster_tree_builder_add_algorithm(hmat_cluster_tree_builder_t* ctb, int level, const hmat_clustering_algorithm_t* algo)
125 {
126     ClusterTreeBuilder* ct_builder = static_cast<ClusterTreeBuilder*>((void*) ctb);
127     ct_builder->addAlgorithm(level, *static_cast<const ClusteringAlgorithm*>((void*) algo));
128 }
129 
hmat_delete_cluster_tree_builder(hmat_cluster_tree_builder_t * ctb)130 void hmat_delete_cluster_tree_builder(hmat_cluster_tree_builder_t* ctb)
131 {
132     delete static_cast<ClusterTreeBuilder*>((void*)ctb);
133 }
134 
135 /* Create a ClusterTree from the DoFs coordinates. */
hmat_create_cluster_tree_from_builder(double * coord,int dimension,int size,const hmat_cluster_tree_builder_t * ctb)136 hmat_cluster_tree_t * hmat_create_cluster_tree_from_builder(double* coord, int dimension, int size, const hmat_cluster_tree_builder_t* ctb)
137 {
138     struct hmat_cluster_tree_create_context_t ctx;
139     memset(&ctx, 0, sizeof(ctx));
140     ctx.coordinates = coord;
141     ctx.dimension = dimension;
142     ctx.number_of_points = size;
143     ctx.number_of_dof = ctx.number_of_points;
144     ctx.span_offsets = NULL;
145     ctx.spans = NULL;
146     ctx.group_index = NULL;
147     ctx.builder = ctb;
148     return hmat_create_cluster_tree_generic(&ctx);
149 }
150 
hmat_delete_cluster_tree(const hmat_cluster_tree_t * tree)151 void hmat_delete_cluster_tree(const hmat_cluster_tree_t * tree) {
152     delete ((ClusterTree*)tree);
153 }
154 
hmat_copy_cluster_tree(const hmat_cluster_tree_t * tree)155 hmat_cluster_tree_t * hmat_copy_cluster_tree(const hmat_cluster_tree_t * tree) {
156     return reinterpret_cast<hmat_cluster_tree_t *>(
157         reinterpret_cast<const ClusterTree*>(tree)->copy());
158 }
159 
hmat_tree_nodes_count(const hmat_cluster_tree_t * tree)160 int hmat_tree_nodes_count(const hmat_cluster_tree_t * tree)
161 {
162     return ((ClusterTree*)tree)->nodesCount();
163 }
164 
hmat_cluster_get_son(hmat_cluster_tree_t * tree,int index)165 hmat_cluster_tree_t *hmat_cluster_get_son( hmat_cluster_tree_t * tree, int index )
166 {
167     ClusterTree *son = reinterpret_cast<ClusterTree*>(tree)->getChild(index);
168     return (hmat_cluster_tree_t*)son;
169 }
170 
hmat_cluster_get_info(hmat_cluster_tree_t * tree,hmat_cluster_info_t * info)171 int hmat_cluster_get_info(hmat_cluster_tree_t *tree, hmat_cluster_info_t* info)
172 {
173     ClusterTree* cl          = static_cast<ClusterTree*>((void*) tree);
174     info->spatial_dimension  = cl->data.coordinates()->dimension();
175     info->dimension          = cl->data.coordinates()->numberOfDof();
176     info->nr_tree_nodes      = cl->nodesCount();
177     return 0;
178 }
179 
hmat_cluster_get_indices(const hmat_cluster_tree_t * tree)180 const int * hmat_cluster_get_indices(const hmat_cluster_tree_t *tree) {
181     return reinterpret_cast<const ClusterTree*>(tree)->data.indices();
182 }
183 
hmat_init_admissibility_param(hmat_admissibility_param_t * p)184 void hmat_init_admissibility_param(hmat_admissibility_param_t * p) {
185     p->eta = 2;
186     p->ratio = 0.0;
187     p->max_width = (size_t)-1L;
188 }
189 
hmat_create_admissibility(hmat_admissibility_param_t * p)190 hmat_admissibility_t* hmat_create_admissibility(hmat_admissibility_param_t * p) {
191     hmat::StandardAdmissibilityCondition * r =
192          new hmat::StandardAdmissibilityCondition(p->eta, p->ratio);
193     r->setMaxWidth(p->max_width);
194     return reinterpret_cast<hmat_admissibility_t*>(r);
195 }
196 
hmat_update_admissibility(hmat_admissibility_t * cond,hmat_admissibility_param_t * p)197 void hmat_update_admissibility(hmat_admissibility_t* cond, hmat_admissibility_param_t *p) {
198     hmat::AdmissibilityCondition * r = reinterpret_cast<AdmissibilityCondition*>(cond);
199     r->setRatio(p->ratio);
200     r->setMaxWidth(p->max_width);
201 }
202 
hmat_create_admissibility_standard(double eta)203 hmat_admissibility_t* hmat_create_admissibility_standard(double eta)
204 {
205     return static_cast<hmat_admissibility_t*>((void*) new hmat::StandardAdmissibilityCondition(eta));
206 }
207 
hmat_create_admissibility_always(size_t max_size,unsigned int min_block,int split_rows,int split_cols)208 hmat_admissibility_t* hmat_create_admissibility_always(
209         size_t max_size, unsigned int min_block, int split_rows, int split_cols) {
210     return reinterpret_cast<hmat_admissibility_t*>(
211         new hmat::AlwaysAdmissibilityCondition(max_size, min_block, split_rows, split_cols));
212 }
213 
hmat_create_admissibility_never(size_t max_size,unsigned int min_block,int split_rows,int split_cols)214 hmat_admissibility_t* hmat_create_admissibility_never(
215         size_t max_size, unsigned int min_block, int split_rows, int split_cols) {
216     hmat::AlwaysAdmissibilityCondition * r = new hmat::AlwaysAdmissibilityCondition(
217         max_size, min_block, split_rows, split_cols);
218     r->never(true);
219     return reinterpret_cast<hmat_admissibility_t*>(r);
220 }
221 
hmat_delete_admissibility(hmat_admissibility_t * cond)222 void hmat_delete_admissibility(hmat_admissibility_t * cond) {
223     delete static_cast<AdmissibilityCondition*>((void*)cond);
224 }
225 
hmat_init_default_interface(hmat_interface_t * i,hmat_value_t type)226 void hmat_init_default_interface(hmat_interface_t * i, hmat_value_t type)
227 {
228     i->value_type = type;
229     switch (type) {
230     case HMAT_SIMPLE_PRECISION: createCInterface<S_t, DefaultEngine>(i); break;
231     case HMAT_DOUBLE_PRECISION: createCInterface<D_t, DefaultEngine>(i); break;
232     case HMAT_SIMPLE_COMPLEX: createCInterface<C_t, DefaultEngine>(i); break;
233     case HMAT_DOUBLE_COMPLEX: createCInterface<Z_t, DefaultEngine>(i); break;
234     default: HMAT_ASSERT(false);
235     }
236 }
237 
hmat_get_parameters(hmat_settings_t * settings)238 void hmat_get_parameters(hmat_settings_t* settings)
239 {
240     HMatSettings& settingsCxx = HMatSettings::getInstance();
241     settings->compressionMinLeafSize = settingsCxx.compressionMinLeafSize;
242     settings->coarseningEpsilon = settingsCxx.coarseningEpsilon;
243     settings->maxLeafSize = settingsCxx.maxLeafSize;
244     settings->coarsening = settingsCxx.coarsening;
245     settings->validateNullRowCol = settingsCxx.validateNullRowCol;
246     settings->validateCompression = settingsCxx.validateCompression;
247     settings->validationErrorThreshold = settingsCxx.validationErrorThreshold;
248     settings->validationReRun = settingsCxx.validationReRun;
249     settings->dumpTrace = settingsCxx.dumpTrace;
250     settings->validationDump = settingsCxx.validationDump;
251 }
252 
hmat_set_parameters(hmat_settings_t * settings)253 int hmat_set_parameters(hmat_settings_t* settings)
254 {
255     HMAT_ASSERT(settings != NULL);
256     int rc = 0;
257     HMatSettings& settingsCxx = HMatSettings::getInstance();
258     settingsCxx.compressionMinLeafSize = settings->compressionMinLeafSize;
259     settingsCxx.coarseningEpsilon = settings->coarseningEpsilon;
260     settingsCxx.maxLeafSize = settings->maxLeafSize;
261     settingsCxx.coarsening = settings->coarsening;
262     settingsCxx.validateNullRowCol = settings->validateNullRowCol;
263     settingsCxx.validateCompression = settings->validateCompression;
264     settingsCxx.validationErrorThreshold = settings->validationErrorThreshold;
265     settingsCxx.validationReRun = settings->validationReRun;
266     settingsCxx.dumpTrace = settings->dumpTrace;
267     settingsCxx.validationDump = settings->validationDump;
268     settingsCxx.setParameters();
269     return rc;
270 }
271 
hmat_get_version()272 const char * hmat_get_version()
273 {
274     return HMAT_VERSION;
275 }
276 
hmat_get_build_date(const char ** date,const char ** time)277 void hmat_get_build_date(const char **date, const char **time)
278 {
279 #ifdef HMAT_EXPORT_BUILD_DATE
280   *date=(const char*)&__DATE__;
281   *time=(const char*)&__TIME__;
282 #else
283   *date="N/A";
284   *time="N/A";
285 #endif
286 }
287 
hmat_assemble_context_init(hmat_assemble_context_t * context)288 void hmat_assemble_context_init(hmat_assemble_context_t * context) {
289     context->compression = NULL;
290     context->assembly = NULL;
291     context->simple_compute = NULL;
292     context->block_compute = NULL;
293     context->advanced_compute = NULL;
294     context->user_context = NULL;
295     context->prepare = NULL;
296     context->lower_symmetric = 0;
297     context->factorization = hmat_factorization_none;
298     context->progress = DefaultProgress::getInstance();
299 }
300 
hmat_factorization_context_init(hmat_factorization_context_t * context)301 void hmat_factorization_context_init(hmat_factorization_context_t *context) {
302     context->factorization = hmat_factorization_lu;
303     context->progress = DefaultProgress::getInstance();
304 }
305 
hmat_delete_procedure(hmat_procedure_t * proc)306 void hmat_delete_procedure(hmat_procedure_t* proc) {
307     switch (proc->value_type) {
308     case HMAT_SIMPLE_PRECISION: delete static_cast<hmat::TreeProcedure<HMatrix<S_t> >*>(proc->internal); break;
309     case HMAT_DOUBLE_PRECISION: delete static_cast<hmat::TreeProcedure<HMatrix<D_t> >*>(proc->internal); break;
310     case HMAT_SIMPLE_COMPLEX:   delete static_cast<hmat::TreeProcedure<HMatrix<C_t> >*>(proc->internal); break;
311     case HMAT_DOUBLE_COMPLEX:   delete static_cast<hmat::TreeProcedure<HMatrix<Z_t> >*>(proc->internal); break;
312     default: HMAT_ASSERT(false);
313     }
314     delete proc;
315 }
316 
hmat_delete_leaf_procedure(hmat_leaf_procedure_t * proc)317 void hmat_delete_leaf_procedure(hmat_leaf_procedure_t* proc) {
318     switch (proc->value_type) {
319     case HMAT_SIMPLE_PRECISION: delete static_cast<const hmat::LeafProcedure<HMatrix<S_t> >*>(proc->internal); break;
320     case HMAT_DOUBLE_PRECISION: delete static_cast<const hmat::LeafProcedure<HMatrix<D_t> >*>(proc->internal); break;
321     case HMAT_SIMPLE_COMPLEX:   delete static_cast<const hmat::LeafProcedure<HMatrix<C_t> >*>(proc->internal); break;
322     case HMAT_DOUBLE_COMPLEX:   delete static_cast<const hmat::LeafProcedure<HMatrix<Z_t> >*>(proc->internal); break;
323     default: HMAT_ASSERT(false);
324     }
325     delete proc;
326 }
327 
hmat_create_compression_svd(double epsilon)328 hmat_compression_algorithm_t* hmat_create_compression_svd(double epsilon) {
329     return static_cast<hmat_compression_algorithm_t*>((void*) new hmat::CompressionSVD(epsilon));
330 }
331 
hmat_create_compression_aca_full(double epsilon)332 hmat_compression_algorithm_t* hmat_create_compression_aca_full(double epsilon) {
333     return static_cast<hmat_compression_algorithm_t*>((void*) new hmat::CompressionAcaFull(epsilon));
334 }
335 
hmat_create_compression_aca_partial(double epsilon)336 hmat_compression_algorithm_t* hmat_create_compression_aca_partial(double epsilon) {
337     return static_cast<hmat_compression_algorithm_t*>((void*) new hmat::CompressionAcaPartial(epsilon));
338 }
339 
hmat_create_compression_aca_plus(double epsilon)340 hmat_compression_algorithm_t* hmat_create_compression_aca_plus(double epsilon) {
341     return static_cast<hmat_compression_algorithm_t*>((void*) new hmat::CompressionAcaPlus(epsilon));
342 }
343 
hmat_create_compression_aca_random(double epsilon)344 hmat_compression_algorithm_t* hmat_create_compression_aca_random(double epsilon) {
345     return static_cast<hmat_compression_algorithm_t*>((void*) new hmat::CompressionAcaRandom(epsilon));
346 }
347 
hmat_delete_compression(const hmat_compression_algorithm_t * algo)348 void hmat_delete_compression(const hmat_compression_algorithm_t* algo) {
349     delete static_cast<hmat::CompressionAlgorithm*>((void*)algo);
350 }
351 
hmat_tracing_dump(char * filename)352 void hmat_tracing_dump(char *filename) {
353   tracing_dump(filename);
354 }
355 
hmat_default_progress()356 hmat_progress_t * hmat_default_progress() {
357     return DefaultProgress::getInstance();
358 }
359 
hmat_set_worker_index_function(int (* f)())360 void hmat_set_worker_index_function(int (*f)()) {
361   tracing_set_worker_index_func(f);
362 }
363