Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
NormalizeOpt.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7
9#include <alien/kernels/simple_csr/SimpleCSRMatrix.h>
10#include <alien/kernels/simple_csr/SimpleCSRVector.h>
11
12#ifdef ALIEN_USE_EIGEN3
13#include <Eigen/Core>
14#include <Eigen/LU>
15#endif
16
17#include <iostream>
18
19#include "NormalizeOpt.h"
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Alien
25{
26
27using namespace Arccore;
28
29/*---------------------------------------------------------------------------*/
30/*---------------------------------------------------------------------------*/
31
36
37/*---------------------------------------------------------------------------*/
38/*---------------------------------------------------------------------------*/
39
41{
42 m_algo = algo;
43}
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48void NormalizeOpt::setOpt(eOptType opt, bool flag)
49{
50 switch (opt) {
51 case SumFirstEq:
52 m_sum_first_eq = flag;
53 break;
54 default:
55 FatalErrorException(A_FUNCINFO, String::format("Unhandle option type: ", opt));
56 break;
57 }
58}
59
60/*---------------------------------------------------------------------------*/
61/*---------------------------------------------------------------------------*/
62
70
71/*---------------------------------------------------------------------------*/
72/*---------------------------------------------------------------------------*/
73
76CompositeMatrix& m, CompositeVector& x, ConstArrayView<Integer> eq_ids) const
77{
78 // need to update timestamp of all submatrices
79 MatrixImpl& A00 = m(0, 0).impl()->get<Alien::BackEnd::tag::simplecsr>(true);
80 MatrixImpl& A01 = m(0, 1).impl()->get<Alien::BackEnd::tag::simplecsr>(true);
81 MatrixImpl& A10 = m(1, 0).impl()->get<Alien::BackEnd::tag::simplecsr>(true);
82 MatrixImpl& A11 = m(1, 1).impl()->get<Alien::BackEnd::tag::simplecsr>(true);
85 {
86 eErrorType error =
87 _normalize(A00, A01, m(0, 1).impl()->hasFeature("transposed"), eq_ids, b0);
88 if (error != NoError)
89 return error;
90 }
91 {
92 eErrorType error =
93 _normalize(A11, eq_ids, A10, m(1, 0).impl()->hasFeature("transposed"), b1);
94 return error;
95 }
96}
97
98/*---------------------------------------------------------------------------*/
99/*---------------------------------------------------------------------------*/
100
101template <>
103{}
104
105/*---------------------------------------------------------------------------*/
106/*---------------------------------------------------------------------------*/
107
108template <>
110{
111 for (Integer irow = 0; irow < m_local_size; ++irow) {
112 Integer off = m_row_offset[irow];
113 Real diag = m_matrix[off];
114 for (Integer col = off; col < m_row_offset[irow + 1]; ++col) {
115 m_matrix[col] /= diag;
116 }
117 m_rhs[irow] /= diag;
118
119 if (!m_keep_diag)
120 m_matrix[off] = 0.;
121 }
122}
123
124/*---------------------------------------------------------------------------*/
125/*---------------------------------------------------------------------------*/
126
127template <Integer N>
129{
130#ifdef ALIEN_USE_EIGEN3
131 if (m_algo == EigenLU) {
132 using namespace Eigen;
133 typedef Eigen::Matrix<Real, N, N, RowMajor> MatrixType;
134 typedef Eigen::Matrix<Real, N, 1> VectorType;
135 const Integer NxN = N * N;
136 // TOCHECK : to be removed ?
137 // cout<<"MULT INV DIAG B"<<m_equations_num<<endl;
138 UniqueArray<Real> block(NxN);
139 UniqueArray<Real> vect(N);
140 Map<MatrixType> m(block.data());
141 Map<VectorType> v(vect.data());
142 if (m_diag_first) {
143 for (Integer irow = 0; irow < m_local_size; ++irow) {
144 Integer off = m_row_offset[irow];
145
146 Map<MatrixType> diag(&m_matrix[off * NxN]);
147 if (diag.determinant() == 0) {
148 std::cout << "Non inversible diagonal : row=" << irow << std::endl;
149 std::cout << " DIAG :" << std::endl;
150 std::cout << diag << std::endl;
151 }
152 MatrixType inv_diag = diag.inverse();
153 // TOCHECK : to be removed ?
154 // PartialPivLU< MatrixType > lu(diag);
155 // MatrixType inv_diag = lu.inverse() ;
156
157 // OFF DIAGONAL treatment
158 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
159 block.copy(ArrayView<Real>(NxN, &m_matrix[col * NxN]));
160 Map<MatrixType> matrix(&m_matrix[col * NxN]);
161 matrix = inv_diag * m;
162 // TOCHECK : to be removed ?
163 // matrix = lu.solve(m) ;
164 }
165
166 // RHS treatment
167 vect.copy(ArrayView<Real>(N, &m_rhs[irow * N]));
168 Map<VectorType> rhs(&m_rhs[irow * N]);
169 rhs = inv_diag * v;
170 // TOCHECK : to be removed
171 // rhs = lu.solve(v) ;
172
173 if (m_keep_diag)
174 diag.setIdentity();
175 else
176 diag.setZero();
177 }
178 }
179 else {
180 for (Integer irow = 0; irow < m_local_size; ++irow) {
181 Integer off = m_upper_diag_offset[irow];
182
183 Map<MatrixType> diag(&m_matrix[off * NxN]);
184 if (diag.determinant() == 0) {
185 std::cout << "Non inversible diagonal : row=" << irow << std::endl;
186 std::cout << " DIAG :" << std::endl;
187 std::cout << diag << std::endl;
188 }
189 MatrixType inv_diag = diag.inverse();
190 // TOCHECK : to be removed ?
191 // PartialPivLU< MatrixType > lu(diag);
192 // MatrixType inv_diag = lu.inverse() ;
193
194 // OFF DIAGONAL treatment
195 for (Integer col = m_row_offset[irow]; col < off; ++col) {
196 block.copy(ArrayView<Real>(NxN, &m_matrix[col * NxN]));
197 Map<MatrixType> matrix(&m_matrix[col * NxN]);
198 matrix = inv_diag * m;
199 // TOCHECK : to be removed ?
200 // matrix = lu.solve(m) ;
201 }
202 // skip diagonal block
203 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
204 block.copy(ArrayView<Real>(NxN, &m_matrix[col * NxN]));
205 Map<MatrixType> matrix(&m_matrix[col * NxN]);
206 matrix = inv_diag * m;
207 // TOCHECK : to be removed ?
208 // matrix = lu.solve(m) ;
209 }
210
211 // RHS treatment
212 vect.copy(ArrayView<Real>(N, &m_rhs[irow * N]));
213 Map<VectorType> rhs(&m_rhs[irow * N]);
214 rhs = inv_diag * v;
215 // TOCHECK : to be removed ?
216 // rhs = lu.solve(v) ;
217
218 if (m_keep_diag)
219 diag.setIdentity();
220 else
221 diag.setZero();
222 }
223 }
224 }
225 else
226#endif
227 {
228 if (m_diag_first) {
229 for (Integer irow = 0; irow < m_local_size; ++irow) {
230 Integer off = m_row_offset[irow];
231
232 Real* diag = &m_matrix[off * N * N];
233 LU<N> lu(diag);
234
235 // OFF DIAGONAL treatment
236 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
237 lu.template solve<N, false>(&m_matrix[col * N * N]);
238 }
239
240 // RHS treatment
241 lu.template solve<1, true>(&m_rhs[irow * N]);
242
243 if (m_keep_diag)
244 lu.setIdentity();
245 else
246 lu.setZero();
247 }
248 }
249 else {
250 for (Integer irow = 0; irow < m_local_size; ++irow) {
251 Integer off = m_upper_diag_offset[irow];
252
253 Real* diag = &m_matrix[off * N * N];
254 LU<N> lu(diag);
255
256 // OFF DIAGONAL treatment
257 for (Integer col = m_row_offset[irow]; col < off; ++col) {
258 lu.template solve<N, false>(&m_matrix[col * N * N]);
259 }
260 // skip diagonal block
261 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
262 lu.template solve<N, false>(&m_matrix[col * N * N]);
263 }
264 // RHS treatment
265 lu.template solve<1, true>(&m_rhs[irow * N]);
266
267 if (m_keep_diag)
268 lu.setIdentity();
269 else
270 lu.setZero();
271 }
272 }
273 }
274}
275
276/*---------------------------------------------------------------------------*/
277/*---------------------------------------------------------------------------*/
278
281{
282 Op op(m, x, m_algo, m_sum_first_eq);
283 if (m.block()) {
284 switch (m.block()->size()) {
285 case 1:
286 op.multInvDiag<1>();
287 break;
288 case 2:
289 op.multInvDiag<2>();
290 break;
291 case 3:
292 op.multInvDiag<3>();
293 break;
294 case 4:
295 op.multInvDiag<4>();
296 break;
297 default:
298 op.multInvDiag<0>();
299 break;
300 }
301 }
302 return NoError;
303}
304
305/*---------------------------------------------------------------------------*/
306/*---------------------------------------------------------------------------*/
307
308template <>
310{}
311
312/*---------------------------------------------------------------------------*/
313/*---------------------------------------------------------------------------*/
314
315template <>
317{
318 if (m_submatrix2) {
319 if (m_diag_first) {
321 //
322 // NORMALIZE SubMatrix00 and RHS
323 for (Integer irow = 0; irow < m_local_size; ++irow) {
324 Integer off = m_row_offset[irow];
325 Real diag = m_matrix[off];
326 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
327 m_matrix[col] /= diag;
328 }
329 m_rhs[irow] /= diag;
330 }
331
333 //
334 // NORMALIZE SubMatrix01
335 if (m_trans)
336 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
337 Integer ieq = m_eq_ids[i];
338 for (Integer k = m_extra_eq_row_offset[ieq]; k < m_extra_eq_row_offset[ieq + 1];
339 ++k) {
340 Integer irow = m_extra_eq_cols[k];
341 Integer off = m_row_offset[irow];
342 Real diag = m_matrix[off];
343 m_extra_eq_matrix[k] /= diag;
344 }
345 }
346 else
347 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
348 Integer irow = m_eq_ids[i];
349 Integer off = m_row_offset[irow];
350 Real diag = m_matrix[off];
351 for (Integer k = m_extra_eq_row_offset[irow];
352 k < m_extra_eq_row_offset[irow + 1]; ++k) {
353 m_extra_eq_matrix[k] /= diag;
354 }
355 }
357 //
358 // SET DIAG TO Id
359 for (Integer irow = 0; irow < m_local_size; ++irow) {
360 Integer off_diag = m_row_offset[irow];
361 m_matrix[off_diag] = m_keep_diag ? 1. : 0.;
362 }
363 }
364 else {
366 //
367 // NORMALIZE SubMatrix00 and RHS
368 for (Integer irow = 0; irow < m_local_size; ++irow) {
369 Integer off_diag = m_upper_diag_offset[irow];
370 Real diag = m_matrix[off_diag];
371 for (Integer col = m_row_offset[irow]; col < off_diag; ++col) {
372 m_matrix[col] /= diag;
373 }
374 for (Integer col = off_diag + 1; col < m_row_offset[irow + 1]; ++col) {
375 m_matrix[col] /= diag;
376 }
377 m_rhs[irow] /= diag;
378 }
379
381 //
382 // NORMALIZE SubMatrix01
383 if (m_trans)
384 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
385 Integer ieq = m_eq_ids[i];
386 for (Integer k = m_extra_eq_row_offset[ieq]; k < m_extra_eq_row_offset[ieq + 1];
387 ++k) {
388 Integer irow = m_extra_eq_cols[k];
389 Integer off = m_upper_diag_offset[irow];
390 Real diag = m_matrix[off];
391 m_extra_eq_matrix[k] /= diag;
392 }
393 }
394 else
395 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
396 Integer irow = m_eq_ids[i];
397 Integer off = m_upper_diag_offset[irow];
398 Real diag = m_matrix[off];
399 for (Integer k = m_extra_eq_row_offset[irow];
400 k < m_extra_eq_row_offset[irow + 1]; ++k) {
401 m_extra_eq_matrix[k] /= diag;
402 }
403 }
405 //
406 // SET DIAG TO Id
407 for (Integer irow = 0; irow < m_local_size; ++irow) {
408 Integer off_diag = m_upper_diag_offset[irow];
409 m_matrix[off_diag] = m_keep_diag ? 1. : 0.;
410 }
411 }
412 }
413
414 if (m_submatrix1) {
416 //
417 // NORMALIZE SubMatrix10 SubMatrix11 RHS
418 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
419 Integer ieq = m_eq_ids[i];
420 Real diag = m_matrix[ieq];
421 for (Integer j = m_extra_eq_row_offset[ieq]; j < m_extra_eq_row_offset[ieq + 1];
422 ++j) {
423 for (Integer k = 0; k < m_nuk2; ++k)
424 m_extra_eq_matrix[j * m_nuk2 + k] /= diag;
425 }
426 m_rhs[ieq] /= diag;
427 m_matrix[ieq] = 1.;
428 }
429 }
430}
431
432/*---------------------------------------------------------------------------*/
433/*---------------------------------------------------------------------------*/
434
435template <Integer N>
437{
438 if (m_submatrix2) {
439 if (m_diag_first) {
441 //
442 // NORMALIZE SubMatrix00
443 for (Integer irow = 0; irow < m_local_size; ++irow) {
444 Integer off = m_row_offset[irow];
445
446 Real* diag = &m_matrix[off * N * N];
447 LU<N> lu(diag);
448
449 // OFF DIAGONAL treatment
450 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
451 lu.template solve<N, false>(&m_matrix[col * N * N]);
452 }
453
454 // RHS treatment
455 lu.template solve<1, true>(&m_rhs[irow * N]);
456 }
457
459 //
460 // NORMALIZE SubMatrix01
461 if (m_trans)
462 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
463 Integer ieq = m_eq_ids[i];
464 for (Integer k = m_extra_eq_row_offset[ieq]; k < m_extra_eq_row_offset[ieq + 1];
465 ++k) {
466 Integer irow = m_extra_eq_cols[k];
467 Integer off = m_row_offset[irow];
468 Real* diag = &m_matrix[off * N * N];
469 LU<N> lu(diag, false);
470
471 lu.template solve<1, true>(&m_extra_eq_matrix[k * N]);
472 }
473 }
474 else
475 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
476 Integer irow = m_eq_ids[i];
477 Integer off = m_row_offset[irow];
478 Real* diag = &m_matrix[off * N * N];
479 LU<N> lu(diag, false);
480 for (Integer k = m_extra_eq_row_offset[irow];
481 k < m_extra_eq_row_offset[irow + 1]; ++k) {
482 lu.template solve<N, false>(&m_extra_eq_matrix[k * N]);
483 }
484 }
485
487 //
488 // SET DIAG TO Id
489 if (m_keep_diag)
490 for (Integer irow = 0; irow < m_local_size; ++irow) {
491 Integer off = m_row_offset[irow];
492 Real* diag = &m_matrix[off * N * N];
493 LU<N> lu(diag, false);
494
495 lu.setIdentity();
496 }
497 else
498 for (Integer irow = 0; irow < m_local_size; ++irow) {
499 Integer off = m_row_offset[irow];
500 Real* diag = &m_matrix[off * N * N];
501 LU<N> lu(diag, false);
502 lu.setZero();
503 }
504 }
505 else {
507 //
508 // NORMALIZE SubMatrix01
509 for (Integer irow = 0; irow < m_local_size; ++irow) {
510 Integer off = m_upper_diag_offset[irow];
511
512 Real* diag = &m_matrix[off * N * N];
513 LU<N> lu(diag);
514
515 // OFF DIAGONAL treatment
516 for (Integer col = m_row_offset[irow]; col < off; ++col) {
517 lu.template solve<N, false>(&m_matrix[col * N * N]);
518 }
519 // skip diagonal block
520 for (Integer col = off + 1; col < m_row_offset[irow + 1]; ++col) {
521 lu.template solve<N, false>(&m_matrix[col * N * N]);
522 }
523 // RHS treatment
524 lu.template solve<1, true>(&m_rhs[irow * N]);
525 }
527 //
528 // NORMALIZE SubMatrix01
529 if (m_trans)
530 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
531 Integer ieq = m_eq_ids[i];
532 for (Integer k = m_extra_eq_row_offset[ieq]; k < m_extra_eq_row_offset[ieq + 1];
533 ++k) {
534 Integer irow = m_extra_eq_cols[k] - m_local_offset;
535
536 Integer off = m_upper_diag_offset[irow];
537 Real* diag = &m_matrix[off * N * N];
538 LU<N> lu(diag, false);
539
540 lu.template solve<1, true>(&m_extra_eq_matrix[k * N]);
541 }
542 }
543 else {
544 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
545 Integer irow = m_eq_ids[i];
546 Integer off = m_upper_diag_offset[irow];
547 Real* diag = &m_matrix[off * N * N];
548 LU<N> lu(diag, false);
549 for (Integer k = m_extra_eq_row_offset[irow];
550 k < m_extra_eq_row_offset[irow + 1]; ++k) {
551 lu.template solve<N, false>(&m_extra_eq_matrix[k * N]);
552 }
553 }
554 }
555
557 //
558 // SET DIAG TO Id
559 if (m_keep_diag)
560 for (Integer irow = 0; irow < m_local_size; ++irow) {
561 Integer off = m_upper_diag_offset[irow];
562 Real* diag = &m_matrix[off * N * N];
563 LU<N> lu(diag, false);
564
565 lu.setIdentity();
566 }
567 else
568 for (Integer irow = 0; irow < m_local_size; ++irow) {
569 Integer off = m_upper_diag_offset[irow];
570 Real* diag = &m_matrix[off * N * N];
571 LU<N> lu(diag, false);
572 lu.setZero();
573 }
574 }
575 }
576
577 if (m_submatrix1) {
579 //
580 // NORMALIZE SubMatrix10 SubMatrix11 RHS
581 for (Integer i = 0; i < m_eq_ids.size(); ++i) {
582 Integer ieq = m_eq_ids[i];
583 Real diag = m_matrix[ieq];
584 for (Integer j = m_extra_eq_row_offset[ieq]; j < m_extra_eq_row_offset[ieq + 1];
585 ++j) {
586 for (Integer k = 0; k < N; ++k)
587 m_extra_eq_matrix[j * N + k] /= diag;
588 }
589 m_rhs[ieq] /= diag;
590 m_matrix[ieq] = 1.;
591 }
592 }
593}
594
595/*---------------------------------------------------------------------------*/
596/*---------------------------------------------------------------------------*/
597
600 ConstArrayView<Integer> eq_ids, VectorImpl& x) const
601{
602 Op2 op(m, m2, trans, eq_ids, x, m_algo, m_sum_first_eq);
603
604 switch (x.block()->size()) {
605 case 1:
606 op.multInvDiag<1>();
607 break;
608 case 2:
609 op.multInvDiag<2>();
610 break;
611 case 3:
612 op.multInvDiag<3>();
613 break;
614 case 4:
615 op.multInvDiag<4>();
616 break;
617 default:
618 op.multInvDiag<0>();
619 break;
620 }
621 return NoError;
622}
623
624/*---------------------------------------------------------------------------*/
625/*---------------------------------------------------------------------------*/
626
628NormalizeOpt::_normalize(MatrixImpl& m, ConstArrayView<Integer> eq_ids, MatrixImpl& m2,
629 bool trans, VectorImpl& x) const
630{
631 Op2 op(m, eq_ids, m2, trans, x, m_algo, m_sum_first_eq);
632
633 switch (x.block()->size()) {
634 case 1:
635 op.multInvDiag<1>();
636 break;
637 case 2:
638 op.multInvDiag<2>();
639 break;
640 case 3:
641 op.multInvDiag<3>();
642 break;
643 case 4:
644 op.multInvDiag<4>();
645 break;
646 default:
647 op.multInvDiag<0>();
648 break;
649 }
650 return NoError;
651}
652
653/*---------------------------------------------------------------------------*/
654/*---------------------------------------------------------------------------*/
655
656} // namespace Alien
657
658/*---------------------------------------------------------------------------*/
659/*---------------------------------------------------------------------------*/
MultiVectorImpl.h.
Arccore::Integer size() const
Get square block size.
Definition Block.cc:90
Composite matrix for heterogenous matrices.
MultiMatrixImpl * impl()
Get the multimatrix implementation.
Composite vector for heterogenous vector.
MultiVectorImpl * impl()
Get the multivector implementation.
virtual const Block * block() const
Get block datas of the matrix.
Interface for all matrices.
Definition IMatrix.h:51
virtual MultiMatrixImpl * impl()=0
Get the multimatrix implementation.
virtual const Block * block() const
Get block datas of the vector.
Interface for all vectors.
Definition IVector.h:51
virtual MultiVectorImpl * impl()=0
Get the multivector implementation.
const AlgebraTraits< tag >::matrix_type & get() const
Get a specific matrix implementation.
const AlgebraTraits< tag >::vector_type & get() const
Get a specific vector implementation.
LU normalization.
void setIdentity()
Set identity.
void setZero()
Set zero.
Normalize operator for composite matrices.
Arccore::ConstArrayView< Arccore::Integer > m_eq_ids
Ids of the equations.
Arccore::ConstArrayView< Arccore::Integer > m_extra_eq_cols
Pointer on extra equations unknowns columns.
bool m_trans
Transposed flag.
Arccore::ConstArrayView< Arccore::Integer > m_extra_eq_row_offset
Pointer on extra equations unknowns rows.
void multInvDiag()
Invert diagonal.
bool m_submatrix2
Whether or not the second submatrix should be normalized.
Arccore::Real * m_extra_eq_matrix
Pointer of extra equations datas.
bool m_submatrix1
Whether or not the first submatrix should be normalized.
Normalize operator.
Arccore::Integer m_local_size
The local size.
Arccore::Real * m_rhs
The rhs.
Arccore::Integer m_local_offset
The local offset.
eAlgoType m_algo
The algorithm type.
void multInvDiag()
Invert diagonal.
bool m_keep_diag
Whether or not diagonal should be kept.
Arccore::ConstArrayView< Arccore::Integer > m_upper_diag_offset
The indices of the upper diagonal.
Arccore::ConstArrayView< Arccore::Integer > m_row_offset
The rows offset.
Arccore::Real * m_matrix
The matrix.
bool m_diag_first
Whether or not the diagonal entry is stored first.
void setAlgo(eAlgoType algo)
Set the type of algorithm.
eErrorType
Type of the error.
eAlgoType
Type of algorithm.
eOptType
Type of the options.
SimpleCSRVector< Arccore::Real > VectorImpl
Type of the vector implementation.
eErrorType normalize(IMatrix &matrix, IVector &vector) const
Normalize the linear system.
bool m_sum_first_eq
Flag to sum the fist equation.
SimpleCSRMatrix< Arccore::Real > MatrixImpl
Type of the matrix implementation.
NormalizeOpt()
Constructor.
eErrorType _normalize(MatrixImpl &matrix, VectorImpl &vector) const
Normalize a linear system.
void setOpt(eOptType opt, bool flag)
Set the options.
eAlgoType m_algo
The algorithm.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17