22 #include "getfem/getfem_generic_assembly_functions_and_operators.h"
23 #include "getfem/getfem_generic_assembly_compile_and_exec.h"
32 static GA_TOKEN_TYPE ga_char_type[256];
33 static int ga_operator_priorities[GA_NB_TOKEN_TYPE];
36 static bool init_ga_char_type() {
37 for (
int i = 0; i < 256; ++i) ga_char_type[i] = GA_INVALID;
38 ga_char_type[
'+'] = GA_PLUS; ga_char_type[
'-'] = GA_MINUS;
39 ga_char_type[
'*'] = GA_MULT; ga_char_type[
'/'] = GA_DIV;
40 ga_char_type[
':'] = GA_COLON; ga_char_type[
'\''] = GA_QUOTE;
41 ga_char_type[
'.'] = GA_DOT; ga_char_type[
'@'] = GA_TMULT;
42 ga_char_type[
','] = GA_COMMA; ga_char_type[
';'] = GA_SEMICOLON;
43 ga_char_type[
'('] = GA_LPAR; ga_char_type[
')'] = GA_RPAR;
44 ga_char_type[
'['] = GA_LBRACKET; ga_char_type[
']'] = GA_RBRACKET;
45 ga_char_type[
'_'] = GA_NAME; ga_char_type[
'='] = GA_COLON_EQ;
46 for (
unsigned i =
'a'; i <=
'z'; ++i) ga_char_type[i] = GA_NAME;
47 for (
unsigned i =
'A'; i <=
'Z'; ++i) ga_char_type[i] = GA_NAME;
48 for (
unsigned i =
'0'; i <=
'9'; ++i) ga_char_type[i] = GA_SCALAR;
50 for (
unsigned i=0; i < GA_NB_TOKEN_TYPE; ++i) ga_operator_priorities[i] = 0;
51 ga_operator_priorities[GA_PLUS] = 1;
52 ga_operator_priorities[GA_MINUS] = 1;
53 ga_operator_priorities[GA_MULT] = 2;
54 ga_operator_priorities[GA_DIV] = 2;
55 ga_operator_priorities[GA_COLON] = 2;
56 ga_operator_priorities[GA_DOT] = 2;
57 ga_operator_priorities[GA_DOTMULT] = 2;
58 ga_operator_priorities[GA_DOTDIV] = 2;
59 ga_operator_priorities[GA_TMULT] = 2;
60 ga_operator_priorities[GA_QUOTE] = 3;
61 ga_operator_priorities[GA_UNARY_MINUS] = 3;
62 ga_operator_priorities[GA_SYM] = 4;
63 ga_operator_priorities[GA_SKEW] = 4;
64 ga_operator_priorities[GA_TRACE] = 4;
65 ga_operator_priorities[GA_DEVIATOR] = 4;
66 ga_operator_priorities[GA_PRINT] = 4;
71 static bool ga_initialized = init_ga_char_type();
74 static GA_TOKEN_TYPE ga_get_token(
const std::string &expr,
78 bool fdot =
false, fE =
false;
79 GMM_ASSERT1(ga_initialized,
"Internal error");
82 while (expr[pos] ==
' ' && pos < expr.size()) ++pos;
87 if (pos >= expr.size())
return GA_END;
90 GA_TOKEN_TYPE type = ga_char_type[unsigned(expr[pos])];
91 ++pos; ++token_length;
93 if (pos >= expr.size())
return type;
94 if (expr[pos] ==
'*') { ++pos; ++token_length;
return GA_DOTMULT; }
95 if (expr[pos] ==
'/') { ++pos; ++token_length;
return GA_DOTDIV; }
96 if (ga_char_type[
unsigned(expr[pos])] != GA_SCALAR)
return type;
97 fdot =
true; type = GA_SCALAR;
101 while (pos < expr.size()) {
102 GA_TOKEN_TYPE ctype = ga_char_type[unsigned(expr[pos])];
105 if (fdot)
return type;
106 fdot =
true; ++pos; ++token_length;
109 if (fE || (expr[pos] !=
'E' && expr[pos] !=
'e'))
return type;
110 fE =
true; fdot =
true; ++pos; ++token_length;
111 if (pos < expr.size()) {
112 if (expr[pos] ==
'+' || expr[pos] ==
'-')
113 { ++pos; ++token_length; }
115 if (pos >= expr.size()
116 || ga_char_type[
unsigned(expr[pos])] != GA_SCALAR)
120 ++pos; ++token_length;
break;
127 while (pos < expr.size()) {
128 GA_TOKEN_TYPE ctype = ga_char_type[unsigned(expr[pos])];
129 if (ctype != GA_SCALAR && ctype != GA_NAME)
break;
130 ++pos; ++token_length;
132 if (expr.compare(token_pos, token_length,
"Sym") == 0)
134 if (expr.compare(token_pos, token_length,
"Def") == 0)
136 if (expr.compare(token_pos, token_length,
"Skew") == 0)
138 if (expr.compare(token_pos, token_length,
"Trace") == 0)
140 if (expr.compare(token_pos, token_length,
"Deviator") == 0)
142 if (expr.compare(token_pos, token_length,
"Interpolate") == 0)
143 return GA_INTERPOLATE;
144 if (expr.compare(token_pos, token_length,
"Interpolate_derivative") == 0)
145 return GA_INTERPOLATE_DERIVATIVE;
146 if (expr.compare(token_pos, token_length,
"Interpolate_filter") == 0)
147 return GA_INTERPOLATE_FILTER;
148 if (expr.compare(token_pos, token_length,
149 "Elementary_transformation") == 0)
150 return GA_ELEMENTARY;
151 if (expr.compare(token_pos, token_length,
"Secondary_domain") == 0 ||
152 expr.compare(token_pos, token_length,
"Secondary_Domain") == 0)
153 return GA_SECONDARY_DOMAIN;
154 if (expr.compare(token_pos, token_length,
"Xfem_plus") == 0)
156 if (expr.compare(token_pos, token_length,
"Xfem_minus") == 0)
157 return GA_XFEM_MINUS;
158 if (expr.compare(token_pos, token_length,
"Print") == 0)
162 if (pos < expr.size() &&
163 ga_char_type[
unsigned(expr[pos])] == GA_COMMA) {
164 ++pos;
return GA_DCOMMA;
168 if (pos < expr.size() &&
169 ga_char_type[
unsigned(expr[pos])] == GA_SEMICOLON) {
170 ++pos;
return GA_DSEMICOLON;
174 if (pos < expr.size() &&
175 ga_char_type[
unsigned(expr[pos])] == GA_COLON_EQ) {
176 ++pos;
return GA_COLON_EQ;
181 default:
return type;
189 void ga_throw_error_msg(pstring expr,
size_type pos,
190 const std::string &msg) {
191 int length_before = 70, length_after = 70;
192 if (expr && expr->size()) {
193 int first = std::max(0,
int(pos)-length_before);
194 int last = std::min(
int(pos)+length_after,
int(expr->size()));
195 if (last - first < length_before+length_after)
196 first = std::max(0,
int(pos)-length_before
197 -(length_before+length_after-last+first));
198 if (last - first < length_before+length_after)
199 last = std::min(
int(pos)+length_after
200 +(length_before+length_after-last+first),
202 if (first > 0) cerr <<
"...";
203 cerr << expr->substr(first, last-first);
204 if (last <
int(expr->size())) cerr <<
"...";
206 if (first > 0) cerr <<
" ";
207 if (
int(pos) > first)
208 cerr << std::setfill (
'-') << std::setw(
int(pos)-first) <<
'-'
209 << std::setfill (
' ');
219 void ga_tree_node::mult_test(
const pga_tree_node n0,
const pga_tree_node n1) {
221 size_type test0 = n0->test_function_type, test1 = n1->test_function_type;
222 if (test0 && test1 && (test0 == test1 || test0 >= 3 || test1 >= 3))
223 ga_throw_error(expr, pos,
224 "Incompatibility of test functions in product.");
228 test_function_type = test0 + test1;
231 bgeot::multi_index mi(st);
234 case 1: mi[0] = n0->t.sizes()[0];
break;
235 case 2: mi[st-1] = n0->t.sizes()[0];
break;
236 case 3: mi[0] = n0->t.sizes()[0]; mi[1] = n0->t.sizes()[1];
break;
239 case 1: mi[0] = n1->t.sizes()[0];
break;
240 case 2: mi[st-1] = n1->t.sizes()[0];
break;
241 case 3: mi[0] = n1->t.sizes()[0]; mi[1] = n1->t.sizes()[1];
break;
244 if (n0->name_test1.size()) {
245 name_test1 = n0->name_test1; qdim1 = n0->qdim1;
246 interpolate_name_test1 = n0->interpolate_name_test1;
248 name_test1 = n1->name_test1; qdim1 = n1->qdim1;
249 interpolate_name_test1 = n1->interpolate_name_test1;
252 if (n0->name_test2.size()) {
253 name_test2 = n0->name_test2; qdim2 = n0->qdim2;
254 interpolate_name_test2 = n0->interpolate_name_test2;
256 name_test2 = n1->name_test2; qdim2 = n1->qdim2;
257 interpolate_name_test2 = n1->interpolate_name_test2;
262 void ga_tree::add_scalar(scalar_type val,
size_type pos, pstring expr) {
263 while (current_node && current_node->node_type != GA_NODE_OP)
264 current_node = current_node->parent;
266 current_node->adopt_child(
new ga_tree_node(val, pos, expr));
267 current_node = current_node->children.back();
270 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
271 current_node = root =
new ga_tree_node(val, pos, expr);
272 root->parent =
nullptr;
276 void ga_tree::add_allindices(
size_type pos, pstring expr) {
277 while (current_node && current_node->node_type != GA_NODE_OP)
278 current_node = current_node->parent;
280 current_node->adopt_child(
new ga_tree_node(GA_NODE_ALLINDICES, pos,expr));
281 current_node = current_node->children.back();
284 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
285 current_node = root =
new ga_tree_node(GA_NODE_ALLINDICES, pos, expr);
286 root->parent =
nullptr;
292 while (current_node && current_node->node_type != GA_NODE_OP)
293 current_node = current_node->parent;
295 current_node->adopt_child(
new ga_tree_node(name, length, pos, expr));
296 current_node = current_node->children.back();
299 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
300 current_node = root =
new ga_tree_node(name, length, pos, expr);
301 root->parent =
nullptr;
305 void ga_tree::add_sub_tree(ga_tree &sub_tree) {
307 (current_node->node_type == GA_NODE_PARAMS ||
308 current_node->node_type == GA_NODE_INTERPOLATE_FILTER ||
309 current_node->node_type == GA_NODE_C_MATRIX)) {
310 GMM_ASSERT1(sub_tree.root,
"Invalid tree operation");
311 current_node->adopt_child(sub_tree.root);
313 GMM_ASSERT1(sub_tree.root,
"Invalid tree operation");
314 while (current_node && current_node->node_type != GA_NODE_OP)
315 current_node = current_node->parent;
317 current_node->adopt_child(sub_tree.root);
318 current_node = sub_tree.root;
321 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
322 current_node = root = sub_tree.root;
323 root->parent =
nullptr;
326 sub_tree.root = sub_tree.current_node =
nullptr;
329 void ga_tree::add_params(
size_type pos, pstring expr) {
330 GMM_ASSERT1(current_node,
"internal error");
331 while (current_node && current_node->parent &&
332 current_node->parent->node_type == GA_NODE_OP &&
333 ga_operator_priorities[current_node->parent->op_type] >= 4)
334 current_node = current_node->parent;
335 pga_tree_node new_node =
new ga_tree_node(GA_NODE_PARAMS, pos, expr);
336 new_node->parent = current_node->parent;
337 if (current_node->parent)
338 current_node->parent->replace_child(current_node, new_node);
341 new_node->adopt_child(current_node);
342 current_node = new_node;
345 void ga_tree::add_matrix(
size_type pos, pstring expr) {
346 while (current_node && current_node->node_type != GA_NODE_OP)
347 current_node = current_node->parent;
349 current_node->adopt_child(
new ga_tree_node(GA_NODE_C_MATRIX, pos, expr));
350 current_node = current_node->children.back();
353 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
354 current_node = root =
new ga_tree_node(GA_NODE_C_MATRIX, pos, expr);
355 root->parent =
nullptr;
357 current_node->nbc1 = current_node->nbc2 = current_node->nbc3 = 0;
360 void ga_tree::add_op(GA_TOKEN_TYPE op_type,
size_type pos,
362 while (current_node && current_node->parent &&
363 current_node->parent->node_type == GA_NODE_OP &&
364 ga_operator_priorities[current_node->parent->op_type]
365 >= ga_operator_priorities[op_type])
366 current_node = current_node->parent;
367 pga_tree_node new_node =
new ga_tree_node(op_type, pos, expr);
369 if (op_type == GA_UNARY_MINUS
370 || op_type == GA_SYM || op_type == GA_SKEW
371 || op_type == GA_TRACE || op_type == GA_DEVIATOR
372 || op_type == GA_PRINT) {
373 current_node->adopt_child(new_node);
375 new_node->parent = current_node->parent;
376 if (current_node->parent)
377 current_node->parent->replace_child(current_node, new_node);
380 new_node->adopt_child(current_node);
383 if (root) new_node->adopt_child(root);
385 root->parent =
nullptr;
387 current_node = new_node;
390 void ga_tree::clear_node_rec(pga_tree_node pnode) {
392 for (pga_tree_node &child : pnode->children)
393 clear_node_rec(child);
395 current_node =
nullptr;
399 void ga_tree::clear_node(pga_tree_node pnode) {
401 pga_tree_node parent = pnode->parent;
404 for (pga_tree_node &sibling : parent->children)
405 if (sibling != pnode)
406 parent->children[j++] = sibling;
407 parent->children.resize(j);
411 clear_node_rec(pnode);
414 void ga_tree::clear_children(pga_tree_node pnode) {
415 for (pga_tree_node &child : pnode->children)
416 clear_node_rec(child);
417 pnode->children.resize(0);
420 void ga_tree::replace_node_by_child(pga_tree_node pnode,
size_type i) {
421 GMM_ASSERT1(i < pnode->children.size(),
"Internal error");
422 pga_tree_node child = pnode->children[i];
423 child->parent = pnode->parent;
425 pnode->parent->replace_child(pnode, child);
428 current_node =
nullptr;
429 for (pga_tree_node &sibling : pnode->children)
430 if (sibling != child) clear_node_rec(sibling);
434 size_type ga_tree_count_nodes(pga_tree_node pnode) {
438 for (pga_tree_node child : pnode->children)
439 count += ga_tree_count_nodes(child);
444 void ga_tree_copy_node_rec(pga_tree_node pnode,
445 pga_tree_node &pnode_new,
446 std::vector<pga_tree_node> &preallocated_nodes) {
447 GMM_ASSERT1(pnode_new ==
nullptr,
"Internal error");
448 GMM_ASSERT1(preallocated_nodes.size() > 0,
449 "Internal error, too small preallocation of nodes");
450 pnode_new = preallocated_nodes.back();
452 preallocated_nodes.pop_back();
453 pnode_new->parent =
nullptr;
454 for (
size_type j = 0; j < pnode_new->children.size(); ++j) {
455 pnode_new->children[j] =
nullptr;
456 ga_tree_copy_node_rec(pnode->children[j], pnode_new->children[j],
458 pnode_new->accept_child(j);
464 void ga_tree::copy_node(pga_tree_node pnode,
465 pga_tree_node &pnode_new) {
466 const size_type count = ga_tree_count_nodes(pnode);
467 std::vector<pga_tree_node> preallocated_nodes(count);
469 preallocated_nodes[i] =
new ga_tree_node();
470 ga_tree_copy_node_rec(pnode, pnode_new, preallocated_nodes);
473 void ga_tree::duplicate_with_operation(pga_tree_node pnode,
474 GA_TOKEN_TYPE op_type) {
475 pga_tree_node newop =
new ga_tree_node(op_type, pnode->pos, pnode->expr);
476 newop->children.resize(2,
nullptr);
477 newop->children[0] = pnode;
478 newop->pos = pnode->pos; newop->expr = pnode->expr;
479 newop->parent = pnode->parent;
481 pnode->parent->replace_child(pnode, newop);
484 pnode->parent = newop;
485 copy_node(pnode, newop->children[1]);
486 newop->accept_child(1);
489 void ga_tree::add_child(pga_tree_node pnode, GA_NODE_TYPE node_type) {
490 pga_tree_node newnode=
new ga_tree_node();
491 newnode->pos = pnode->pos; newnode->expr = pnode->expr;
492 newnode->node_type = node_type; pnode->adopt_child(newnode);
495 void ga_tree::insert_node(pga_tree_node pnode, GA_NODE_TYPE node_type) {
496 pga_tree_node newnode =
new ga_tree_node();
497 newnode->node_type = node_type;
498 newnode->parent = pnode->parent;
499 newnode->pos = pnode->pos; newnode->expr = pnode->expr;
501 pnode->parent->replace_child(pnode, newnode);
504 newnode->adopt_child(pnode);
507 bool sub_tree_are_equal(
const pga_tree_node pnode1,
508 const pga_tree_node pnode2,
509 const ga_workspace &workspace,
int version) {
512 if (ntype1 == GA_NODE_ZERO) ntype1 = GA_NODE_CONSTANT;
514 if (ntype2 == GA_NODE_ZERO) ntype2 = GA_NODE_CONSTANT;
515 if (ntype1 != ntype2)
return false;
516 if (pnode1->children.size() != pnode2->children.size())
return false;
520 if (pnode1->op_type != pnode2->op_type)
return false;
521 if (pnode1->symmetric_op != pnode2->symmetric_op)
return false;
523 case GA_NODE_OPERATOR:
524 if (pnode1->der1 != pnode2->der1 || pnode1->der2 != pnode2->der2)
526 if (pnode1->name.compare(pnode2->name))
return false;
528 case GA_NODE_PREDEF_FUNC:
case GA_NODE_SPEC_FUNC:
529 if (pnode1->name.compare(pnode2->name))
return false;
531 case GA_NODE_CONSTANT:
case GA_NODE_ZERO:
532 if (pnode1->tensor().size() != pnode2->tensor().size())
return false;
536 if (pnode1->test_function_type != pnode2->test_function_type)
538 if ((pnode1->test_function_type & 1) &&
539 pnode1->name_test1.compare(pnode2->name_test1) != 0)
541 if ((pnode1->test_function_type & 2) &&
542 pnode1->name_test2.compare(pnode2->name_test2) != 0)
546 if ((pnode1->test_function_type == 1 &&
547 pnode2->test_function_type == 1) ||
548 (pnode1->test_function_type == 2 &&
549 pnode2->test_function_type == 2))
551 if ((pnode1->test_function_type & 1) &&
552 pnode1->name_test1.compare(pnode2->name_test2) != 0)
554 if ((pnode1->test_function_type & 2) &&
555 pnode1->name_test2.compare(pnode2->name_test1) != 0)
559 if (pnode1->tensor().size() != 1 &&
560 pnode1->t.sizes().size() != pnode2->t.sizes().size())
return false;
561 for (
size_type i = 0; i < pnode1->t.sizes().size(); ++i)
562 if (pnode1->t.sizes()[i] != pnode2->t.sizes()[i])
return false;
563 for (
size_type i = 0; i < pnode1->tensor().size(); ++i)
564 if (gmm::abs(pnode1->tensor()[i] - pnode2->tensor()[i]) > 1E-25)
567 case GA_NODE_C_MATRIX:
568 if (pnode1->children.size() != pnode2->children.size() ||
569 pnode1->nb_test_functions() != pnode2->nb_test_functions() ||
570 pnode1->t.sizes().size() != pnode2->t.sizes().size())
572 for (
size_type i=pnode1->nb_test_functions();
573 i < pnode1->t.sizes().size(); ++i)
574 if (pnode1->t.sizes()[i] != pnode2->t.sizes()[i])
return false;
575 if (pnode1->nbc1 != pnode2->nbc1)
return false;
577 case GA_NODE_INTERPOLATE_FILTER:
578 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
579 pnode1->nbc1 != pnode2->nbc1)
582 case GA_NODE_INTERPOLATE_X:
583 case GA_NODE_SECONDARY_DOMAIN_X:
584 case GA_NODE_INTERPOLATE_ELT_K:
case GA_NODE_INTERPOLATE_ELT_B:
585 case GA_NODE_INTERPOLATE_NORMAL:
586 case GA_NODE_SECONDARY_DOMAIN_NORMAL:
587 if (pnode1->interpolate_name.compare(pnode2->interpolate_name))
590 case GA_NODE_INTERPOLATE_DERIVATIVE:
591 if (pnode1->interpolate_name_der.compare(pnode2->interpolate_name_der))
593 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
594 pnode1->elementary_name.compare(pnode2->elementary_name))
597 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
598 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
601 if (pnode1->name.compare(pnode2->name) ||
602 pnode1->test_function_type != pnode2->test_function_type)
607 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
608 pnode1->test_function_type != pnode2->test_function_type)
613 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
614 pnode1->test_function_type == pnode2->test_function_type)
620 case GA_NODE_INTERPOLATE_VAL_TEST:
case GA_NODE_INTERPOLATE_GRAD_TEST:
621 case GA_NODE_INTERPOLATE_HESS_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
622 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
623 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
624 case GA_NODE_SECONDARY_DOMAIN_VAL_TEST:
625 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
626 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
627 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
628 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
629 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
630 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
631 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
632 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
633 pnode1->elementary_name.compare(pnode2->elementary_name))
636 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
637 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
640 if (pnode1->name.compare(pnode2->name) ||
641 pnode1->test_function_type != pnode2->test_function_type)
646 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
647 pnode1->test_function_type != pnode2->test_function_type)
652 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
653 pnode1->test_function_type == pnode2->test_function_type)
659 case GA_NODE_VAL_TEST:
case GA_NODE_GRAD_TEST:
660 case GA_NODE_HESS_TEST:
case GA_NODE_DIVERG_TEST:
662 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
663 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
666 if (pnode1->name.compare(pnode2->name) ||
667 pnode1->test_function_type != pnode2->test_function_type)
672 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
673 pnode1->test_function_type != pnode2->test_function_type)
678 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
679 pnode1->test_function_type == pnode2->test_function_type)
685 case GA_NODE_VAL:
case GA_NODE_GRAD:
686 case GA_NODE_HESS:
case GA_NODE_DIVERG:
687 if (pnode1->name.compare(pnode2->name))
return false;
689 case GA_NODE_INTERPOLATE_VAL:
case GA_NODE_INTERPOLATE_GRAD:
690 case GA_NODE_INTERPOLATE_HESS:
case GA_NODE_INTERPOLATE_DIVERG:
691 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
692 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
693 case GA_NODE_SECONDARY_DOMAIN_VAL:
case GA_NODE_SECONDARY_DOMAIN_GRAD:
694 case GA_NODE_SECONDARY_DOMAIN_HESS:
case GA_NODE_SECONDARY_DOMAIN_DIVERG:
695 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
696 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
697 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
698 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
699 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
700 pnode1->elementary_name.compare(pnode2->elementary_name) ||
701 pnode1->name.compare(pnode2->name))
705 if (pnode1->nbc1 != pnode2->nbc1)
return false;
711 if (version && ntype1 == GA_NODE_OP && pnode1->symmetric_op) {
712 if (sub_tree_are_equal(pnode1->children[0], pnode2->children[0],
713 workspace, version) &&
714 sub_tree_are_equal(pnode1->children[1], pnode2->children[1],
717 if (sub_tree_are_equal(pnode1->children[1], pnode2->children[0],
718 workspace, version) &&
719 sub_tree_are_equal(pnode1->children[0], pnode2->children[1],
720 workspace, version) )
724 for (
size_type i = 0; i < pnode1->children.size(); ++i)
725 if (!(sub_tree_are_equal(pnode1->children[i], pnode2->children[i],
726 workspace, version)))
732 static void verify_tree(
const pga_tree_node pnode,
733 const pga_tree_node parent) {
734 GMM_ASSERT1(pnode->parent == parent,
735 "Invalid tree node " << pnode->node_type);
736 for (pga_tree_node &child : pnode->children)
737 verify_tree(child, pnode);
741 static void ga_print_constant_tensor(
const pga_tree_node pnode,
743 size_type nt = pnode->nb_test_functions();
744 switch (pnode->tensor_order()) {
746 str << (nt ? scalar_type(0) : pnode->tensor()[0]);
751 for (
size_type i = 0; i < pnode->tensor_proper_size(0); ++i) {
752 if (i != 0) str <<
",";
753 str << (nt ? scalar_type(0) : pnode->tensor()[i]);
758 case 2:
case 3:
case 4:
761 size_type n0 = pnode->tensor_proper_size(0);
762 size_type n1 = pnode->tensor_proper_size(1);
763 size_type n2 = ((pnode->tensor_order() > 2) ?
764 pnode->tensor_proper_size(2) : 1);
765 size_type n3 = ((pnode->tensor_order() > 3) ?
766 pnode->tensor_proper_size(3) : 1);
767 if (n3 > 1) str <<
"[";
769 if (l != 0) str <<
",";
770 if (n2 > 1) str <<
"[";
772 if (k != 0) str <<
",";
773 if (n1 > 1) str <<
"[";
775 if (j != 0) str <<
",";
776 if (n0 > 1) str <<
"[";
778 if (i != 0) str <<
",";
779 str << (nt ? scalar_type(0) : pnode->tensor()[ii++]);
781 if (n0 > 1) str <<
"]";
783 if (n1 > 1) str <<
"]";
785 if (n2 > 1) str <<
"]";
787 if (n3 > 1) str <<
"]";
791 case 5:
case 6:
case 7:
case 8:
793 for (
size_type i = 0; i < pnode->tensor_proper_size(); ++i) {
794 if (i != 0) str <<
";";
795 str << (nt ? scalar_type(0) : pnode->tensor()[i]);
798 for (
size_type i = 0; i < pnode->tensor_order(); ++i) {
799 if (i != 0) str <<
", ";
800 str << pnode->tensor_proper_size(i);
805 default: GMM_ASSERT1(
false,
"Invalid tensor dimension");
807 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
810 void ga_print_node(
const pga_tree_node pnode, std::ostream &str) {
812 long prec = str.precision(16);
814 bool is_interpolate(
false), is_elementary(
false), is_secondary(
false);
815 bool is_xfem_plus(
false), is_xfem_minus(
false);
816 switch(pnode->node_type) {
817 case GA_NODE_INTERPOLATE:
818 case GA_NODE_INTERPOLATE_X:
819 case GA_NODE_INTERPOLATE_ELT_K:
case GA_NODE_INTERPOLATE_ELT_B:
820 case GA_NODE_INTERPOLATE_NORMAL:
821 case GA_NODE_INTERPOLATE_VAL:
822 case GA_NODE_INTERPOLATE_GRAD:
823 case GA_NODE_INTERPOLATE_HESS:
824 case GA_NODE_INTERPOLATE_DIVERG:
825 case GA_NODE_INTERPOLATE_VAL_TEST:
826 case GA_NODE_INTERPOLATE_GRAD_TEST:
827 case GA_NODE_INTERPOLATE_HESS_TEST:
828 case GA_NODE_INTERPOLATE_DIVERG_TEST:
829 str <<
"Interpolate(";
830 is_interpolate =
true;
832 case GA_NODE_ELEMENTARY:
833 case GA_NODE_ELEMENTARY_VAL:
834 case GA_NODE_ELEMENTARY_GRAD:
835 case GA_NODE_ELEMENTARY_HESS:
836 case GA_NODE_ELEMENTARY_DIVERG:
837 case GA_NODE_ELEMENTARY_VAL_TEST:
838 case GA_NODE_ELEMENTARY_GRAD_TEST:
839 case GA_NODE_ELEMENTARY_HESS_TEST:
840 case GA_NODE_ELEMENTARY_DIVERG_TEST:
841 is_elementary =
true;
842 str <<
"Elementary_transformation(";
844 case GA_NODE_SECONDARY_DOMAIN:
845 case GA_NODE_SECONDARY_DOMAIN_X:
846 case GA_NODE_SECONDARY_DOMAIN_NORMAL:
847 case GA_NODE_SECONDARY_DOMAIN_VAL:
848 case GA_NODE_SECONDARY_DOMAIN_GRAD:
849 case GA_NODE_SECONDARY_DOMAIN_HESS:
850 case GA_NODE_SECONDARY_DOMAIN_DIVERG:
851 case GA_NODE_SECONDARY_DOMAIN_VAL_TEST:
852 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
853 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
854 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
855 str <<
"Secondary_domain(";
859 case GA_NODE_XFEM_PLUS:
860 case GA_NODE_XFEM_PLUS_VAL:
861 case GA_NODE_XFEM_PLUS_GRAD:
862 case GA_NODE_XFEM_PLUS_HESS:
863 case GA_NODE_XFEM_PLUS_DIVERG:
864 case GA_NODE_XFEM_PLUS_VAL_TEST:
865 case GA_NODE_XFEM_PLUS_GRAD_TEST:
866 case GA_NODE_XFEM_PLUS_HESS_TEST:
867 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
871 case GA_NODE_XFEM_MINUS:
872 case GA_NODE_XFEM_MINUS_VAL:
873 case GA_NODE_XFEM_MINUS_GRAD:
874 case GA_NODE_XFEM_MINUS_HESS:
875 case GA_NODE_XFEM_MINUS_DIVERG:
876 case GA_NODE_XFEM_MINUS_VAL_TEST:
877 case GA_NODE_XFEM_MINUS_GRAD_TEST:
878 case GA_NODE_XFEM_MINUS_HESS_TEST:
879 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
880 is_xfem_minus =
true;
881 str <<
"Xfem_minus(";
887 switch(pnode->node_type) {
889 case GA_NODE_INTERPOLATE_GRAD:
890 case GA_NODE_ELEMENTARY_GRAD:
891 case GA_NODE_SECONDARY_DOMAIN_GRAD:
892 case GA_NODE_XFEM_PLUS_GRAD:
893 case GA_NODE_XFEM_MINUS_GRAD:
894 case GA_NODE_GRAD_TEST:
895 case GA_NODE_INTERPOLATE_GRAD_TEST:
896 case GA_NODE_ELEMENTARY_GRAD_TEST:
897 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
898 case GA_NODE_XFEM_PLUS_GRAD_TEST:
899 case GA_NODE_XFEM_MINUS_GRAD_TEST:
903 case GA_NODE_INTERPOLATE_HESS:
904 case GA_NODE_ELEMENTARY_HESS:
905 case GA_NODE_SECONDARY_DOMAIN_HESS:
906 case GA_NODE_XFEM_PLUS_HESS:
907 case GA_NODE_XFEM_MINUS_HESS:
908 case GA_NODE_HESS_TEST:
909 case GA_NODE_INTERPOLATE_HESS_TEST:
910 case GA_NODE_ELEMENTARY_HESS_TEST:
911 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
912 case GA_NODE_XFEM_PLUS_HESS_TEST:
913 case GA_NODE_XFEM_MINUS_HESS_TEST:
917 case GA_NODE_INTERPOLATE_DIVERG:
918 case GA_NODE_SECONDARY_DOMAIN_DIVERG:
919 case GA_NODE_ELEMENTARY_DIVERG:
920 case GA_NODE_XFEM_PLUS_DIVERG:
921 case GA_NODE_XFEM_MINUS_DIVERG:
922 case GA_NODE_DIVERG_TEST:
923 case GA_NODE_INTERPOLATE_DIVERG_TEST:
924 case GA_NODE_ELEMENTARY_DIVERG_TEST:
925 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
926 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
927 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
934 switch(pnode->node_type) {
939 if (pnode->parent->node_type == GA_NODE_OP &&
940 (ga_operator_priorities[pnode->op_type] >= 2 ||
941 ga_operator_priorities[pnode->op_type]
942 < ga_operator_priorities[pnode->parent->op_type]))
944 if (pnode->parent->node_type == GA_NODE_PARAMS) par =
true;
949 if (pnode->op_type == GA_UNARY_MINUS) {
950 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
951 str <<
"-"; ga_print_node(pnode->children[0], str);
952 }
else if (pnode->op_type == GA_QUOTE) {
953 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
954 ga_print_node(pnode->children[0], str); str <<
"'";
955 }
else if (pnode->op_type == GA_SYM) {
956 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
957 str <<
"Sym("; ga_print_node(pnode->children[0], str); str <<
")";
958 }
else if (pnode->op_type == GA_SKEW) {
959 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
960 str <<
"Skew("; ga_print_node(pnode->children[0], str); str <<
")";
961 }
else if (pnode->op_type == GA_TRACE) {
962 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
963 str <<
"Trace("; ga_print_node(pnode->children[0], str); str <<
")";
964 }
else if (pnode->op_type == GA_DEVIATOR) {
965 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree with "
966 << pnode->children.size() <<
" children instead of 1");
967 str <<
"Deviator("; ga_print_node(pnode->children[0], str); str<<
")";
968 }
else if (pnode->op_type == GA_PRINT) {
969 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
970 str <<
"Print("; ga_print_node(pnode->children[0], str); str <<
")";
972 if (!par && pnode->op_type == GA_MULT &&
973 (pnode->children.size() == 1 ||
974 pnode->test_function_type ==
size_type(-1) ||
975 (pnode->children[0]->tensor_order() == 4 &&
976 pnode->children[1]->tensor_order() == 2)))
977 { par =
true; str <<
"("; }
978 ga_print_node(pnode->children[0], str);
979 switch (pnode->op_type) {
980 case GA_PLUS: str <<
"+";
break;
981 case GA_MINUS: str <<
"-";
break;
982 case GA_MULT: str <<
"*";
break;
983 case GA_DIV: str <<
"/";
break;
984 case GA_COLON: str <<
":";
break;
985 case GA_DOT: str <<
".";
break;
986 case GA_DOTMULT: str <<
".*";
break;
987 case GA_DOTDIV: str <<
"./";
break;
988 case GA_TMULT: str <<
"@";
break;
989 default: GMM_ASSERT1(
false,
"Invalid or not taken into account "
992 if (pnode->children.size() >= 2)
993 ga_print_node(pnode->children[1], str);
995 str <<
"(unknown second argument)";
1002 if (pnode->nbc1) str <<
"X(" << pnode->nbc1 <<
")";
else str <<
"X";
1004 case GA_NODE_ELT_SIZE: str <<
"element_size";
break;
1005 case GA_NODE_ELT_K: str <<
"element_K";
break;
1006 case GA_NODE_ELT_B: str <<
"element_B";
break;
1007 case GA_NODE_NORMAL: str <<
"Normal";
break;
1008 case GA_NODE_INTERPOLATE_FILTER:
1009 str <<
"Interpolate_filter(" << pnode->interpolate_name <<
",";
1010 ga_print_node(pnode->children[0], str);
1011 if (pnode->children.size() == 2)
1012 { str <<
","; ga_print_node(pnode->children[1], str); }
1013 else if (pnode->nbc1 !=
size_type(-1)) str <<
"," << pnode->nbc1;
1016 case GA_NODE_INTERPOLATE_X:
case GA_NODE_SECONDARY_DOMAIN_X:
1019 case GA_NODE_INTERPOLATE_NORMAL:
case GA_NODE_SECONDARY_DOMAIN_NORMAL:
1022 case GA_NODE_INTERPOLATE_ELT_K:
1025 case GA_NODE_INTERPOLATE_ELT_B:
1028 case GA_NODE_INTERPOLATE_DERIVATIVE:
1029 str << (pnode->test_function_type == 1 ?
"Test_" :
"Test2_")
1030 <<
"Interpolate_derivative(" << pnode->interpolate_name_der <<
","
1032 if (pnode->interpolate_name.size())
1033 str <<
"," << pnode->interpolate_name;
1036 case GA_NODE_INTERPOLATE:
1037 case GA_NODE_ELEMENTARY:
1038 case GA_NODE_SECONDARY_DOMAIN:
1039 case GA_NODE_XFEM_PLUS:
1040 case GA_NODE_XFEM_MINUS:
1042 case GA_NODE_INTERPOLATE_VAL:
1043 case GA_NODE_ELEMENTARY_VAL:
1044 case GA_NODE_SECONDARY_DOMAIN_VAL:
1045 case GA_NODE_XFEM_PLUS_VAL:
1046 case GA_NODE_XFEM_MINUS_VAL:
1048 case GA_NODE_INTERPOLATE_GRAD:
1049 case GA_NODE_SECONDARY_DOMAIN_GRAD:
1050 case GA_NODE_ELEMENTARY_GRAD:
1051 case GA_NODE_XFEM_PLUS_GRAD:
1052 case GA_NODE_XFEM_MINUS_GRAD:
1054 case GA_NODE_INTERPOLATE_HESS:
1055 case GA_NODE_SECONDARY_DOMAIN_HESS:
1056 case GA_NODE_ELEMENTARY_HESS:
1057 case GA_NODE_XFEM_PLUS_HESS:
1058 case GA_NODE_XFEM_MINUS_HESS:
1059 case GA_NODE_DIVERG:
1060 case GA_NODE_INTERPOLATE_DIVERG:
1061 case GA_NODE_ELEMENTARY_DIVERG:
1062 case GA_NODE_SECONDARY_DOMAIN_DIVERG:
1063 case GA_NODE_XFEM_PLUS_DIVERG:
1064 case GA_NODE_XFEM_MINUS_DIVERG:
1067 case GA_NODE_VAL_TEST:
1068 case GA_NODE_INTERPOLATE_VAL_TEST:
1069 case GA_NODE_ELEMENTARY_VAL_TEST:
1070 case GA_NODE_SECONDARY_DOMAIN_VAL_TEST:
1071 case GA_NODE_XFEM_PLUS_VAL_TEST:
1072 case GA_NODE_XFEM_MINUS_VAL_TEST:
1073 case GA_NODE_GRAD_TEST:
1074 case GA_NODE_INTERPOLATE_GRAD_TEST:
1075 case GA_NODE_ELEMENTARY_GRAD_TEST:
1076 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
1077 case GA_NODE_XFEM_PLUS_GRAD_TEST:
1078 case GA_NODE_XFEM_MINUS_GRAD_TEST:
1079 case GA_NODE_HESS_TEST:
1080 case GA_NODE_INTERPOLATE_HESS_TEST:
1081 case GA_NODE_ELEMENTARY_HESS_TEST:
1082 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
1083 case GA_NODE_XFEM_PLUS_HESS_TEST:
1084 case GA_NODE_XFEM_MINUS_HESS_TEST:
1085 case GA_NODE_DIVERG_TEST:
1086 case GA_NODE_INTERPOLATE_DIVERG_TEST:
1087 case GA_NODE_ELEMENTARY_DIVERG_TEST:
1088 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
1089 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
1090 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
1091 str << (pnode->test_function_type == 1 ?
"Test_" :
"Test2_")
1094 case GA_NODE_SPEC_FUNC: str << pnode->name;
break;
1095 case GA_NODE_OPERATOR:
1096 case GA_NODE_PREDEF_FUNC:
1098 str <<
"Derivative_" << pnode->der1 <<
"_";
1099 if (pnode->der2) str << pnode->der2 <<
"_";
1101 str << pnode->name;
break;
1103 GMM_ASSERT1(pnode->test_function_type !=
size_type(-1),
1105 if (pnode->test_function_type) str <<
"(";
1106 ga_print_constant_tensor(pnode, str);
1107 if (pnode->name_test1.size()) {
1108 GMM_ASSERT1(pnode->qdim1 > 0,
"Internal error");
1109 if (pnode->qdim1 == 1)
1110 str <<
"*Test_" << pnode->name_test1;
1112 str <<
"*(Reshape(Test_" << pnode->name_test1 <<
","
1113 << pnode->qdim1<<
")(1))";
1116 if (pnode->name_test2.size()) {
1117 GMM_ASSERT1(pnode->qdim2 > 0,
"Internal error");
1118 if (pnode->qdim2 == 1)
1119 str <<
"*Test2_" << pnode->name_test2;
1121 str <<
"*(Reshape(Test2_" << pnode->name_test2 <<
","
1122 << pnode->qdim2<<
")(1))";
1125 if (pnode->test_function_type) str <<
")";
1128 case GA_NODE_CONSTANT:
1129 ga_print_constant_tensor(pnode, str);
1132 case GA_NODE_ALLINDICES:
1134 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1137 case GA_NODE_PARAMS:
1138 GMM_ASSERT1(pnode->children.size(),
"Invalid tree");
1139 ga_print_node(pnode->children[0], str);
1141 for (
size_type i = 1; i < pnode->children.size(); ++i) {
1142 if (i > 1) str <<
", ";
1143 ga_print_node(pnode->children[i], str);
1150 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1153 case GA_NODE_MACRO_PARAM:
1154 if (pnode->nbc2 == 1) str <<
"Grad_";
1155 if (pnode->nbc2 == 2) str <<
"Hess_";
1156 if (pnode->nbc2 == 3) str <<
"Div_";
1157 if (pnode->nbc3 == 1) str <<
"Test_";
1158 if (pnode->nbc3 == 2) str <<
"Test2_";
1159 str <<
"P" << pnode->nbc1;
1160 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1163 case GA_NODE_RESHAPE:
1165 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1168 case GA_NODE_CROSS_PRODUCT:
1169 str <<
"Cross_product";
1170 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1173 case GA_NODE_SWAP_IND:
1174 str <<
"Swap_indices";
1175 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1178 case GA_NODE_IND_MOVE_LAST:
1179 str <<
"Index_move_last";
1180 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1183 case GA_NODE_CONTRACT:
1185 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1188 case GA_NODE_C_MATRIX:
1189 GMM_ASSERT1(pnode->children.size(),
"Invalid tree");
1190 GMM_ASSERT1(pnode->nbc1 == pnode->tensor_order(),
"Invalid C_MATRIX");
1191 switch (pnode->tensor_order()) {
1193 ga_print_node(pnode->children[0], str);
1198 for (
size_type i = 0; i < pnode->tensor_proper_size(0); ++i) {
1199 if (i != 0) str <<
",";
1200 ga_print_node(pnode->children[i], str);
1205 case 2:
case 3:
case 4:
1208 size_type n0 = pnode->tensor_proper_size(0);
1209 size_type n1 = pnode->tensor_proper_size(1);
1210 size_type n2 = ((pnode->tensor_order() > 2) ?
1211 pnode->tensor_proper_size(2) : 1);
1212 size_type n3 = ((pnode->tensor_order() > 3) ?
1213 pnode->tensor_proper_size(3) : 1);
1214 if (n3 > 1) str <<
"[";
1216 if (l != 0) str <<
",";
1217 if (n2 > 1) str <<
"[";
1219 if (k != 0) str <<
",";
1220 if (n1 > 1) str <<
"[";
1222 if (j != 0) str <<
",";
1223 if (n0 > 1) str <<
"[";
1225 if (i != 0) str <<
",";
1226 ga_print_node(pnode->children[ii++], str);
1228 if (n0 > 1) str <<
"]";
1230 if (n1 > 1) str <<
"]";
1232 if (n2 > 1) str <<
"]";
1234 if (n3 > 1) str <<
"]";
1238 case 5:
case 6:
case 7:
case 8:
1240 for (
size_type i = 0; i < pnode->tensor_proper_size(); ++i) {
1241 if (i != 0) str <<
";";
1242 ga_print_node(pnode->children[i], str);
1245 for (
size_type i = 0; i < pnode->tensor_order(); ++i) {
1246 if (i != 0) str <<
", ";
1247 str << pnode->tensor_proper_size(i);
1252 default: GMM_ASSERT1(
false,
"Invalid tensor dimension");
1257 str <<
"Invalid or not taken into account node type "
1258 << pnode->node_type;
1263 str <<
"," << pnode->interpolate_name <<
")";
1264 else if (is_elementary) {
1265 str <<
"," << pnode->elementary_name;
1266 if (pnode->name.compare(pnode->elementary_target) != 0)
1267 str <<
"," << pnode->elementary_target;
1269 }
else if (is_secondary)
1271 else if (is_xfem_plus || is_xfem_minus)
1274 str.precision(prec);
1277 std::string ga_tree_to_string(
const ga_tree &tree) {
1278 std::stringstream str;
1280 if (tree.root) verify_tree(tree.root, 0);
1281 if (tree.root) ga_print_node(tree.root, str);
else str <<
"0";
1285 size_type ga_parse_prefix_operator(std::string &name) {
1286 if (name.size() >= 5 && name.compare(0, 5,
"Grad_") == 0)
1287 { name = name.substr(5);
return 1; }
1288 else if (name.size() >= 5 && name.compare(0, 5,
"Hess_") == 0)
1289 { name = name.substr(5);
return 2; }
1290 else if (name.size() >= 4 && name.compare(0, 4,
"Div_") == 0)
1291 { name = name.substr(4);
return 3; }
1295 size_type ga_parse_prefix_test(std::string &name) {
1296 if (name.size() >= 5 && name.compare(0, 5,
"Test_") == 0)
1297 { name = name.substr(5);
return 1; }
1298 else if (name.size() >= 6 && name.compare(0, 6,
"Test2_") == 0)
1299 { name = name.substr(6);
return 2; }
1307 int ga_check_name_validity(
const std::string &name) {
1308 if (name.compare(0, 11,
"Derivative_") == 0)
1311 const ga_predef_operator_tab &PREDEF_OPERATORS
1313 const ga_spec_function_tab &SPEC_FUNCTIONS
1315 const ga_spec_op_tab &SPEC_OP
1317 const ga_predef_function_tab &PREDEF_FUNCTIONS
1320 if (SPEC_OP.find(name) != SPEC_OP.end())
1323 if (PREDEF_FUNCTIONS.find(name) != PREDEF_FUNCTIONS.end())
1326 if (SPEC_FUNCTIONS.find(name) != SPEC_FUNCTIONS.end())
1329 if (PREDEF_OPERATORS.tab.find(name) != PREDEF_OPERATORS.tab.end())
1332 if (name.size() >= 5 && name.compare(0, 5,
"Grad_") == 0)
1335 if (name.size() >= 5 && name.compare(0, 5,
"Hess_") == 0)
1338 if (name.size() >= 4 && name.compare(0, 4,
"Div_") == 0)
1341 if (name.size() >= 6 && name.compare(0, 6,
"Test2_") == 0)
1344 if (name.size() >= 5 && name.compare(0, 5,
"Test_") == 0)
1366 ga_macro::ga_macro() : ptree(new ga_tree), nbp(0) {}
1367 ga_macro::~ga_macro() {
delete ptree; }
1368 ga_macro::ga_macro(
const std::string &name,
const ga_tree &t,
size_type nbp_)
1369 : ptree(new ga_tree(t)), macro_name_(name), nbp(nbp_) {}
1370 ga_macro::ga_macro(
const ga_macro &gam)
1371 : ptree(new ga_tree(gam.tree())), macro_name_(gam.name()),
1372 nbp(gam.nb_params()) {}
1373 ga_macro &ga_macro::operator =(
const ga_macro &gam) {
1374 delete ptree; ptree =
new ga_tree(gam.tree());
1375 macro_name_ = gam.name();
1376 nbp = gam.nb_params();
1380 static void ga_replace_macro_params
1381 (ga_tree &tree, pga_tree_node pnode,
1382 const std::vector<pga_tree_node> &children) {
1384 for (pga_tree_node &child : pnode->children)
1385 ga_replace_macro_params(tree, child, children);
1387 if (pnode->node_type == GA_NODE_MACRO_PARAM) {
1390 GMM_ASSERT1(pnode->nbc1+1 < children.size(),
"Internal error");
1391 pga_tree_node pchild = children[pnode->nbc1+1];
1393 if (po || pt || pnode->op_type != GA_NAME) {
1394 if (!(pchild->children.empty()) || pchild->node_type != GA_NODE_NAME)
1395 ga_throw_error(pchild->expr, pchild->pos,
"Error in macro "
1396 "expansion. Only variable name are allowed for macro "
1397 "parameter preceded by Grad_ Hess_ Test_ or Test2_ "
1399 switch(pnode->op_type) {
1400 case GA_NAME : pnode->node_type = GA_NODE_NAME;
break;
1401 case GA_INTERPOLATE : pnode->node_type = GA_NODE_INTERPOLATE;
break;
1402 case GA_INTERPOLATE_DERIVATIVE :
1403 pnode->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
break;
1404 case GA_ELEMENTARY : pnode->node_type = GA_NODE_ELEMENTARY;
break;
1405 case GA_SECONDARY_DOMAIN :
1406 pnode->node_type = GA_NODE_SECONDARY_DOMAIN;
break;
1407 case GA_XFEM_PLUS : pnode->node_type = GA_NODE_XFEM_PLUS;
break;
1408 case GA_XFEM_MINUS: pnode->node_type = GA_NODE_XFEM_MINUS;
break;
1411 pnode->name = pchild->name;
1412 if (pt == 1) pnode->name =
"Test_" + pnode->name;
1413 if (pt == 2) pnode->name =
"Test2_" + pnode->name;
1414 if (po == 1) pnode->name =
"Grad_" + pnode->name;
1415 if (po == 2) pnode->name =
"Hess_" + pnode->name;
1416 if (po == 3) pnode->name =
"Div_" + pnode->name;
1418 pga_tree_node pnode_old = pnode;
1420 tree.copy_node(pchild, pnode);
1421 pnode->parent = pnode_old->parent;
1422 if (pnode_old->parent)
1423 pnode_old->parent->replace_child(pnode_old, pnode);
1426 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1432 static void ga_expand_macro(ga_tree &tree, pga_tree_node pnode,
1433 const ga_macro_dictionary ¯o_dict) {
1436 if (pnode->node_type == GA_NODE_PARAMS) {
1438 for (
size_type i = 1; i < pnode->children.size(); ++i)
1439 ga_expand_macro(tree, pnode->children[i], macro_dict);
1441 if (pnode->children[0]->node_type != GA_NODE_NAME) {
1442 ga_expand_macro(tree, pnode->children[0], macro_dict);
1445 if (macro_dict.macro_exists(pnode->children[0]->name)) {
1447 const ga_macro &gam = macro_dict.get_macro(pnode->children[0]->name);
1449 if (gam.nb_params()==0) {
1450 pga_tree_node pnode_old = pnode->children[0];
1451 pnode->children[0] =
nullptr;
1452 tree.copy_node(gam.tree().root, pnode->children[0]);
1453 pnode->children[0]->parent = pnode_old->parent;
1454 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1457 if (gam.nb_params()+1 != pnode->children.size())
1458 ga_throw_error(pnode->expr, pnode->pos,
1459 "Bad number of parameters in the use of macro '"
1460 << gam.name() <<
"'. Expected " << gam.nb_params()
1461 <<
" found " << pnode->children.size()-1 <<
".");
1463 pga_tree_node pnode_old = pnode;
1465 tree.copy_node(gam.tree().root, pnode);
1466 pnode->parent = pnode_old->parent;
1467 if (pnode_old->parent)
1468 pnode_old->parent->replace_child(pnode_old, pnode);
1471 ga_replace_macro_params(tree, pnode, pnode_old->children);
1472 tree.clear_node_rec(pnode_old);
1477 }
else if (pnode->node_type == GA_NODE_NAME &&
1478 macro_dict.macro_exists(pnode->name)) {
1480 const ga_macro &gam = macro_dict.get_macro(pnode->name);
1481 if (gam.nb_params() != 0)
1482 ga_throw_error(pnode->expr, pnode->pos,
1483 "Bad number of parameters in the use of macro '"
1484 << gam.name() <<
"'. Expected " << gam.nb_params()
1487 pga_tree_node pnode_old = pnode;
1489 tree.copy_node(gam.tree().root, pnode);
1490 pnode->parent = pnode_old->parent;
1491 if (pnode_old->parent)
1492 pnode_old->parent->replace_child(pnode_old, pnode);
1495 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1498 for (pga_tree_node &child : pnode->children)
1499 ga_expand_macro(tree, child, macro_dict);
1503 static void ga_mark_macro_params_rec(
const pga_tree_node pnode,
1504 const std::vector<std::string> ¶ms) {
1506 for (pga_tree_node &child : pnode->children)
1507 ga_mark_macro_params_rec(child, params);
1509 if (pnode->node_type == GA_NODE_NAME ||
1510 pnode->node_type == GA_NODE_INTERPOLATE ||
1511 pnode->node_type == GA_NODE_ELEMENTARY ||
1512 pnode->node_type == GA_NODE_SECONDARY_DOMAIN ||
1513 pnode->node_type == GA_NODE_XFEM_PLUS ||
1514 pnode->node_type == GA_NODE_XFEM_MINUS) {
1515 std::string name = pnode->name;
1516 size_type po = ga_parse_prefix_operator(name);
1517 size_type pt = ga_parse_prefix_test(name);
1519 for (
size_type i = 0; i < params.size(); ++i)
1520 if (name.compare(params[i]) == 0) {
1522 switch(pnode->node_type) {
1523 case GA_NODE_NAME : pnode->op_type = GA_NAME;
break;
1524 case GA_NODE_INTERPOLATE : pnode->op_type = GA_INTERPOLATE;
break;
1525 case GA_NODE_INTERPOLATE_DERIVATIVE :
1526 pnode->op_type = GA_INTERPOLATE_DERIVATIVE;
break;
1527 case GA_NODE_ELEMENTARY : pnode->op_type = GA_ELEMENTARY;
break;
1528 case GA_NODE_SECONDARY_DOMAIN :
1529 pnode->op_type = GA_SECONDARY_DOMAIN;
break;
1530 case GA_NODE_XFEM_PLUS : pnode->op_type = GA_XFEM_PLUS;
break;
1531 case GA_NODE_XFEM_MINUS: pnode->op_type = GA_XFEM_MINUS;
break;
1534 pnode->node_type = GA_NODE_MACRO_PARAM;
1535 pnode->nbc1 = i; pnode->nbc2 = po; pnode->nbc3 = pt;
1540 static void ga_mark_macro_params(ga_macro &gam,
1541 const std::vector<std::string> ¶ms,
1542 const ga_macro_dictionary ¯o_dict) {
1543 if (gam.tree().root) {
1544 ga_mark_macro_params_rec(gam.tree().root, params);
1545 ga_expand_macro(gam.tree(), gam.tree().root, macro_dict);
1549 bool ga_macro_dictionary::macro_exists(
const std::string &name)
const {
1550 if (macros.find(name) != macros.end())
return true;
1551 if (parent && parent->macro_exists(name))
return true;
1556 ga_macro_dictionary::get_macro(
const std::string &name)
const {
1557 auto it = macros.find(name);
1558 if (it != macros.end())
return it->second;
1559 if (parent)
return parent->get_macro(name);
1560 GMM_ASSERT1(
false,
"Undefined macro");
1563 void ga_macro_dictionary::add_macro(
const ga_macro &gam)
1564 { macros[gam.name()] = gam; }
1566 void ga_macro_dictionary::add_macro(
const std::string &name,
1567 const std::string &expr)
1568 { ga_tree tree; ga_read_string_reg(
"Def "+name+
":="+expr, tree, *
this); }
1570 void ga_macro_dictionary::del_macro(
const std::string &name) {
1571 auto it = macros.find(name);
1572 GMM_ASSERT1(it != macros.end(),
"Undefined macro (at this level)");
1582 static GA_TOKEN_TYPE ga_read_term(pstring expr,
size_type &pos,
1584 ga_macro_dictionary ¯o_dict) {
1586 GA_TOKEN_TYPE t_type;
1591 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1599 char *endptr;
const char *nptr = &((*expr)[token_pos]);
1600 scalar_type s_read = ::strtod(nptr, &endptr);
1602 ga_throw_error(expr, token_pos,
"Bad numeric format.");
1603 tree.add_scalar(s_read, token_pos, expr);
1608 tree.add_allindices(token_pos, expr);
1612 tree.add_name(&((*expr)[token_pos]), token_length, token_pos, expr);
1616 tree.add_op(GA_UNARY_MINUS, token_pos, expr);
1623 tree.add_op(GA_SYM, token_pos, expr);
1627 tree.add_op(GA_SKEW, token_pos, expr);
1631 tree.add_op(GA_TRACE, token_pos, expr);
1635 tree.add_op(GA_DEVIATOR, token_pos, expr);
1641 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1642 if (t_type != GA_NAME)
1643 ga_throw_error(expr, pos,
1644 "Macro definition should begin with macro name");
1645 gam.name() = std::string(&((*expr)[token_pos]), token_length);
1646 if (ga_check_name_validity(gam.name()))
1647 ga_throw_error(expr, pos-1,
"Invalid macro name.")
1648 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1649 std::vector<std::
string> params;
1650 if (t_type == GA_LPAR) {
1651 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1652 while (t_type == GA_NAME) {
1653 params.push_back(std::string(&((*expr)[token_pos]),
1655 if (ga_check_name_validity(params.back()))
1656 ga_throw_error(expr, pos-1,
"Invalid macro parameter name.");
1657 for (
size_type i = 0; i+1 < params.size(); ++i)
1658 if (params.back().compare(params[i]) == 0)
1659 ga_throw_error(expr, pos-1,
1660 "Invalid repeated macro parameter name.");
1661 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1662 if (t_type == GA_COMMA)
1663 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1665 if (t_type != GA_RPAR)
1666 ga_throw_error(expr, pos-1,
1667 "Missing right parenthesis in macro definition.");
1668 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1670 if (t_type != GA_COLON_EQ)
1671 ga_throw_error(expr, pos-1,
"Missing := for macro definition.");
1673 t_type = ga_read_term(expr, pos, gam.tree(), macro_dict);
1674 if (gam.tree().root)
1675 ga_expand_macro(gam.tree(), gam.tree().root, macro_dict);
1676 gam.nb_params() = params.size();
1678 ga_mark_macro_params(gam, params, macro_dict);
1679 macro_dict.add_macro(gam);
1685 if (t_type == GA_END)
return t_type;
1686 else if (t_type != GA_SEMICOLON)
1687 ga_throw_error(expr, pos-1,
1688 "Syntax error at the end of macro definition.");
1693 case GA_INTERPOLATE:
1695 tree.add_scalar(scalar_type(0), token_pos, expr);
1696 tree.current_node->node_type = GA_NODE_INTERPOLATE;
1697 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1698 if (t_type != GA_LPAR)
1699 ga_throw_error(expr, pos-1,
"Missing interpolate arguments.");
1700 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1701 if (t_type != GA_NAME)
1702 ga_throw_error(expr, pos,
1703 "First argument of Interpolate should be a "
1704 "variable, test function, X or Normal.");
1705 tree.current_node->name = std::string(&((*expr)[token_pos]),
1707 if (tree.current_node->name.compare(
"Grad") == 0) {
1708 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1709 if (t_type != GA_LPAR)
1710 ga_throw_error(expr, pos-1,
"Missing Grad argument.");
1711 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1712 if (t_type != GA_NAME)
1713 ga_throw_error(expr, pos,
1714 "Argument of Grad should be a variable name, here.");
1715 tree.current_node->name = std::string(&((*expr)[token_pos]),
1717 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1718 if (t_type != GA_RPAR)
1719 ga_throw_error(expr, pos-1,
1720 "The sole argument of Grad should be a variable name, here.");
1721 tree.current_node->name =
"Grad_" + tree.current_node->name;
1724 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1725 if (t_type != GA_COMMA)
1726 ga_throw_error(expr, pos,
"Bad format for Interpolate "
1728 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1729 if (t_type != GA_NAME)
1730 ga_throw_error(expr, pos,
1731 "Second argument of Interpolate should be a "
1732 "transformation name.");
1733 tree.current_node->interpolate_name
1734 = std::string(&((*expr)[token_pos]), token_length);
1735 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1736 if (t_type != GA_RPAR)
1737 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1738 "interpolate arguments.");
1743 case GA_INTERPOLATE_DERIVATIVE:
1745 tree.add_scalar(scalar_type(0), token_pos, expr);
1746 tree.current_node->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
1747 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1748 if (t_type != GA_LPAR)
1749 ga_throw_error(expr, pos-1,
1750 "Missing Interpolate_derivative arguments.");
1751 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1752 if (t_type != GA_NAME)
1753 ga_throw_error(expr, pos,
1754 "First argument of Interpolate should the "
1755 "interpolate transformation name ");
1756 tree.current_node->interpolate_name_der
1757 = std::string(&((*expr)[token_pos]), token_length);
1758 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1759 if (t_type != GA_COMMA)
1760 ga_throw_error(expr, pos,
"Bad format for Interpolate_derivative "
1762 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1763 if (t_type != GA_NAME)
1764 ga_throw_error(expr, pos,
1765 "Second argument of Interpolate should be a "
1767 tree.current_node->name
1768 = std::string(&((*expr)[token_pos]), token_length);
1770 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1771 tree.current_node->interpolate_name =
"";
1772 if (t_type == GA_COMMA) {
1773 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1774 if (t_type != GA_NAME)
1775 ga_throw_error(expr, pos,
1776 "Third argument of Interpolate should be a "
1777 "interpolate transformation name.");
1778 tree.current_node->interpolate_name
1779 = std::string(&((*expr)[token_pos]), token_length);
1780 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1782 if (t_type != GA_RPAR)
1783 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1784 "Interpolate_derivative arguments.");
1791 tree.add_scalar(scalar_type(0), token_pos, expr);
1792 tree.current_node->node_type = GA_NODE_ELEMENTARY;
1793 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1794 if (t_type != GA_LPAR)
1795 ga_throw_error(expr, pos-1,
1796 "Missing Elementary_transformation arguments.");
1797 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1798 if (t_type != GA_NAME)
1799 ga_throw_error(expr, pos,
1800 "First argument of Elementary_transformation "
1801 "should be a variable or a test function.");
1802 tree.current_node->name = std::string(&((*expr)[token_pos]),
1804 tree.current_node->elementary_target = tree.current_node->name;
1806 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1807 if (t_type != GA_COMMA)
1808 ga_throw_error(expr, pos,
"Bad format for "
1809 "Elementary_transformation arguments.");
1810 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1811 if (t_type != GA_NAME)
1812 ga_throw_error(expr, pos,
1813 "Second argument of Elementary_transformation "
1814 "should be a transformation name.");
1815 tree.current_node->elementary_name
1816 = std::string(&((*expr)[token_pos]), token_length);
1817 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1819 if (t_type == GA_COMMA) {
1820 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1821 if (t_type != GA_NAME)
1822 ga_throw_error(expr, pos,
1823 "Third argument of Elementary_transformation "
1824 "should be a variable or data name.");
1826 tree.current_node->elementary_target =
1827 std::string(&((*expr)[token_pos]), token_length);
1828 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1831 if (t_type != GA_RPAR)
1832 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1833 "Elementary_transformation arguments.");
1838 case GA_SECONDARY_DOMAIN:
1840 tree.add_scalar(scalar_type(0), token_pos, expr);
1841 tree.current_node->node_type = GA_NODE_SECONDARY_DOMAIN;
1842 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1843 if (t_type != GA_LPAR)
1844 ga_throw_error(expr, pos-1,
"Missing Secondary_domain arguments.");
1845 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1846 if (t_type != GA_NAME)
1847 ga_throw_error(expr, pos,
1848 "First argument of Secondary_domain should be a "
1849 "variable, test function, X or Normal.");
1850 tree.current_node->name = std::string(&((*expr)[token_pos]),
1852 tree.current_node->interpolate_name = tree.secondary_domain;
1853 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1854 if (t_type != GA_RPAR)
1855 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1856 "Secondary_domain arguments.");
1863 tree.add_scalar(scalar_type(0), token_pos, expr);
1864 tree.current_node->node_type = GA_NODE_XFEM_PLUS;
1865 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1866 if (t_type != GA_LPAR)
1867 ga_throw_error(expr, pos-1,
1868 "Missing Xfem_plus arguments.");
1869 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1870 if (t_type != GA_NAME)
1871 ga_throw_error(expr, pos,
1872 "The argument of Xfem_plus should be a "
1873 "variable or a test function.");
1874 tree.current_node->name = std::string(&((*expr)[token_pos]),
1876 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1877 if (t_type != GA_RPAR)
1878 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1879 "Xfem_plus argument.");
1886 tree.add_scalar(scalar_type(0), token_pos, expr);
1887 tree.current_node->node_type = GA_NODE_XFEM_MINUS;
1888 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1889 if (t_type != GA_LPAR)
1890 ga_throw_error(expr, pos-1,
1891 "Missing Xfem_minus arguments.");
1892 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1893 if (t_type != GA_NAME)
1894 ga_throw_error(expr, pos,
1895 "The argument of Xfem_minus should be a "
1896 "variable or a test function.");
1897 tree.current_node->name = std::string(&((*expr)[token_pos]),
1899 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1900 if (t_type != GA_RPAR)
1901 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1902 "Xfem_minus argument.");
1907 case GA_INTERPOLATE_FILTER:
1909 tree.add_scalar(scalar_type(0), token_pos, expr);
1910 tree.current_node->node_type = GA_NODE_INTERPOLATE_FILTER;
1911 tree.current_node->nbc1 =
size_type(-1);
1912 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1913 if (t_type != GA_LPAR)
1914 ga_throw_error(expr, pos-1,
"Missing interpolate arguments.");
1915 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1916 if (t_type != GA_NAME)
1917 ga_throw_error(expr, pos,
"First argument of Interpolate_filter "
1918 "should be a transformation name.");
1919 tree.current_node->interpolate_name
1920 = std::string(&((*expr)[token_pos]), token_length);
1921 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1922 if (t_type != GA_COMMA)
1923 ga_throw_error(expr, pos,
1924 "Bad format for Interpolate_filter arguments.");
1926 t_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1927 if (t_type != GA_RPAR && t_type != GA_COMMA)
1928 ga_throw_error(expr, pos-1,
1929 "Bad format for Interpolate_filter arguments.");
1930 tree.add_sub_tree(sub_tree);
1931 if (t_type == GA_COMMA) {
1933 t_type = ga_read_term(expr, pos, sub_tree2, macro_dict);
1934 tree.add_sub_tree(sub_tree2);
1936 if (t_type != GA_RPAR)
1937 ga_throw_error(expr, pos-1,
"Unbalanced parenthesis.");
1943 tree.add_op(GA_PRINT, token_pos, expr);
1949 GA_TOKEN_TYPE r_type;
1950 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1951 if (r_type != GA_RPAR)
1952 ga_throw_error(expr, pos-1,
"Unbalanced parenthesis.");
1953 tree.add_sub_tree(sub_tree);
1961 GA_TOKEN_TYPE r_type;
1962 size_type nbc1(0), nbc2(0), nbc3(0), n1(0), n2(0), n3(0);
1964 bool foundcomma(
false), foundsemi(
false);
1966 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1968 tree.add_matrix(token_pos, expr);
1970 if (sub_tree.root->node_type == GA_NODE_C_MATRIX) {
1971 bgeot::multi_index mii;
1975 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1978 if (sub_tree.root->node_type != GA_NODE_C_MATRIX ||
1979 (r_type != GA_COMMA && r_type != GA_RBRACKET))
1980 ga_throw_error(expr, pos-1,
"Bad explicit "
1981 "vector/matrix/tensor format.");
1984 if (sub_tree.root->marked &&
1985 sub_tree.root->tensor().sizes()[0] == 1 &&
1986 sub_tree.root->tensor().size() != 1) {
1987 bgeot::multi_index mi = sub_tree.root->tensor().sizes();
1988 for (
size_type i = mi.size()-1; i > 0; i--)
1991 sub_tree.root->tensor().adjust_sizes(mi);
1994 mii = sub_tree.root->tensor().sizes();
1996 const bgeot::multi_index &mi=sub_tree.root->tensor().sizes();
1998 if (mii.size() == mi.size()) {
1999 for (
size_type i = 0; i < mi.size(); ++i)
2000 if (mi[i] != mii[i]) cmp =
false;
2003 ga_throw_error(expr, pos-1,
"Bad explicit "
2004 "vector/matrix/tensor format.");
2006 for (pga_tree_node &child : sub_tree.root->children) {
2007 child->parent = tree.current_node;
2008 tree.current_node->children.push_back(child);
2010 sub_tree.root->children.resize(0);
2012 }
while (r_type != GA_RBRACKET);
2013 tree.current_node->marked =
false;
2014 mii.push_back(nb_comp);
2015 tree.current_node->tensor().adjust_sizes(mii);
2020 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
2024 tree.add_sub_tree(sub_tree);
2027 if (tensor_order < 2) ++nbc1;
2028 if (tensor_order < 3) ++nbc2;
2029 if (tensor_order < 4) ++nbc3;
2031 if (r_type == GA_COMMA) {
2032 if (!foundcomma && tensor_order > 1)
2033 ga_throw_error(expr, pos-1,
"Bad explicit "
2034 "vector/matrix/tensor format.");
2036 }
else if (r_type == GA_SEMICOLON) {
2038 ga_throw_error(expr, pos-1,
"Bad explicit "
2039 "vector/matrix/tensor format.");
2041 tensor_order = std::max(tensor_order,
size_type(2));
2042 }
else if (r_type == GA_DCOMMA) {
2043 if (n1 != nbc1 || n2 != nbc2)
2044 ga_throw_error(expr, pos-1,
"Bad explicit "
2045 "vector/matrix/tensor format.");
2048 tensor_order = std::max(tensor_order,
size_type(3));
2049 }
else if (r_type == GA_DSEMICOLON) {
2050 if (n1 != nbc1 || n2 != nbc2 || n3 != nbc3 ||
2052 ga_throw_error(expr, pos-1,
"Bad explicit "
2053 "vector/matrix/tensor format.");
2055 tensor_order = std::max(tensor_order,
size_type(4));
2056 }
else if (r_type == GA_RBRACKET) {
2057 if (n1 != nbc1 || n2 != nbc2 || n3 != nbc3 ||
2059 ga_throw_error(expr, pos-1,
"Bad explicit "
2060 "vector/matrix/tensor format.");
2061 tree.current_node->nbc1 = nbc1;
2062 if (tensor_order == 4) {
2063 tree.current_node->nbc2 = nbc2/nbc1;
2064 tree.current_node->nbc3 = nbc3/nbc2;
2066 tree.current_node->nbc2 = tree.current_node->nbc3 = 1;
2069 ga_throw_error(expr, pos-1,
"The explicit "
2070 "vector/matrix/tensor components should be "
2071 "separated by ',', ';', ',,' and ';;' and "
2072 "be ended by ']'.");
2075 }
while (r_type != GA_RBRACKET);
2076 bgeot::multi_index mi;
2077 nbc1 = tree.current_node->nbc1;
2078 nbc2 = tree.current_node->nbc2;
2079 nbc3 = tree.current_node->nbc3;
2081 size_type nbl = tree.current_node->children.size()
2082 / (nbc2 * nbc1 * nbc3);
2083 switch(tensor_order) {
2104 default: GMM_ASSERT1(
false,
"Internal error");
2106 tree.current_node->tensor().adjust_sizes(mi);
2107 std::vector<pga_tree_node> children = tree.current_node->children;
2108 auto it = tree.current_node->children.begin();
2112 for (
size_type l = 0; l < nbl; ++l, ++it)
2113 *it = children[i+nbc1*(j+nbc2*(k+nbc3*l))];
2114 tree.current_node->marked =
true;
2117 tree.current_node->nbc1 = tree.current_node->tensor().sizes().size();
2122 ga_throw_error(expr, token_pos,
"Unexpected token.");
2128 case GA_PLUS:
case GA_MINUS:
case GA_MULT:
case GA_DIV:
2129 case GA_COLON:
case GA_DOT:
case GA_DOTMULT:
case GA_DOTDIV:
2131 tree.add_op(t_type, token_pos, expr);
2135 tree.add_op(t_type, token_pos, expr);
2138 case GA_END:
case GA_RPAR:
case GA_COMMA:
case GA_DCOMMA:
2139 case GA_RBRACKET:
case GA_SEMICOLON:
case GA_DSEMICOLON:
2144 GA_TOKEN_TYPE r_type;
2145 tree.add_params(token_pos, expr);
2147 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
2148 if (r_type != GA_RPAR && r_type != GA_COMMA)
2149 ga_throw_error(expr, pos-((r_type != GA_END)?1:0),
2150 "Parameters should be separated "
2151 "by ',' and parameter list ended by ')'.");
2152 tree.add_sub_tree(sub_tree);
2153 }
while (r_type != GA_RPAR);
2159 ga_throw_error(expr, token_pos,
"Unexpected token.");
2169 void ga_read_string_reg(
const std::string &expr, ga_tree &tree,
2170 ga_macro_dictionary ¯o_dict) {
2171 size_type pos = 0, token_pos, token_length;
2173 GA_TOKEN_TYPE t = ga_get_token(expr, pos, token_pos, token_length);
2174 if (t == GA_END)
return;
2176 pstring nexpr(
new std::string(expr));
2178 t = ga_read_term(nexpr, pos, tree, macro_dict);
2179 if (tree.root) ga_expand_macro(tree, tree.root, macro_dict);
2183 ga_throw_error(nexpr, pos-1,
"Unbalanced parenthesis.");
2186 ga_throw_error(nexpr, pos-1,
"Unbalanced bracket.");
2191 ga_throw_error(nexpr, pos-1,
"Unexpected token.");
2198 void ga_read_string(
const std::string &expr, ga_tree &tree,
2199 const ga_macro_dictionary ¯o_dict) {
2200 ga_macro_dictionary macro_dict_loc(
true, macro_dict);
2201 ga_read_string_reg(expr, tree, macro_dict_loc);
2206 std::string ga_substitute(
const std::string &expr,
2207 const std::map<std::string, std::string> &dict) {
2209 size_type pos = 0, token_pos, token_length;
2210 std::stringstream exprs;
2213 GA_TOKEN_TYPE t_type = ga_get_token(expr, pos, token_pos, token_length);
2214 if (t_type == GA_END)
return exprs.str();
2215 std::string name(&(expr[token_pos]), token_length);
2216 if (t_type == GA_NAME && dict.find(name) != dict.end())
2217 exprs << dict.at(name);
else exprs << name;
static T & instance()
Instance from the current thread.
Compilation and execution operations.
size_t size_type
used as the common size type in the library
GEneric Tool for Finite Element Methods.