23 #include "getfem/getfem_generic_assembly_functions_and_operators.h"
24 #include "getfem/getfem_generic_assembly_compile_and_exec.h"
33 static GA_TOKEN_TYPE ga_char_type[256];
34 static int ga_operator_priorities[GA_NB_TOKEN_TYPE];
37 static bool init_ga_char_type() {
38 for (
int i = 0; i < 256; ++i) ga_char_type[i] = GA_INVALID;
39 ga_char_type[
'+'] = GA_PLUS; ga_char_type[
'-'] = GA_MINUS;
40 ga_char_type[
'*'] = GA_MULT; ga_char_type[
'/'] = GA_DIV;
41 ga_char_type[
':'] = GA_COLON; ga_char_type[
'\''] = GA_QUOTE;
42 ga_char_type[
'.'] = GA_DOT; ga_char_type[
'@'] = GA_TMULT;
43 ga_char_type[
','] = GA_COMMA; ga_char_type[
';'] = GA_SEMICOLON;
44 ga_char_type[
'('] = GA_LPAR; ga_char_type[
')'] = GA_RPAR;
45 ga_char_type[
'['] = GA_LBRACKET; ga_char_type[
']'] = GA_RBRACKET;
46 ga_char_type[
'_'] = GA_NAME; ga_char_type[
'='] = GA_COLON_EQ;
47 for (
unsigned i =
'a'; i <=
'z'; ++i) ga_char_type[i] = GA_NAME;
48 for (
unsigned i =
'A'; i <=
'Z'; ++i) ga_char_type[i] = GA_NAME;
49 for (
unsigned i =
'0'; i <=
'9'; ++i) ga_char_type[i] = GA_SCALAR;
51 for (
unsigned i=0; i < GA_NB_TOKEN_TYPE; ++i) ga_operator_priorities[i] = 0;
52 ga_operator_priorities[GA_PLUS] = 1;
53 ga_operator_priorities[GA_MINUS] = 1;
54 ga_operator_priorities[GA_MULT] = 2;
55 ga_operator_priorities[GA_DIV] = 2;
56 ga_operator_priorities[GA_COLON] = 2;
57 ga_operator_priorities[GA_DOT] = 2;
58 ga_operator_priorities[GA_DOTMULT] = 2;
59 ga_operator_priorities[GA_DOTDIV] = 2;
60 ga_operator_priorities[GA_TMULT] = 2;
61 ga_operator_priorities[GA_QUOTE] = 3;
62 ga_operator_priorities[GA_UNARY_MINUS] = 3;
63 ga_operator_priorities[GA_SYM] = 4;
64 ga_operator_priorities[GA_SKEW] = 4;
65 ga_operator_priorities[GA_TRACE] = 4;
66 ga_operator_priorities[GA_DEVIATOR] = 4;
67 ga_operator_priorities[GA_PRINT] = 4;
72 static bool ga_initialized = init_ga_char_type();
75 static GA_TOKEN_TYPE ga_get_token(
const std::string &expr,
79 bool fdot =
false, fE =
false;
80 GMM_ASSERT1(ga_initialized,
"Internal error");
83 while (expr[pos] ==
' ' && pos < expr.size()) ++pos;
88 if (pos >= expr.size())
return GA_END;
91 GA_TOKEN_TYPE type = ga_char_type[unsigned(expr[pos])];
92 ++pos; ++token_length;
94 if (pos >= expr.size())
return type;
95 if (expr[pos] ==
'*') { ++pos; ++token_length;
return GA_DOTMULT; }
96 if (expr[pos] ==
'/') { ++pos; ++token_length;
return GA_DOTDIV; }
97 if (ga_char_type[
unsigned(expr[pos])] != GA_SCALAR)
return type;
98 fdot =
true; type = GA_SCALAR;
102 while (pos < expr.size()) {
103 GA_TOKEN_TYPE ctype = ga_char_type[unsigned(expr[pos])];
106 if (fdot)
return type;
107 fdot =
true; ++pos; ++token_length;
110 if (fE || (expr[pos] !=
'E' && expr[pos] !=
'e'))
return type;
111 fE =
true; fdot =
true; ++pos; ++token_length;
112 if (pos < expr.size()) {
113 if (expr[pos] ==
'+' || expr[pos] ==
'-')
114 { ++pos; ++token_length; }
116 if (pos >= expr.size()
117 || ga_char_type[
unsigned(expr[pos])] != GA_SCALAR)
121 ++pos; ++token_length;
break;
128 while (pos < expr.size()) {
129 GA_TOKEN_TYPE ctype = ga_char_type[unsigned(expr[pos])];
130 if (ctype != GA_SCALAR && ctype != GA_NAME)
break;
131 ++pos; ++token_length;
133 if (expr.compare(token_pos, token_length,
"Sym") == 0)
135 if (expr.compare(token_pos, token_length,
"Def") == 0)
137 if (expr.compare(token_pos, token_length,
"Skew") == 0)
139 if (expr.compare(token_pos, token_length,
"Trace") == 0)
141 if (expr.compare(token_pos, token_length,
"Deviator") == 0)
143 if (expr.compare(token_pos, token_length,
"Interpolate") == 0)
144 return GA_INTERPOLATE;
145 if (expr.compare(token_pos, token_length,
"Interpolate_derivative") == 0)
146 return GA_INTERPOLATE_DERIVATIVE;
147 if (expr.compare(token_pos, token_length,
"Interpolate_filter") == 0)
148 return GA_INTERPOLATE_FILTER;
149 if (expr.compare(token_pos, token_length,
150 "Elementary_transformation") == 0)
151 return GA_ELEMENTARY;
152 if (expr.compare(token_pos, token_length,
"Secondary_domain") == 0 ||
153 expr.compare(token_pos, token_length,
"Secondary_Domain") == 0)
154 return GA_SECONDARY_DOMAIN;
155 if (expr.compare(token_pos, token_length,
"Xfem_plus") == 0)
157 if (expr.compare(token_pos, token_length,
"Xfem_minus") == 0)
158 return GA_XFEM_MINUS;
159 if (expr.compare(token_pos, token_length,
"Print") == 0)
163 if (pos < expr.size() &&
164 ga_char_type[
unsigned(expr[pos])] == GA_COMMA) {
165 ++pos;
return GA_DCOMMA;
169 if (pos < expr.size() &&
170 ga_char_type[
unsigned(expr[pos])] == GA_SEMICOLON) {
171 ++pos;
return GA_DSEMICOLON;
175 if (pos < expr.size() &&
176 ga_char_type[
unsigned(expr[pos])] == GA_COLON_EQ) {
177 ++pos;
return GA_COLON_EQ;
182 default:
return type;
190 void ga_throw_error_msg(pstring expr,
size_type pos,
191 const std::string &msg) {
192 int length_before = 70, length_after = 70;
193 if (expr && expr->size()) {
194 int first = std::max(0,
int(pos)-length_before);
195 int last = std::min(
int(pos)+length_after,
int(expr->size()));
196 if (last - first < length_before+length_after)
197 first = std::max(0,
int(pos)-length_before
198 -(length_before+length_after-last+first));
199 if (last - first < length_before+length_after)
200 last = std::min(
int(pos)+length_after
201 +(length_before+length_after-last+first),
203 if (first > 0) cerr <<
"...";
204 cerr << expr->substr(first, last-first);
205 if (last <
int(expr->size())) cerr <<
"...";
207 if (first > 0) cerr <<
" ";
208 if (
int(pos) > first)
209 cerr << std::setfill (
'-') << std::setw(
int(pos)-first) <<
'-'
210 << std::setfill (
' ');
220 void ga_tree_node::mult_test(
const pga_tree_node n0,
const pga_tree_node n1) {
222 size_type test0 = n0->test_function_type, test1 = n1->test_function_type;
223 if (test0 && test1 && (test0 == test1 || test0 >= 3 || test1 >= 3))
224 ga_throw_error(expr, pos,
225 "Incompatibility of test functions in product.");
229 test_function_type = test0 + test1;
232 bgeot::multi_index mi(st);
235 case 1: mi[0] = n0->t.sizes()[0];
break;
236 case 2: mi[st-1] = n0->t.sizes()[0];
break;
237 case 3: mi[0] = n0->t.sizes()[0]; mi[1] = n0->t.sizes()[1];
break;
240 case 1: mi[0] = n1->t.sizes()[0];
break;
241 case 2: mi[st-1] = n1->t.sizes()[0];
break;
242 case 3: mi[0] = n1->t.sizes()[0]; mi[1] = n1->t.sizes()[1];
break;
245 if (n0->name_test1.size()) {
246 name_test1 = n0->name_test1; qdim1 = n0->qdim1;
247 interpolate_name_test1 = n0->interpolate_name_test1;
249 name_test1 = n1->name_test1; qdim1 = n1->qdim1;
250 interpolate_name_test1 = n1->interpolate_name_test1;
253 if (n0->name_test2.size()) {
254 name_test2 = n0->name_test2; qdim2 = n0->qdim2;
255 interpolate_name_test2 = n0->interpolate_name_test2;
257 name_test2 = n1->name_test2; qdim2 = n1->qdim2;
258 interpolate_name_test2 = n1->interpolate_name_test2;
263 void ga_tree::add_scalar(scalar_type val,
size_type pos, pstring expr) {
264 while (current_node && current_node->node_type != GA_NODE_OP)
265 current_node = current_node->parent;
267 current_node->adopt_child(
new ga_tree_node(val, pos, expr));
268 current_node = current_node->children.back();
271 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
272 current_node = root =
new ga_tree_node(val, pos, expr);
273 root->parent =
nullptr;
277 void ga_tree::add_allindices(
size_type pos, pstring expr) {
278 while (current_node && current_node->node_type != GA_NODE_OP)
279 current_node = current_node->parent;
281 current_node->adopt_child(
new ga_tree_node(GA_NODE_ALLINDICES, pos,expr));
282 current_node = current_node->children.back();
285 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
286 current_node = root =
new ga_tree_node(GA_NODE_ALLINDICES, pos, expr);
287 root->parent =
nullptr;
293 while (current_node && current_node->node_type != GA_NODE_OP)
294 current_node = current_node->parent;
296 current_node->adopt_child(
new ga_tree_node(name, length, pos, expr));
297 current_node = current_node->children.back();
300 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
301 current_node = root =
new ga_tree_node(name, length, pos, expr);
302 root->parent =
nullptr;
306 void ga_tree::add_sub_tree(ga_tree &sub_tree) {
308 (current_node->node_type == GA_NODE_PARAMS ||
309 current_node->node_type == GA_NODE_INTERPOLATE_FILTER ||
310 current_node->node_type == GA_NODE_C_MATRIX)) {
311 GMM_ASSERT1(sub_tree.root,
"Invalid tree operation");
312 current_node->adopt_child(sub_tree.root);
314 GMM_ASSERT1(sub_tree.root,
"Invalid tree operation");
315 while (current_node && current_node->node_type != GA_NODE_OP)
316 current_node = current_node->parent;
318 current_node->adopt_child(sub_tree.root);
319 current_node = sub_tree.root;
322 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
323 current_node = root = sub_tree.root;
324 root->parent =
nullptr;
327 sub_tree.root = sub_tree.current_node =
nullptr;
330 void ga_tree::add_params(
size_type pos, pstring expr) {
331 GMM_ASSERT1(current_node,
"internal error");
332 while (current_node && current_node->parent &&
333 current_node->parent->node_type == GA_NODE_OP &&
334 ga_operator_priorities[current_node->parent->op_type] >= 4)
335 current_node = current_node->parent;
336 pga_tree_node new_node =
new ga_tree_node(GA_NODE_PARAMS, pos, expr);
337 new_node->parent = current_node->parent;
338 if (current_node->parent)
339 current_node->parent->replace_child(current_node, new_node);
342 new_node->adopt_child(current_node);
343 current_node = new_node;
346 void ga_tree::add_matrix(
size_type pos, pstring expr) {
347 while (current_node && current_node->node_type != GA_NODE_OP)
348 current_node = current_node->parent;
350 current_node->adopt_child(
new ga_tree_node(GA_NODE_C_MATRIX, pos, expr));
351 current_node = current_node->children.back();
354 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
355 current_node = root =
new ga_tree_node(GA_NODE_C_MATRIX, pos, expr);
356 root->parent =
nullptr;
358 current_node->nbc1 = current_node->nbc2 = current_node->nbc3 = 0;
361 void ga_tree::add_op(GA_TOKEN_TYPE op_type,
size_type pos,
363 while (current_node && current_node->parent &&
364 current_node->parent->node_type == GA_NODE_OP &&
365 ga_operator_priorities[current_node->parent->op_type]
366 >= ga_operator_priorities[op_type])
367 current_node = current_node->parent;
368 pga_tree_node new_node =
new ga_tree_node(op_type, pos, expr);
370 if (op_type == GA_UNARY_MINUS
371 || op_type == GA_SYM || op_type == GA_SKEW
372 || op_type == GA_TRACE || op_type == GA_DEVIATOR
373 || op_type == GA_PRINT) {
374 current_node->adopt_child(new_node);
376 new_node->parent = current_node->parent;
377 if (current_node->parent)
378 current_node->parent->replace_child(current_node, new_node);
381 new_node->adopt_child(current_node);
384 if (root) new_node->adopt_child(root);
386 root->parent =
nullptr;
388 current_node = new_node;
391 void ga_tree::clear_node_rec(pga_tree_node pnode) {
393 for (pga_tree_node &child : pnode->children)
394 clear_node_rec(child);
396 current_node =
nullptr;
400 void ga_tree::clear_node(pga_tree_node pnode) {
402 pga_tree_node parent = pnode->parent;
405 for (pga_tree_node &sibling : parent->children)
406 if (sibling != pnode)
407 parent->children[j++] = sibling;
408 parent->children.resize(j);
412 clear_node_rec(pnode);
415 void ga_tree::clear_children(pga_tree_node pnode) {
416 for (pga_tree_node &child : pnode->children)
417 clear_node_rec(child);
418 pnode->children.resize(0);
421 void ga_tree::replace_node_by_child(pga_tree_node pnode,
size_type i) {
422 GMM_ASSERT1(i < pnode->children.size(),
"Internal error");
423 pga_tree_node child = pnode->children[i];
424 child->parent = pnode->parent;
426 pnode->parent->replace_child(pnode, child);
429 current_node =
nullptr;
430 for (pga_tree_node &sibling : pnode->children)
431 if (sibling != child) clear_node_rec(sibling);
437 void ga_tree::copy_node(pga_tree_node pnode,
438 pga_tree_node &pnode_new) {
439 GMM_ASSERT1(pnode_new ==
nullptr,
"Internal error");
440 pnode_new =
new ga_tree_node();
442 pnode_new->parent =
nullptr;
443 for (
size_type j = 0; j < pnode_new->children.size(); ++j) {
444 pnode_new->children[j] =
nullptr;
445 copy_node(pnode->children[j], pnode_new->children[j]);
446 pnode_new->accept_child(j);
450 void ga_tree::duplicate_with_operation(pga_tree_node pnode,
451 GA_TOKEN_TYPE op_type) {
452 pga_tree_node newop =
new ga_tree_node(op_type, pnode->pos, pnode->expr);
453 newop->children.resize(2,
nullptr);
454 newop->children[0] = pnode;
455 newop->pos = pnode->pos; newop->expr = pnode->expr;
456 newop->parent = pnode->parent;
458 pnode->parent->replace_child(pnode, newop);
461 pnode->parent = newop;
462 copy_node(pnode, newop->children[1]);
463 newop->accept_child(1);
466 void ga_tree::add_child(pga_tree_node pnode, GA_NODE_TYPE node_type) {
467 pga_tree_node newnode=
new ga_tree_node();
468 newnode->pos = pnode->pos; newnode->expr = pnode->expr;
469 newnode->node_type = node_type; pnode->adopt_child(newnode);
472 void ga_tree::insert_node(pga_tree_node pnode, GA_NODE_TYPE node_type) {
473 pga_tree_node newnode =
new ga_tree_node();
474 newnode->node_type = node_type;
475 newnode->parent = pnode->parent;
476 newnode->pos = pnode->pos; newnode->expr = pnode->expr;
478 pnode->parent->replace_child(pnode, newnode);
481 newnode->adopt_child(pnode);
484 bool sub_tree_are_equal
485 (
const pga_tree_node pnode1,
const pga_tree_node pnode2,
486 const ga_workspace &workspace,
int version) {
489 if (ntype1 == GA_NODE_ZERO) ntype1 = GA_NODE_CONSTANT;
491 if (ntype2 == GA_NODE_ZERO) ntype2 = GA_NODE_CONSTANT;
492 if (ntype1 != ntype2)
return false;
493 if (pnode1->children.size() != pnode2->children.size())
return false;
497 if (pnode1->op_type != pnode2->op_type)
return false;
498 if (pnode1->symmetric_op != pnode2->symmetric_op)
return false;
500 case GA_NODE_OPERATOR:
501 if (pnode1->der1 != pnode2->der1 || pnode1->der2 != pnode2->der2)
503 if (pnode1->name.compare(pnode2->name))
return false;
505 case GA_NODE_PREDEF_FUNC:
case GA_NODE_SPEC_FUNC:
506 if (pnode1->name.compare(pnode2->name))
return false;
508 case GA_NODE_CONSTANT:
case GA_NODE_ZERO:
509 if (pnode1->tensor().size() != pnode2->tensor().size())
return false;
513 if (pnode1->test_function_type != pnode2->test_function_type)
515 if ((pnode1->test_function_type & 1) &&
516 pnode1->name_test1.compare(pnode2->name_test1) != 0)
518 if ((pnode1->test_function_type & 2) &&
519 pnode1->name_test2.compare(pnode2->name_test2) != 0)
523 if ((pnode1->test_function_type == 1 &&
524 pnode2->test_function_type == 1) ||
525 (pnode1->test_function_type == 2 &&
526 pnode2->test_function_type == 2))
528 if ((pnode1->test_function_type & 1) &&
529 pnode1->name_test1.compare(pnode2->name_test2) != 0)
531 if ((pnode1->test_function_type & 2) &&
532 pnode1->name_test2.compare(pnode2->name_test1) != 0)
536 if (pnode1->tensor().size() != 1 &&
537 pnode1->t.sizes().size() != pnode2->t.sizes().size())
return false;
538 for (
size_type i = 0; i < pnode1->t.sizes().size(); ++i)
539 if (pnode1->t.sizes()[i] != pnode2->t.sizes()[i])
return false;
540 for (
size_type i = 0; i < pnode1->tensor().size(); ++i)
541 if (gmm::abs(pnode1->tensor()[i] - pnode2->tensor()[i]) > 1E-25)
544 case GA_NODE_C_MATRIX:
545 if (pnode1->children.size() != pnode2->children.size() ||
546 pnode1->nb_test_functions() != pnode2->nb_test_functions() ||
547 pnode1->t.sizes().size() != pnode2->t.sizes().size())
549 for (
size_type i=pnode1->nb_test_functions();
550 i < pnode1->t.sizes().size(); ++i)
551 if (pnode1->t.sizes()[i] != pnode2->t.sizes()[i])
return false;
552 if (pnode1->nbc1 != pnode2->nbc1)
return false;
554 case GA_NODE_INTERPOLATE_FILTER:
555 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
556 pnode1->nbc1 != pnode2->nbc1)
559 case GA_NODE_INTERPOLATE_X:
560 case GA_NODE_SECONDARY_DOMAIN_X:
561 case GA_NODE_INTERPOLATE_ELT_K:
case GA_NODE_INTERPOLATE_ELT_B:
562 case GA_NODE_INTERPOLATE_NORMAL:
563 case GA_NODE_SECONDARY_DOMAIN_NORMAL:
564 if (pnode1->interpolate_name.compare(pnode2->interpolate_name))
567 case GA_NODE_INTERPOLATE_DERIVATIVE:
568 if (pnode1->interpolate_name_der.compare(pnode2->interpolate_name_der))
570 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
571 pnode1->elementary_name.compare(pnode2->elementary_name))
574 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
575 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
578 if (pnode1->name.compare(pnode2->name) ||
579 pnode1->test_function_type != pnode2->test_function_type)
584 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
585 pnode1->test_function_type != pnode2->test_function_type)
590 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
591 pnode1->test_function_type == pnode2->test_function_type)
597 case GA_NODE_INTERPOLATE_VAL_TEST:
case GA_NODE_INTERPOLATE_GRAD_TEST:
598 case GA_NODE_INTERPOLATE_HESS_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
599 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
600 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
601 case GA_NODE_SECONDARY_DOMAIN_VAL_TEST:
602 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
603 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
604 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
605 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
606 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
607 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
608 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
609 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
610 pnode1->elementary_name.compare(pnode2->elementary_name))
613 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
614 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
617 if (pnode1->name.compare(pnode2->name) ||
618 pnode1->test_function_type != pnode2->test_function_type)
623 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
624 pnode1->test_function_type != pnode2->test_function_type)
629 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
630 pnode1->test_function_type == pnode2->test_function_type)
636 case GA_NODE_VAL_TEST:
case GA_NODE_GRAD_TEST:
637 case GA_NODE_HESS_TEST:
case GA_NODE_DIVERG_TEST:
639 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
640 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
643 if (pnode1->name.compare(pnode2->name) ||
644 pnode1->test_function_type != pnode2->test_function_type)
649 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
650 pnode1->test_function_type != pnode2->test_function_type)
655 workspace.qdim(pnode1->name) != workspace.qdim(pnode2->name) ||
656 pnode1->test_function_type == pnode2->test_function_type)
662 case GA_NODE_VAL:
case GA_NODE_GRAD:
663 case GA_NODE_HESS:
case GA_NODE_DIVERG:
664 if (pnode1->name.compare(pnode2->name))
return false;
666 case GA_NODE_INTERPOLATE_VAL:
case GA_NODE_INTERPOLATE_GRAD:
667 case GA_NODE_INTERPOLATE_HESS:
case GA_NODE_INTERPOLATE_DIVERG:
668 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
669 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
670 case GA_NODE_SECONDARY_DOMAIN_VAL:
case GA_NODE_SECONDARY_DOMAIN_GRAD:
671 case GA_NODE_SECONDARY_DOMAIN_HESS:
case GA_NODE_SECONDARY_DOMAIN_DIVERG:
672 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
673 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
674 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
675 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
676 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
677 pnode1->elementary_name.compare(pnode2->elementary_name) ||
678 pnode1->name.compare(pnode2->name))
682 if (pnode1->nbc1 != pnode2->nbc1)
return false;
688 if (version && ntype1 == GA_NODE_OP && pnode1->symmetric_op) {
689 if (sub_tree_are_equal(pnode1->children[0], pnode2->children[0],
690 workspace, version) &&
691 sub_tree_are_equal(pnode1->children[1], pnode2->children[1],
694 if (sub_tree_are_equal(pnode1->children[1], pnode2->children[0],
695 workspace, version) &&
696 sub_tree_are_equal(pnode1->children[0], pnode2->children[1],
697 workspace, version) )
701 for (
size_type i = 0; i < pnode1->children.size(); ++i)
702 if (!(sub_tree_are_equal(pnode1->children[i], pnode2->children[i],
703 workspace, version)))
709 static void verify_tree(
const pga_tree_node pnode,
710 const pga_tree_node parent) {
711 GMM_ASSERT1(pnode->parent == parent,
712 "Invalid tree node " << pnode->node_type);
713 for (pga_tree_node &child : pnode->children)
714 verify_tree(child, pnode);
718 static void ga_print_constant_tensor(
const pga_tree_node pnode,
720 size_type nt = pnode->nb_test_functions();
721 switch (pnode->tensor_order()) {
723 str << (nt ? scalar_type(0) : pnode->tensor()[0]);
728 for (
size_type i = 0; i < pnode->tensor_proper_size(0); ++i) {
729 if (i != 0) str <<
",";
730 str << (nt ? scalar_type(0) : pnode->tensor()[i]);
735 case 2:
case 3:
case 4:
738 size_type n0 = pnode->tensor_proper_size(0);
739 size_type n1 = pnode->tensor_proper_size(1);
740 size_type n2 = ((pnode->tensor_order() > 2) ?
741 pnode->tensor_proper_size(2) : 1);
742 size_type n3 = ((pnode->tensor_order() > 3) ?
743 pnode->tensor_proper_size(3) : 1);
744 if (n3 > 1) str <<
"[";
746 if (l != 0) str <<
",";
747 if (n2 > 1) str <<
"[";
749 if (k != 0) str <<
",";
750 if (n1 > 1) str <<
"[";
752 if (j != 0) str <<
",";
753 if (n0 > 1) str <<
"[";
755 if (i != 0) str <<
",";
756 str << (nt ? scalar_type(0) : pnode->tensor()[ii++]);
758 if (n0 > 1) str <<
"]";
760 if (n1 > 1) str <<
"]";
762 if (n2 > 1) str <<
"]";
764 if (n3 > 1) str <<
"]";
768 case 5:
case 6:
case 7:
case 8:
770 for (
size_type i = 0; i < pnode->tensor_proper_size(); ++i) {
771 if (i != 0) str <<
";";
772 str << (nt ? scalar_type(0) : pnode->tensor()[i]);
775 for (
size_type i = 0; i < pnode->tensor_order(); ++i) {
776 if (i != 0) str <<
", ";
777 str << pnode->tensor_proper_size(i);
782 default: GMM_ASSERT1(
false,
"Invalid tensor dimension");
784 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
787 void ga_print_node(
const pga_tree_node pnode, std::ostream &str) {
789 long prec = str.precision(16);
791 bool is_interpolate(
false), is_elementary(
false), is_secondary(
false);
792 bool is_xfem_plus(
false), is_xfem_minus(
false);
793 switch(pnode->node_type) {
794 case GA_NODE_INTERPOLATE:
795 case GA_NODE_INTERPOLATE_X:
796 case GA_NODE_INTERPOLATE_ELT_K:
case GA_NODE_INTERPOLATE_ELT_B:
797 case GA_NODE_INTERPOLATE_NORMAL:
798 case GA_NODE_INTERPOLATE_VAL:
799 case GA_NODE_INTERPOLATE_GRAD:
800 case GA_NODE_INTERPOLATE_HESS:
801 case GA_NODE_INTERPOLATE_DIVERG:
802 case GA_NODE_INTERPOLATE_VAL_TEST:
803 case GA_NODE_INTERPOLATE_GRAD_TEST:
804 case GA_NODE_INTERPOLATE_HESS_TEST:
805 case GA_NODE_INTERPOLATE_DIVERG_TEST:
806 str <<
"Interpolate(";
807 is_interpolate =
true;
809 case GA_NODE_ELEMENTARY:
810 case GA_NODE_ELEMENTARY_VAL:
811 case GA_NODE_ELEMENTARY_GRAD:
812 case GA_NODE_ELEMENTARY_HESS:
813 case GA_NODE_ELEMENTARY_DIVERG:
814 case GA_NODE_ELEMENTARY_VAL_TEST:
815 case GA_NODE_ELEMENTARY_GRAD_TEST:
816 case GA_NODE_ELEMENTARY_HESS_TEST:
817 case GA_NODE_ELEMENTARY_DIVERG_TEST:
818 is_elementary =
true;
819 str <<
"Elementary_transformation(";
821 case GA_NODE_SECONDARY_DOMAIN:
822 case GA_NODE_SECONDARY_DOMAIN_X:
823 case GA_NODE_SECONDARY_DOMAIN_NORMAL:
824 case GA_NODE_SECONDARY_DOMAIN_VAL:
825 case GA_NODE_SECONDARY_DOMAIN_GRAD:
826 case GA_NODE_SECONDARY_DOMAIN_HESS:
827 case GA_NODE_SECONDARY_DOMAIN_DIVERG:
828 case GA_NODE_SECONDARY_DOMAIN_VAL_TEST:
829 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
830 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
831 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
832 str <<
"Secondary_domain(";
836 case GA_NODE_XFEM_PLUS:
837 case GA_NODE_XFEM_PLUS_VAL:
838 case GA_NODE_XFEM_PLUS_GRAD:
839 case GA_NODE_XFEM_PLUS_HESS:
840 case GA_NODE_XFEM_PLUS_DIVERG:
841 case GA_NODE_XFEM_PLUS_VAL_TEST:
842 case GA_NODE_XFEM_PLUS_GRAD_TEST:
843 case GA_NODE_XFEM_PLUS_HESS_TEST:
844 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
848 case GA_NODE_XFEM_MINUS:
849 case GA_NODE_XFEM_MINUS_VAL:
850 case GA_NODE_XFEM_MINUS_GRAD:
851 case GA_NODE_XFEM_MINUS_HESS:
852 case GA_NODE_XFEM_MINUS_DIVERG:
853 case GA_NODE_XFEM_MINUS_VAL_TEST:
854 case GA_NODE_XFEM_MINUS_GRAD_TEST:
855 case GA_NODE_XFEM_MINUS_HESS_TEST:
856 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
857 is_xfem_minus =
true;
858 str <<
"Xfem_minus(";
864 switch(pnode->node_type) {
866 case GA_NODE_INTERPOLATE_GRAD:
867 case GA_NODE_ELEMENTARY_GRAD:
868 case GA_NODE_SECONDARY_DOMAIN_GRAD:
869 case GA_NODE_XFEM_PLUS_GRAD:
870 case GA_NODE_XFEM_MINUS_GRAD:
871 case GA_NODE_GRAD_TEST:
872 case GA_NODE_INTERPOLATE_GRAD_TEST:
873 case GA_NODE_ELEMENTARY_GRAD_TEST:
874 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
875 case GA_NODE_XFEM_PLUS_GRAD_TEST:
876 case GA_NODE_XFEM_MINUS_GRAD_TEST:
880 case GA_NODE_INTERPOLATE_HESS:
881 case GA_NODE_ELEMENTARY_HESS:
882 case GA_NODE_SECONDARY_DOMAIN_HESS:
883 case GA_NODE_XFEM_PLUS_HESS:
884 case GA_NODE_XFEM_MINUS_HESS:
885 case GA_NODE_HESS_TEST:
886 case GA_NODE_INTERPOLATE_HESS_TEST:
887 case GA_NODE_ELEMENTARY_HESS_TEST:
888 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
889 case GA_NODE_XFEM_PLUS_HESS_TEST:
890 case GA_NODE_XFEM_MINUS_HESS_TEST:
894 case GA_NODE_INTERPOLATE_DIVERG:
895 case GA_NODE_SECONDARY_DOMAIN_DIVERG:
896 case GA_NODE_ELEMENTARY_DIVERG:
897 case GA_NODE_XFEM_PLUS_DIVERG:
898 case GA_NODE_XFEM_MINUS_DIVERG:
899 case GA_NODE_DIVERG_TEST:
900 case GA_NODE_INTERPOLATE_DIVERG_TEST:
901 case GA_NODE_ELEMENTARY_DIVERG_TEST:
902 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
903 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
904 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
911 switch(pnode->node_type) {
916 if (pnode->parent->node_type == GA_NODE_OP &&
917 (ga_operator_priorities[pnode->op_type] >= 2 ||
918 ga_operator_priorities[pnode->op_type]
919 < ga_operator_priorities[pnode->parent->op_type]))
921 if (pnode->parent->node_type == GA_NODE_PARAMS) par =
true;
926 if (pnode->op_type == GA_UNARY_MINUS) {
927 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
928 str <<
"-"; ga_print_node(pnode->children[0], str);
929 }
else if (pnode->op_type == GA_QUOTE) {
930 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
931 ga_print_node(pnode->children[0], str); str <<
"'";
932 }
else if (pnode->op_type == GA_SYM) {
933 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
934 str <<
"Sym("; ga_print_node(pnode->children[0], str); str <<
")";
935 }
else if (pnode->op_type == GA_SKEW) {
936 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
937 str <<
"Skew("; ga_print_node(pnode->children[0], str); str <<
")";
938 }
else if (pnode->op_type == GA_TRACE) {
939 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
940 str <<
"Trace("; ga_print_node(pnode->children[0], str); str <<
")";
941 }
else if (pnode->op_type == GA_DEVIATOR) {
942 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree with "
943 << pnode->children.size() <<
" children instead of 1");
944 str <<
"Deviator("; ga_print_node(pnode->children[0], str); str<<
")";
945 }
else if (pnode->op_type == GA_PRINT) {
946 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
947 str <<
"Print("; ga_print_node(pnode->children[0], str); str <<
")";
949 if (!par && pnode->op_type == GA_MULT &&
950 (pnode->children.size() == 1 ||
951 pnode->test_function_type ==
size_type(-1) ||
952 (pnode->children[0]->tensor_order() == 4 &&
953 pnode->children[1]->tensor_order() == 2)))
954 { par =
true; str <<
"("; }
955 ga_print_node(pnode->children[0], str);
956 switch (pnode->op_type) {
957 case GA_PLUS: str <<
"+";
break;
958 case GA_MINUS: str <<
"-";
break;
959 case GA_MULT: str <<
"*";
break;
960 case GA_DIV: str <<
"/";
break;
961 case GA_COLON: str <<
":";
break;
962 case GA_DOT: str <<
".";
break;
963 case GA_DOTMULT: str <<
".*";
break;
964 case GA_DOTDIV: str <<
"./";
break;
965 case GA_TMULT: str <<
"@";
break;
966 default: GMM_ASSERT1(
false,
"Invalid or not taken into account "
969 if (pnode->children.size() >= 2)
970 ga_print_node(pnode->children[1], str);
972 str <<
"(unknown second argument)";
979 if (pnode->nbc1) str <<
"X(" << pnode->nbc1 <<
")";
else str <<
"X";
981 case GA_NODE_ELT_SIZE: str <<
"element_size";
break;
982 case GA_NODE_ELT_K: str <<
"element_K";
break;
983 case GA_NODE_ELT_B: str <<
"element_B";
break;
984 case GA_NODE_NORMAL: str <<
"Normal";
break;
985 case GA_NODE_INTERPOLATE_FILTER:
986 str <<
"Interpolate_filter(" << pnode->interpolate_name <<
",";
987 ga_print_node(pnode->children[0], str);
988 if (pnode->children.size() == 2)
989 { str <<
","; ga_print_node(pnode->children[1], str); }
990 else if (pnode->nbc1 !=
size_type(-1)) str <<
"," << pnode->nbc1;
993 case GA_NODE_INTERPOLATE_X:
case GA_NODE_SECONDARY_DOMAIN_X:
996 case GA_NODE_INTERPOLATE_NORMAL:
case GA_NODE_SECONDARY_DOMAIN_NORMAL:
999 case GA_NODE_INTERPOLATE_ELT_K:
1002 case GA_NODE_INTERPOLATE_ELT_B:
1005 case GA_NODE_INTERPOLATE_DERIVATIVE:
1006 str << (pnode->test_function_type == 1 ?
"Test_" :
"Test2_")
1007 <<
"Interpolate_derivative(" << pnode->interpolate_name_der <<
","
1009 if (pnode->interpolate_name.size())
1010 str <<
"," << pnode->interpolate_name;
1013 case GA_NODE_INTERPOLATE:
1014 case GA_NODE_ELEMENTARY:
1015 case GA_NODE_SECONDARY_DOMAIN:
1016 case GA_NODE_XFEM_PLUS:
1017 case GA_NODE_XFEM_MINUS:
1019 case GA_NODE_INTERPOLATE_VAL:
1020 case GA_NODE_ELEMENTARY_VAL:
1021 case GA_NODE_SECONDARY_DOMAIN_VAL:
1022 case GA_NODE_XFEM_PLUS_VAL:
1023 case GA_NODE_XFEM_MINUS_VAL:
1025 case GA_NODE_INTERPOLATE_GRAD:
1026 case GA_NODE_SECONDARY_DOMAIN_GRAD:
1027 case GA_NODE_ELEMENTARY_GRAD:
1028 case GA_NODE_XFEM_PLUS_GRAD:
1029 case GA_NODE_XFEM_MINUS_GRAD:
1031 case GA_NODE_INTERPOLATE_HESS:
1032 case GA_NODE_SECONDARY_DOMAIN_HESS:
1033 case GA_NODE_ELEMENTARY_HESS:
1034 case GA_NODE_XFEM_PLUS_HESS:
1035 case GA_NODE_XFEM_MINUS_HESS:
1036 case GA_NODE_DIVERG:
1037 case GA_NODE_INTERPOLATE_DIVERG:
1038 case GA_NODE_ELEMENTARY_DIVERG:
1039 case GA_NODE_SECONDARY_DOMAIN_DIVERG:
1040 case GA_NODE_XFEM_PLUS_DIVERG:
1041 case GA_NODE_XFEM_MINUS_DIVERG:
1044 case GA_NODE_VAL_TEST:
1045 case GA_NODE_INTERPOLATE_VAL_TEST:
1046 case GA_NODE_ELEMENTARY_VAL_TEST:
1047 case GA_NODE_SECONDARY_DOMAIN_VAL_TEST:
1048 case GA_NODE_XFEM_PLUS_VAL_TEST:
1049 case GA_NODE_XFEM_MINUS_VAL_TEST:
1050 case GA_NODE_GRAD_TEST:
1051 case GA_NODE_INTERPOLATE_GRAD_TEST:
1052 case GA_NODE_ELEMENTARY_GRAD_TEST:
1053 case GA_NODE_SECONDARY_DOMAIN_GRAD_TEST:
1054 case GA_NODE_XFEM_PLUS_GRAD_TEST:
1055 case GA_NODE_XFEM_MINUS_GRAD_TEST:
1056 case GA_NODE_HESS_TEST:
1057 case GA_NODE_INTERPOLATE_HESS_TEST:
1058 case GA_NODE_ELEMENTARY_HESS_TEST:
1059 case GA_NODE_SECONDARY_DOMAIN_HESS_TEST:
1060 case GA_NODE_XFEM_PLUS_HESS_TEST:
1061 case GA_NODE_XFEM_MINUS_HESS_TEST:
1062 case GA_NODE_DIVERG_TEST:
1063 case GA_NODE_INTERPOLATE_DIVERG_TEST:
1064 case GA_NODE_ELEMENTARY_DIVERG_TEST:
1065 case GA_NODE_SECONDARY_DOMAIN_DIVERG_TEST:
1066 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
1067 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
1068 str << (pnode->test_function_type == 1 ?
"Test_" :
"Test2_")
1071 case GA_NODE_SPEC_FUNC: str << pnode->name;
break;
1072 case GA_NODE_OPERATOR:
1073 case GA_NODE_PREDEF_FUNC:
1075 str <<
"Derivative_" << pnode->der1 <<
"_";
1076 if (pnode->der2) str << pnode->der2 <<
"_";
1078 str << pnode->name;
break;
1080 GMM_ASSERT1(pnode->test_function_type !=
size_type(-1),
1082 if (pnode->test_function_type) str <<
"(";
1083 ga_print_constant_tensor(pnode, str);
1084 if (pnode->name_test1.size()) {
1085 GMM_ASSERT1(pnode->qdim1 > 0,
"Internal error");
1086 if (pnode->qdim1 == 1)
1087 str <<
"*Test_" << pnode->name_test1;
1089 str <<
"*(Reshape(Test_" << pnode->name_test1 <<
","
1090 << pnode->qdim1<<
")(1))";
1093 if (pnode->name_test2.size()) {
1094 GMM_ASSERT1(pnode->qdim2 > 0,
"Internal error");
1095 if (pnode->qdim2 == 1)
1096 str <<
"*Test2_" << pnode->name_test2;
1098 str <<
"*(Reshape(Test2_" << pnode->name_test2 <<
","
1099 << pnode->qdim2<<
")(1))";
1102 if (pnode->test_function_type) str <<
")";
1105 case GA_NODE_CONSTANT:
1106 ga_print_constant_tensor(pnode, str);
1109 case GA_NODE_ALLINDICES:
1111 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1114 case GA_NODE_PARAMS:
1115 GMM_ASSERT1(pnode->children.size(),
"Invalid tree");
1116 ga_print_node(pnode->children[0], str);
1118 for (
size_type i = 1; i < pnode->children.size(); ++i) {
1119 if (i > 1) str <<
", ";
1120 ga_print_node(pnode->children[i], str);
1127 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1130 case GA_NODE_MACRO_PARAM:
1131 if (pnode->nbc2 == 1) str <<
"Grad_";
1132 if (pnode->nbc2 == 2) str <<
"Hess_";
1133 if (pnode->nbc2 == 3) str <<
"Div_";
1134 if (pnode->nbc3 == 1) str <<
"Test_";
1135 if (pnode->nbc3 == 2) str <<
"Test2_";
1136 str <<
"P" << pnode->nbc1;
1137 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1140 case GA_NODE_RESHAPE:
1142 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1145 case GA_NODE_CROSS_PRODUCT:
1146 str <<
"Cross_product";
1147 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1150 case GA_NODE_SWAP_IND:
1151 str <<
"Swap_indices";
1152 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1155 case GA_NODE_IND_MOVE_LAST:
1156 str <<
"Index_move_last";
1157 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1160 case GA_NODE_CONTRACT:
1162 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1165 case GA_NODE_C_MATRIX:
1166 GMM_ASSERT1(pnode->children.size(),
"Invalid tree");
1167 GMM_ASSERT1(pnode->nbc1 == pnode->tensor_order(),
"Invalid C_MATRIX");
1168 switch (pnode->tensor_order()) {
1170 ga_print_node(pnode->children[0], str);
1175 for (
size_type i = 0; i < pnode->tensor_proper_size(0); ++i) {
1176 if (i != 0) str <<
",";
1177 ga_print_node(pnode->children[i], str);
1182 case 2:
case 3:
case 4:
1185 size_type n0 = pnode->tensor_proper_size(0);
1186 size_type n1 = pnode->tensor_proper_size(1);
1187 size_type n2 = ((pnode->tensor_order() > 2) ?
1188 pnode->tensor_proper_size(2) : 1);
1189 size_type n3 = ((pnode->tensor_order() > 3) ?
1190 pnode->tensor_proper_size(3) : 1);
1191 if (n3 > 1) str <<
"[";
1193 if (l != 0) str <<
",";
1194 if (n2 > 1) str <<
"[";
1196 if (k != 0) str <<
",";
1197 if (n1 > 1) str <<
"[";
1199 if (j != 0) str <<
",";
1200 if (n0 > 1) str <<
"[";
1202 if (i != 0) str <<
",";
1203 ga_print_node(pnode->children[ii++], str);
1205 if (n0 > 1) str <<
"]";
1207 if (n1 > 1) str <<
"]";
1209 if (n2 > 1) str <<
"]";
1211 if (n3 > 1) str <<
"]";
1215 case 5:
case 6:
case 7:
case 8:
1217 for (
size_type i = 0; i < pnode->tensor_proper_size(); ++i) {
1218 if (i != 0) str <<
";";
1219 ga_print_node(pnode->children[i], str);
1222 for (
size_type i = 0; i < pnode->tensor_order(); ++i) {
1223 if (i != 0) str <<
", ";
1224 str << pnode->tensor_proper_size(i);
1229 default: GMM_ASSERT1(
false,
"Invalid tensor dimension");
1234 str <<
"Invalid or not taken into account node type "
1235 << pnode->node_type;
1240 str <<
"," << pnode->interpolate_name <<
")";
1241 else if (is_elementary) {
1242 str <<
"," << pnode->elementary_name;
1243 if (pnode->name.compare(pnode->elementary_target) != 0)
1244 str <<
"," << pnode->elementary_target;
1246 }
else if (is_secondary)
1248 else if (is_xfem_plus || is_xfem_minus)
1251 str.precision(prec);
1254 std::string ga_tree_to_string(
const ga_tree &tree) {
1255 std::stringstream str;
1257 if (tree.root) verify_tree(tree.root, 0);
1258 if (tree.root) ga_print_node(tree.root, str);
else str <<
"0";
1262 size_type ga_parse_prefix_operator(std::string &name) {
1263 if (name.size() >= 5 && name.compare(0, 5,
"Grad_") == 0)
1264 { name = name.substr(5);
return 1; }
1265 else if (name.size() >= 5 && name.compare(0, 5,
"Hess_") == 0)
1266 { name = name.substr(5);
return 2; }
1267 else if (name.size() >= 4 && name.compare(0, 4,
"Div_") == 0)
1268 { name = name.substr(4);
return 3; }
1272 size_type ga_parse_prefix_test(std::string &name) {
1273 if (name.size() >= 5 && name.compare(0, 5,
"Test_") == 0)
1274 { name = name.substr(5);
return 1; }
1275 else if (name.size() >= 6 && name.compare(0, 6,
"Test2_") == 0)
1276 { name = name.substr(6);
return 2; }
1284 int ga_check_name_validity(
const std::string &name) {
1285 if (name.compare(0, 11,
"Derivative_") == 0)
1288 const ga_predef_operator_tab &PREDEF_OPERATORS
1290 const ga_spec_function_tab &SPEC_FUNCTIONS
1292 const ga_spec_op_tab &SPEC_OP
1294 const ga_predef_function_tab &PREDEF_FUNCTIONS
1297 if (SPEC_OP.find(name) != SPEC_OP.end())
1300 if (PREDEF_FUNCTIONS.find(name) != PREDEF_FUNCTIONS.end())
1303 if (SPEC_FUNCTIONS.find(name) != SPEC_FUNCTIONS.end())
1306 if (PREDEF_OPERATORS.tab.find(name) != PREDEF_OPERATORS.tab.end())
1309 if (name.size() >= 5 && name.compare(0, 5,
"Grad_") == 0)
1312 if (name.size() >= 5 && name.compare(0, 5,
"Hess_") == 0)
1315 if (name.size() >= 4 && name.compare(0, 4,
"Div_") == 0)
1318 if (name.size() >= 6 && name.compare(0, 6,
"Test2_") == 0)
1321 if (name.size() >= 5 && name.compare(0, 5,
"Test_") == 0)
1343 ga_macro::ga_macro() : ptree(new ga_tree), nbp(0) {}
1344 ga_macro::~ga_macro() {
delete ptree; }
1345 ga_macro::ga_macro(
const std::string &name,
const ga_tree &t,
size_type nbp_)
1346 : ptree(new ga_tree(t)), macro_name_(name), nbp(nbp_) {}
1347 ga_macro::ga_macro(
const ga_macro &gam)
1348 : ptree(new ga_tree(gam.tree())), macro_name_(gam.name()),
1349 nbp(gam.nb_params()) {}
1350 ga_macro &ga_macro::operator =(
const ga_macro &gam) {
1351 delete ptree; ptree =
new ga_tree(gam.tree());
1352 macro_name_ = gam.name();
1353 nbp = gam.nb_params();
1357 static void ga_replace_macro_params
1358 (ga_tree &tree, pga_tree_node pnode,
1359 const std::vector<pga_tree_node> &children) {
1361 for (pga_tree_node &child : pnode->children)
1362 ga_replace_macro_params(tree, child, children);
1364 if (pnode->node_type == GA_NODE_MACRO_PARAM) {
1367 GMM_ASSERT1(pnode->nbc1+1 < children.size(),
"Internal error");
1368 pga_tree_node pchild = children[pnode->nbc1+1];
1370 if (po || pt || pnode->op_type != GA_NAME) {
1371 if (!(pchild->children.empty()) || pchild->node_type != GA_NODE_NAME)
1372 ga_throw_error(pchild->expr, pchild->pos,
"Error in macro "
1373 "expansion. Only variable name are allowed for macro "
1374 "parameter preceded by Grad_ Hess_ Test_ or Test2_ "
1376 switch(pnode->op_type) {
1377 case GA_NAME : pnode->node_type = GA_NODE_NAME;
break;
1378 case GA_INTERPOLATE : pnode->node_type = GA_NODE_INTERPOLATE;
break;
1379 case GA_INTERPOLATE_DERIVATIVE :
1380 pnode->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
break;
1381 case GA_ELEMENTARY : pnode->node_type = GA_NODE_ELEMENTARY;
break;
1382 case GA_SECONDARY_DOMAIN :
1383 pnode->node_type = GA_NODE_SECONDARY_DOMAIN;
break;
1384 case GA_XFEM_PLUS : pnode->node_type = GA_NODE_XFEM_PLUS;
break;
1385 case GA_XFEM_MINUS: pnode->node_type = GA_NODE_XFEM_MINUS;
break;
1388 pnode->name = pchild->name;
1389 if (pt == 1) pnode->name =
"Test_" + pnode->name;
1390 if (pt == 2) pnode->name =
"Test2_" + pnode->name;
1391 if (po == 1) pnode->name =
"Grad_" + pnode->name;
1392 if (po == 2) pnode->name =
"Hess_" + pnode->name;
1393 if (po == 3) pnode->name =
"Div_" + pnode->name;
1395 pga_tree_node pnode_old = pnode;
1397 tree.copy_node(pchild, pnode);
1398 pnode->parent = pnode_old->parent;
1399 if (pnode_old->parent)
1400 pnode_old->parent->replace_child(pnode_old, pnode);
1403 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1409 static void ga_expand_macro(ga_tree &tree, pga_tree_node pnode,
1410 const ga_macro_dictionary ¯o_dict) {
1413 if (pnode->node_type == GA_NODE_PARAMS) {
1415 for (
size_type i = 1; i < pnode->children.size(); ++i)
1416 ga_expand_macro(tree, pnode->children[i], macro_dict);
1418 if (pnode->children[0]->node_type != GA_NODE_NAME) {
1419 ga_expand_macro(tree, pnode->children[0], macro_dict);
1422 if (macro_dict.macro_exists(pnode->children[0]->name)) {
1424 const ga_macro &gam = macro_dict.get_macro(pnode->children[0]->name);
1426 if (gam.nb_params()==0) {
1427 pga_tree_node pnode_old = pnode->children[0];
1428 pnode->children[0] =
nullptr;
1429 tree.copy_node(gam.tree().root, pnode->children[0]);
1430 pnode->children[0]->parent = pnode_old->parent;
1431 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1434 if (gam.nb_params()+1 != pnode->children.size())
1435 ga_throw_error(pnode->expr, pnode->pos,
1436 "Bad number of parameters in the use of macro '"
1437 << gam.name() <<
"'. Expected " << gam.nb_params()
1438 <<
" found " << pnode->children.size()-1 <<
".");
1440 pga_tree_node pnode_old = pnode;
1442 tree.copy_node(gam.tree().root, pnode);
1443 pnode->parent = pnode_old->parent;
1444 if (pnode_old->parent)
1445 pnode_old->parent->replace_child(pnode_old, pnode);
1448 ga_replace_macro_params(tree, pnode, pnode_old->children);
1449 tree.clear_node_rec(pnode_old);
1454 }
else if (pnode->node_type == GA_NODE_NAME &&
1455 macro_dict.macro_exists(pnode->name)) {
1457 const ga_macro &gam = macro_dict.get_macro(pnode->name);
1458 if (gam.nb_params() != 0)
1459 ga_throw_error(pnode->expr, pnode->pos,
1460 "Bad number of parameters in the use of macro '"
1461 << gam.name() <<
"'. Expected " << gam.nb_params()
1464 pga_tree_node pnode_old = pnode;
1466 tree.copy_node(gam.tree().root, pnode);
1467 pnode->parent = pnode_old->parent;
1468 if (pnode_old->parent)
1469 pnode_old->parent->replace_child(pnode_old, pnode);
1472 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1475 for (pga_tree_node &child : pnode->children)
1476 ga_expand_macro(tree, child, macro_dict);
1480 static void ga_mark_macro_params_rec(
const pga_tree_node pnode,
1481 const std::vector<std::string> ¶ms) {
1483 for (pga_tree_node &child : pnode->children)
1484 ga_mark_macro_params_rec(child, params);
1486 if (pnode->node_type == GA_NODE_NAME ||
1487 pnode->node_type == GA_NODE_INTERPOLATE ||
1488 pnode->node_type == GA_NODE_ELEMENTARY ||
1489 pnode->node_type == GA_NODE_SECONDARY_DOMAIN ||
1490 pnode->node_type == GA_NODE_XFEM_PLUS ||
1491 pnode->node_type == GA_NODE_XFEM_MINUS) {
1492 std::string name = pnode->name;
1493 size_type po = ga_parse_prefix_operator(name);
1494 size_type pt = ga_parse_prefix_test(name);
1496 for (
size_type i = 0; i < params.size(); ++i)
1497 if (name.compare(params[i]) == 0) {
1499 switch(pnode->node_type) {
1500 case GA_NODE_NAME : pnode->op_type = GA_NAME;
break;
1501 case GA_NODE_INTERPOLATE : pnode->op_type = GA_INTERPOLATE;
break;
1502 case GA_NODE_INTERPOLATE_DERIVATIVE :
1503 pnode->op_type = GA_INTERPOLATE_DERIVATIVE;
break;
1504 case GA_NODE_ELEMENTARY : pnode->op_type = GA_ELEMENTARY;
break;
1505 case GA_NODE_SECONDARY_DOMAIN :
1506 pnode->op_type = GA_SECONDARY_DOMAIN;
break;
1507 case GA_NODE_XFEM_PLUS : pnode->op_type = GA_XFEM_PLUS;
break;
1508 case GA_NODE_XFEM_MINUS: pnode->op_type = GA_XFEM_MINUS;
break;
1511 pnode->node_type = GA_NODE_MACRO_PARAM;
1512 pnode->nbc1 = i; pnode->nbc2 = po; pnode->nbc3 = pt;
1517 static void ga_mark_macro_params(ga_macro &gam,
1518 const std::vector<std::string> ¶ms,
1519 const ga_macro_dictionary ¯o_dict) {
1520 if (gam.tree().root) {
1521 ga_mark_macro_params_rec(gam.tree().root, params);
1522 ga_expand_macro(gam.tree(), gam.tree().root, macro_dict);
1526 bool ga_macro_dictionary::macro_exists(
const std::string &name)
const {
1527 if (macros.find(name) != macros.end())
return true;
1528 if (parent && parent->macro_exists(name))
return true;
1533 ga_macro_dictionary::get_macro(
const std::string &name)
const {
1534 auto it = macros.find(name);
1535 if (it != macros.end())
return it->second;
1536 if (parent)
return parent->get_macro(name);
1537 GMM_ASSERT1(
false,
"Undefined macro");
1540 void ga_macro_dictionary::add_macro(
const ga_macro &gam)
1541 { macros[gam.name()] = gam; }
1543 void ga_macro_dictionary::add_macro(
const std::string &name,
1544 const std::string &expr)
1545 { ga_tree tree; ga_read_string_reg(
"Def "+name+
":="+expr, tree, *
this); }
1547 void ga_macro_dictionary::del_macro(
const std::string &name) {
1548 auto it = macros.find(name);
1549 GMM_ASSERT1(it != macros.end(),
"Undefined macro (at this level)");
1559 static GA_TOKEN_TYPE ga_read_term(pstring expr,
size_type &pos,
1561 ga_macro_dictionary ¯o_dict) {
1563 GA_TOKEN_TYPE t_type;
1568 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1576 char *endptr;
const char *nptr = &((*expr)[token_pos]);
1577 scalar_type s_read = ::strtod(nptr, &endptr);
1579 ga_throw_error(expr, token_pos,
"Bad numeric format.");
1580 tree.add_scalar(s_read, token_pos, expr);
1585 tree.add_allindices(token_pos, expr);
1589 tree.add_name(&((*expr)[token_pos]), token_length, token_pos, expr);
1593 tree.add_op(GA_UNARY_MINUS, token_pos, expr);
1600 tree.add_op(GA_SYM, token_pos, expr);
1604 tree.add_op(GA_SKEW, token_pos, expr);
1608 tree.add_op(GA_TRACE, token_pos, expr);
1612 tree.add_op(GA_DEVIATOR, token_pos, expr);
1618 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1619 if (t_type != GA_NAME)
1620 ga_throw_error(expr, pos,
1621 "Macro definition should begin with macro name");
1622 gam.name() = std::string(&((*expr)[token_pos]), token_length);
1623 if (ga_check_name_validity(gam.name()))
1624 ga_throw_error(expr, pos-1,
"Invalid macro name.")
1625 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1626 std::vector<std::
string> params;
1627 if (t_type == GA_LPAR) {
1628 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1629 while (t_type == GA_NAME) {
1630 params.push_back(std::string(&((*expr)[token_pos]),
1632 if (ga_check_name_validity(params.back()))
1633 ga_throw_error(expr, pos-1,
"Invalid macro parameter name.");
1634 for (
size_type i = 0; i+1 < params.size(); ++i)
1635 if (params.back().compare(params[i]) == 0)
1636 ga_throw_error(expr, pos-1,
1637 "Invalid repeated macro parameter name.");
1638 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1639 if (t_type == GA_COMMA)
1640 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1642 if (t_type != GA_RPAR)
1643 ga_throw_error(expr, pos-1,
1644 "Missing right parenthesis in macro definition.");
1645 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1647 if (t_type != GA_COLON_EQ)
1648 ga_throw_error(expr, pos-1,
"Missing := for macro definition.");
1650 t_type = ga_read_term(expr, pos, gam.tree(), macro_dict);
1651 if (gam.tree().root)
1652 ga_expand_macro(gam.tree(), gam.tree().root, macro_dict);
1653 gam.nb_params() = params.size();
1655 ga_mark_macro_params(gam, params, macro_dict);
1656 macro_dict.add_macro(gam);
1662 if (t_type == GA_END)
return t_type;
1663 else if (t_type != GA_SEMICOLON)
1664 ga_throw_error(expr, pos-1,
1665 "Syntax error at the end of macro definition.");
1670 case GA_INTERPOLATE:
1672 tree.add_scalar(scalar_type(0), token_pos, expr);
1673 tree.current_node->node_type = GA_NODE_INTERPOLATE;
1674 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1675 if (t_type != GA_LPAR)
1676 ga_throw_error(expr, pos-1,
"Missing interpolate arguments.");
1677 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1678 if (t_type != GA_NAME)
1679 ga_throw_error(expr, pos,
1680 "First argument of Interpolate should be a "
1681 "variable, test function, X or Normal.");
1682 tree.current_node->name = std::string(&((*expr)[token_pos]),
1685 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1686 if (t_type != GA_COMMA)
1687 ga_throw_error(expr, pos,
"Bad format for Interpolate "
1689 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1690 if (t_type != GA_NAME)
1691 ga_throw_error(expr, pos,
1692 "Second argument of Interpolate should be a "
1693 "transformation name.");
1694 tree.current_node->interpolate_name
1695 = std::string(&((*expr)[token_pos]), token_length);
1696 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1697 if (t_type != GA_RPAR)
1698 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1699 "interpolate arguments.");
1704 case GA_INTERPOLATE_DERIVATIVE:
1706 tree.add_scalar(scalar_type(0), token_pos, expr);
1707 tree.current_node->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
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,
1711 "Missing Interpolate_derivative arguments.");
1712 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1713 if (t_type != GA_NAME)
1714 ga_throw_error(expr, pos,
1715 "First argument of Interpolate should the "
1716 "interpolate transformation name ");
1717 tree.current_node->interpolate_name_der
1718 = std::string(&((*expr)[token_pos]), token_length);
1719 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1720 if (t_type != GA_COMMA)
1721 ga_throw_error(expr, pos,
"Bad format for Interpolate_derivative "
1723 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1724 if (t_type != GA_NAME)
1725 ga_throw_error(expr, pos,
1726 "Second argument of Interpolate should be a "
1728 tree.current_node->name
1729 = std::string(&((*expr)[token_pos]), token_length);
1731 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1732 tree.current_node->interpolate_name =
"";
1733 if (t_type == GA_COMMA) {
1734 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1735 if (t_type != GA_NAME)
1736 ga_throw_error(expr, pos,
1737 "Third argument of Interpolate should be a "
1738 "interpolate transformation name.");
1739 tree.current_node->interpolate_name
1740 = std::string(&((*expr)[token_pos]), token_length);
1741 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1743 if (t_type != GA_RPAR)
1744 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1745 "Interpolate_derivative arguments.");
1752 tree.add_scalar(scalar_type(0), token_pos, expr);
1753 tree.current_node->node_type = GA_NODE_ELEMENTARY;
1754 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1755 if (t_type != GA_LPAR)
1756 ga_throw_error(expr, pos-1,
1757 "Missing Elementary_transformation arguments.");
1758 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1759 if (t_type != GA_NAME)
1760 ga_throw_error(expr, pos,
1761 "First argument of Elementary_transformation "
1762 "should be a variable or a test function.");
1763 tree.current_node->name = std::string(&((*expr)[token_pos]),
1765 tree.current_node->elementary_target = tree.current_node->name;
1767 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1768 if (t_type != GA_COMMA)
1769 ga_throw_error(expr, pos,
"Bad format for "
1770 "Elementary_transformation arguments.");
1771 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1772 if (t_type != GA_NAME)
1773 ga_throw_error(expr, pos,
1774 "Second argument of Elementary_transformation "
1775 "should be a transformation name.");
1776 tree.current_node->elementary_name
1777 = std::string(&((*expr)[token_pos]), token_length);
1778 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1780 if (t_type == GA_COMMA) {
1781 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1782 if (t_type != GA_NAME)
1783 ga_throw_error(expr, pos,
1784 "Third argument of Elementary_transformation "
1785 "should be a variable or data name.");
1787 tree.current_node->elementary_target =
1788 std::string(&((*expr)[token_pos]), token_length);
1789 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1792 if (t_type != GA_RPAR)
1793 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1794 "Elementary_transformation arguments.");
1799 case GA_SECONDARY_DOMAIN:
1801 tree.add_scalar(scalar_type(0), token_pos, expr);
1802 tree.current_node->node_type = GA_NODE_SECONDARY_DOMAIN;
1803 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1804 if (t_type != GA_LPAR)
1805 ga_throw_error(expr, pos-1,
"Missing Secondary_domain arguments.");
1806 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1807 if (t_type != GA_NAME)
1808 ga_throw_error(expr, pos,
1809 "First argument of Secondary_domain should be a "
1810 "variable, test function, X or Normal.");
1811 tree.current_node->name = std::string(&((*expr)[token_pos]),
1813 tree.current_node->interpolate_name = tree.secondary_domain;
1814 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1815 if (t_type != GA_RPAR)
1816 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1817 "Secondary_domain arguments.");
1824 tree.add_scalar(scalar_type(0), token_pos, expr);
1825 tree.current_node->node_type = GA_NODE_XFEM_PLUS;
1826 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1827 if (t_type != GA_LPAR)
1828 ga_throw_error(expr, pos-1,
1829 "Missing Xfem_plus arguments.");
1830 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1831 if (t_type != GA_NAME)
1832 ga_throw_error(expr, pos,
1833 "The argument of Xfem_plus should be a "
1834 "variable or a test function.");
1835 tree.current_node->name = std::string(&((*expr)[token_pos]),
1837 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1838 if (t_type != GA_RPAR)
1839 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1840 "Xfem_plus argument.");
1847 tree.add_scalar(scalar_type(0), token_pos, expr);
1848 tree.current_node->node_type = GA_NODE_XFEM_MINUS;
1849 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1850 if (t_type != GA_LPAR)
1851 ga_throw_error(expr, pos-1,
1852 "Missing Xfem_minus arguments.");
1853 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1854 if (t_type != GA_NAME)
1855 ga_throw_error(expr, pos,
1856 "The argument of Xfem_minus should be a "
1857 "variable or a test function.");
1858 tree.current_node->name = std::string(&((*expr)[token_pos]),
1860 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1861 if (t_type != GA_RPAR)
1862 ga_throw_error(expr, pos-1,
"Missing a parenthesis after "
1863 "Xfem_minus argument.");
1868 case GA_INTERPOLATE_FILTER:
1870 tree.add_scalar(scalar_type(0), token_pos, expr);
1871 tree.current_node->node_type = GA_NODE_INTERPOLATE_FILTER;
1872 tree.current_node->nbc1 =
size_type(-1);
1873 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1874 if (t_type != GA_LPAR)
1875 ga_throw_error(expr, pos-1,
"Missing interpolate arguments.");
1876 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1877 if (t_type != GA_NAME)
1878 ga_throw_error(expr, pos,
"First argument of Interpolate_filter "
1879 "should be a transformation name.");
1880 tree.current_node->interpolate_name
1881 = std::string(&((*expr)[token_pos]), token_length);
1882 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1883 if (t_type != GA_COMMA)
1884 ga_throw_error(expr, pos,
1885 "Bad format for Interpolate_filter arguments.");
1887 t_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1888 if (t_type != GA_RPAR && t_type != GA_COMMA)
1889 ga_throw_error(expr, pos-1,
1890 "Bad format for Interpolate_filter arguments.");
1891 tree.add_sub_tree(sub_tree);
1892 if (t_type == GA_COMMA) {
1894 t_type = ga_read_term(expr, pos, sub_tree2, macro_dict);
1895 tree.add_sub_tree(sub_tree2);
1897 if (t_type != GA_RPAR)
1898 ga_throw_error(expr, pos-1,
"Unbalanced parenthesis.");
1904 tree.add_op(GA_PRINT, token_pos, expr);
1910 GA_TOKEN_TYPE r_type;
1911 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1912 if (r_type != GA_RPAR)
1913 ga_throw_error(expr, pos-1,
"Unbalanced parenthesis.");
1914 tree.add_sub_tree(sub_tree);
1922 GA_TOKEN_TYPE r_type;
1923 size_type nbc1(0), nbc2(0), nbc3(0), n1(0), n2(0), n3(0);
1925 bool foundcomma(
false), foundsemi(
false);
1927 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1929 tree.add_matrix(token_pos, expr);
1931 if (sub_tree.root->node_type == GA_NODE_C_MATRIX) {
1932 bgeot::multi_index mii;
1936 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1939 if (sub_tree.root->node_type != GA_NODE_C_MATRIX ||
1940 (r_type != GA_COMMA && r_type != GA_RBRACKET))
1941 ga_throw_error(expr, pos-1,
"Bad explicit "
1942 "vector/matrix/tensor format.");
1945 if (sub_tree.root->marked &&
1946 sub_tree.root->tensor().sizes()[0] == 1 &&
1947 sub_tree.root->tensor().size() != 1) {
1948 bgeot::multi_index mi = sub_tree.root->tensor().sizes();
1949 for (
size_type i = mi.size()-1; i > 0; i--)
1952 sub_tree.root->tensor().adjust_sizes(mi);
1955 mii = sub_tree.root->tensor().sizes();
1957 const bgeot::multi_index &mi=sub_tree.root->tensor().sizes();
1959 if (mii.size() == mi.size()) {
1960 for (
size_type i = 0; i < mi.size(); ++i)
1961 if (mi[i] != mii[i]) cmp =
false;
1964 ga_throw_error(expr, pos-1,
"Bad explicit "
1965 "vector/matrix/tensor format.");
1967 for (pga_tree_node &child : sub_tree.root->children) {
1968 child->parent = tree.current_node;
1969 tree.current_node->children.push_back(child);
1971 sub_tree.root->children.resize(0);
1973 }
while (r_type != GA_RBRACKET);
1974 tree.current_node->marked =
false;
1975 mii.push_back(nb_comp);
1976 tree.current_node->tensor().adjust_sizes(mii);
1981 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1985 tree.add_sub_tree(sub_tree);
1988 if (tensor_order < 2) ++nbc1;
1989 if (tensor_order < 3) ++nbc2;
1990 if (tensor_order < 4) ++nbc3;
1992 if (r_type == GA_COMMA) {
1993 if (!foundcomma && tensor_order > 1)
1994 ga_throw_error(expr, pos-1,
"Bad explicit "
1995 "vector/matrix/tensor format.");
1997 }
else if (r_type == GA_SEMICOLON) {
1999 ga_throw_error(expr, pos-1,
"Bad explicit "
2000 "vector/matrix/tensor format.");
2002 tensor_order = std::max(tensor_order,
size_type(2));
2003 }
else if (r_type == GA_DCOMMA) {
2004 if (n1 != nbc1 || n2 != nbc2)
2005 ga_throw_error(expr, pos-1,
"Bad explicit "
2006 "vector/matrix/tensor format.");
2009 tensor_order = std::max(tensor_order,
size_type(3));
2010 }
else if (r_type == GA_DSEMICOLON) {
2011 if (n1 != nbc1 || n2 != nbc2 || n3 != nbc3 ||
2013 ga_throw_error(expr, pos-1,
"Bad explicit "
2014 "vector/matrix/tensor format.");
2016 tensor_order = std::max(tensor_order,
size_type(4));
2017 }
else if (r_type == GA_RBRACKET) {
2018 if (n1 != nbc1 || n2 != nbc2 || n3 != nbc3 ||
2020 ga_throw_error(expr, pos-1,
"Bad explicit "
2021 "vector/matrix/tensor format.");
2022 tree.current_node->nbc1 = nbc1;
2023 if (tensor_order == 4) {
2024 tree.current_node->nbc2 = nbc2/nbc1;
2025 tree.current_node->nbc3 = nbc3/nbc2;
2027 tree.current_node->nbc2 = tree.current_node->nbc3 = 1;
2030 ga_throw_error(expr, pos-1,
"The explicit "
2031 "vector/matrix/tensor components should be "
2032 "separated by ',', ';', ',,' and ';;' and "
2033 "be ended by ']'.");
2036 }
while (r_type != GA_RBRACKET);
2037 bgeot::multi_index mi;
2038 nbc1 = tree.current_node->nbc1;
2039 nbc2 = tree.current_node->nbc2;
2040 nbc3 = tree.current_node->nbc3;
2042 size_type nbl = tree.current_node->children.size()
2043 / (nbc2 * nbc1 * nbc3);
2044 switch(tensor_order) {
2065 default: GMM_ASSERT1(
false,
"Internal error");
2067 tree.current_node->tensor().adjust_sizes(mi);
2068 std::vector<pga_tree_node> children = tree.current_node->children;
2069 auto it = tree.current_node->children.begin();
2073 for (
size_type l = 0; l < nbl; ++l, ++it)
2074 *it = children[i+nbc1*(j+nbc2*(k+nbc3*l))];
2075 tree.current_node->marked =
true;
2078 tree.current_node->nbc1 = tree.current_node->tensor().sizes().size();
2083 ga_throw_error(expr, token_pos,
"Unexpected token.");
2089 case GA_PLUS:
case GA_MINUS:
case GA_MULT:
case GA_DIV:
2090 case GA_COLON:
case GA_DOT:
case GA_DOTMULT:
case GA_DOTDIV:
2092 tree.add_op(t_type, token_pos, expr);
2096 tree.add_op(t_type, token_pos, expr);
2099 case GA_END:
case GA_RPAR:
case GA_COMMA:
case GA_DCOMMA:
2100 case GA_RBRACKET:
case GA_SEMICOLON:
case GA_DSEMICOLON:
2105 GA_TOKEN_TYPE r_type;
2106 tree.add_params(token_pos, expr);
2108 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
2109 if (r_type != GA_RPAR && r_type != GA_COMMA)
2110 ga_throw_error(expr, pos-((r_type != GA_END)?1:0),
2111 "Parameters should be separated "
2112 "by ',' and parameter list ended by ')'.");
2113 tree.add_sub_tree(sub_tree);
2114 }
while (r_type != GA_RPAR);
2120 ga_throw_error(expr, token_pos,
"Unexpected token.");
2130 void ga_read_string_reg(
const std::string &expr, ga_tree &tree,
2131 ga_macro_dictionary ¯o_dict) {
2132 size_type pos = 0, token_pos, token_length;
2134 GA_TOKEN_TYPE t = ga_get_token(expr, pos, token_pos, token_length);
2135 if (t == GA_END)
return;
2137 pstring nexpr(
new std::string(expr));
2139 t = ga_read_term(nexpr, pos, tree, macro_dict);
2140 if (tree.root) ga_expand_macro(tree, tree.root, macro_dict);
2144 ga_throw_error(nexpr, pos-1,
"Unbalanced parenthesis.");
2147 ga_throw_error(nexpr, pos-1,
"Unbalanced bracket.");
2152 ga_throw_error(nexpr, pos-1,
"Unexpected token.");
2159 void ga_read_string(
const std::string &expr, ga_tree &tree,
2160 const ga_macro_dictionary ¯o_dict) {
2161 ga_macro_dictionary macro_dict_loc(
true, macro_dict);
2162 ga_read_string_reg(expr, tree, macro_dict_loc);
2167 std::string ga_substitute(
const std::string &expr,
2168 const std::map<std::string, std::string> &dict) {
2170 size_type pos = 0, token_pos, token_length;
2171 std::stringstream exprs;
2174 GA_TOKEN_TYPE t_type = ga_get_token(expr, pos, token_pos, token_length);
2175 if (t_type == GA_END)
return exprs.str();
2176 std::string name(&(expr[token_pos]), token_length);
2177 if (t_type == GA_NAME && dict.find(name) != dict.end())
2178 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.