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;
95 if (pos >= expr.size())
return type;
96 if (expr[pos] ==
'*') { ++pos; ++token_length;
return GA_DOTMULT; }
97 if (expr[pos] ==
'/') { ++pos; ++token_length;
return GA_DOTDIV; }
98 if (ga_char_type[
unsigned(expr[pos])] != GA_SCALAR)
100 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_filter") == 0)
146 return GA_INTERPOLATE_FILTER;
147 if (expr.compare(token_pos, token_length,
148 "Elementary_transformation") == 0)
149 return GA_ELEMENTARY;
150 if (expr.compare(token_pos, token_length,
"Xfem_plus") == 0)
152 if (expr.compare(token_pos, token_length,
"Xfem_minus") == 0)
153 return GA_XFEM_MINUS;
154 if (expr.compare(token_pos, token_length,
"Print") == 0)
158 if (pos < expr.size() &&
159 ga_char_type[unsigned(expr[pos])] == GA_COMMA) {
160 ++pos;
return GA_DCOMMA;
164 if (pos < expr.size() &&
165 ga_char_type[unsigned(expr[pos])] == GA_SEMICOLON) {
166 ++pos;
return GA_DSEMICOLON;
170 if (pos < expr.size() &&
171 ga_char_type[unsigned(expr[pos])] == GA_COLON_EQ) {
172 ++pos;
return GA_COLON_EQ;
177 default:
return type;
185 void ga_throw_error_msg(pstring expr,
size_type pos,
186 const std::string &msg) {
187 int length_before = 70, length_after = 70;
188 if (expr && expr->size()) {
189 int first = std::max(0,
int(pos)-length_before);
190 int last = std::min(
int(pos)+length_after,
int(expr->size()));
191 if (last - first < length_before+length_after)
192 first = std::max(0,
int(pos)-length_before
193 -(length_before+length_after-last+first));
194 if (last - first < length_before+length_after)
195 last = std::min(
int(pos)+length_after
196 +(length_before+length_after-last+first),
198 if (first > 0) cerr <<
"...";
199 cerr << expr->substr(first, last-first);
200 if (last <
int(expr->size())) cerr <<
"...";
202 if (first > 0) cerr <<
" ";
203 if (
int(pos) > first)
204 cerr << std::setfill (
'-') << std::setw(
int(pos)-first) <<
'-' 205 << std::setfill (
' ');
215 void ga_tree_node::mult_test(
const pga_tree_node n0,
const pga_tree_node n1) {
217 size_type test0 = n0->test_function_type, test1 = n1->test_function_type;
218 if (test0 && test1 && (test0 == test1 ||
219 test0 >= 3 || test1 >= 3))
220 ga_throw_error(expr, pos,
221 "Incompatibility of test functions in product.");
225 test_function_type = test0 + test1;
228 bgeot::multi_index mi(st);
231 case 1: mi[0] = n0->t.sizes()[0];
break;
232 case 2: mi[st-1] = n0->t.sizes()[0];
break;
233 case 3: mi[0] = n0->t.sizes()[0]; mi[1] = n0->t.sizes()[1];
break;
236 case 1: mi[0] = n1->t.sizes()[0];
break;
237 case 2: mi[st-1] = n1->t.sizes()[0];
break;
238 case 3: mi[0] = n1->t.sizes()[0]; mi[1] = n1->t.sizes()[1];
break;
241 if (n0->name_test1.size()) {
242 name_test1 = n0->name_test1; qdim1 = n0->qdim1;
243 interpolate_name_test1 = n0->interpolate_name_test1;
245 name_test1 = n1->name_test1; qdim1 = n1->qdim1;
246 interpolate_name_test1 = n1->interpolate_name_test1;
249 if (n0->name_test2.size()) {
250 name_test2 = n0->name_test2; qdim2 = n0->qdim2;
251 interpolate_name_test2 = n0->interpolate_name_test2;
253 name_test2 = n1->name_test2; qdim2 = n1->qdim2;
254 interpolate_name_test2 = n1->interpolate_name_test2;
259 void ga_tree::add_scalar(scalar_type val,
size_type pos, pstring expr) {
260 while (current_node && current_node->node_type != GA_NODE_OP)
261 current_node = current_node->parent;
263 current_node->adopt_child(
new ga_tree_node(val, pos, expr));
264 current_node = current_node->children.back();
267 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
268 current_node = root =
new ga_tree_node(val, pos, expr);
269 root->parent =
nullptr;
273 void ga_tree::add_allindices(
size_type pos, pstring expr) {
274 while (current_node && current_node->node_type != GA_NODE_OP)
275 current_node = current_node->parent;
277 current_node->adopt_child(
new ga_tree_node(GA_NODE_ALLINDICES, pos,expr));
278 current_node = current_node->children.back();
281 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
282 current_node = root =
new ga_tree_node(GA_NODE_ALLINDICES, pos, expr);
283 root->parent =
nullptr;
289 while (current_node && current_node->node_type != GA_NODE_OP)
290 current_node = current_node->parent;
292 current_node->adopt_child(
new ga_tree_node(name, length, pos, expr));
293 current_node = current_node->children.back();
296 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
297 current_node = root =
new ga_tree_node(name, length, pos, expr);
298 root->parent =
nullptr;
302 void ga_tree::add_sub_tree(ga_tree &sub_tree) {
304 (current_node->node_type == GA_NODE_PARAMS ||
305 current_node->node_type == GA_NODE_INTERPOLATE_FILTER ||
306 current_node->node_type == GA_NODE_C_MATRIX)) {
307 GMM_ASSERT1(sub_tree.root,
"Invalid tree operation");
308 current_node->adopt_child(sub_tree.root);
310 GMM_ASSERT1(sub_tree.root,
"Invalid tree operation");
311 while (current_node && current_node->node_type != GA_NODE_OP)
312 current_node = current_node->parent;
314 current_node->adopt_child(sub_tree.root);
315 current_node = sub_tree.root;
318 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
319 current_node = root = sub_tree.root;
320 root->parent =
nullptr;
323 sub_tree.root = sub_tree.current_node =
nullptr;
326 void ga_tree::add_params(
size_type pos, pstring expr) {
327 GMM_ASSERT1(current_node,
"internal error");
328 while (current_node && current_node->parent &&
329 current_node->parent->node_type == GA_NODE_OP &&
330 ga_operator_priorities[current_node->parent->op_type] >= 4)
331 current_node = current_node->parent;
332 pga_tree_node new_node =
new ga_tree_node(GA_NODE_PARAMS, pos, expr);
333 new_node->parent = current_node->parent;
334 if (current_node->parent)
335 current_node->parent->replace_child(current_node, new_node);
338 new_node->adopt_child(current_node);
339 current_node = new_node;
342 void ga_tree::add_matrix(
size_type pos, pstring expr) {
343 while (current_node && current_node->node_type != GA_NODE_OP)
344 current_node = current_node->parent;
346 current_node->adopt_child(
new ga_tree_node(GA_NODE_C_MATRIX, pos, expr));
347 current_node = current_node->children.back();
350 GMM_ASSERT1(root ==
nullptr,
"Invalid tree operation");
351 current_node = root =
new ga_tree_node(GA_NODE_C_MATRIX, pos, expr);
352 root->parent =
nullptr;
354 current_node->nbc1 = current_node->nbc2 = current_node->nbc3 = 0;
357 void ga_tree::add_op(GA_TOKEN_TYPE op_type,
size_type pos,
359 while (current_node && current_node->parent &&
360 current_node->parent->node_type == GA_NODE_OP &&
361 ga_operator_priorities[current_node->parent->op_type]
362 >= ga_operator_priorities[op_type])
363 current_node = current_node->parent;
364 pga_tree_node new_node =
new ga_tree_node(op_type, pos, expr);
366 if (op_type == GA_UNARY_MINUS
367 || op_type == GA_SYM || op_type == GA_SKEW
368 || op_type == GA_TRACE || op_type == GA_DEVIATOR
369 || op_type == GA_PRINT) {
370 current_node->adopt_child(new_node);
372 new_node->parent = current_node->parent;
373 if (current_node->parent)
374 current_node->parent->replace_child(current_node, new_node);
377 new_node->adopt_child(current_node);
380 if (root) new_node->adopt_child(root);
382 root->parent =
nullptr;
384 current_node = new_node;
387 void ga_tree::clear_node_rec(pga_tree_node pnode) {
389 for (pga_tree_node &child : pnode->children)
390 clear_node_rec(child);
392 current_node =
nullptr;
396 void ga_tree::clear_node(pga_tree_node pnode) {
398 pga_tree_node parent = pnode->parent;
401 for (pga_tree_node &sibling : parent->children)
402 if (sibling != pnode)
403 parent->children[j++] = sibling;
404 parent->children.resize(j);
408 clear_node_rec(pnode);
411 void ga_tree::clear_children(pga_tree_node pnode) {
412 for (pga_tree_node &child : pnode->children)
413 clear_node_rec(child);
414 pnode->children.resize(0);
417 void ga_tree::replace_node_by_child(pga_tree_node pnode,
size_type i) {
418 GMM_ASSERT1(i < pnode->children.size(),
"Internal error");
419 pga_tree_node child = pnode->children[i];
420 child->parent = pnode->parent;
422 pnode->parent->replace_child(pnode, child);
425 current_node =
nullptr;
426 for (pga_tree_node &sibling : pnode->children)
427 if (sibling != child) clear_node_rec(sibling);
431 void ga_tree::copy_node(pga_tree_node pnode, pga_tree_node parent,
432 pga_tree_node &child) {
433 GMM_ASSERT1(child ==
nullptr,
"Internal error");
434 child =
new ga_tree_node();
436 child->parent = parent;
437 for (pga_tree_node &grandchild : child->children)
438 grandchild =
nullptr;
439 for (
size_type j = 0; j < child->children.size(); ++j)
440 copy_node(pnode->children[j], child, child->children[j]);
443 void ga_tree::duplicate_with_operation(pga_tree_node pnode,
444 GA_TOKEN_TYPE op_type) {
445 pga_tree_node newop =
new ga_tree_node(op_type, pnode->pos, pnode->expr);
446 newop->children.resize(2,
nullptr);
447 newop->children[0] = pnode;
448 newop->pos = pnode->pos; newop->expr = pnode->expr;
449 newop->parent = pnode->parent;
451 pnode->parent->replace_child(pnode, newop);
454 pnode->parent = newop;
455 copy_node(pnode, newop, newop->children[1]);
458 void ga_tree::add_child(pga_tree_node pnode, GA_NODE_TYPE node_type) {
459 pga_tree_node newnode=
new ga_tree_node();
460 newnode->pos = pnode->pos; newnode->expr = pnode->expr;
461 newnode->node_type = node_type; pnode->adopt_child(newnode);
464 void ga_tree::insert_node(pga_tree_node pnode, GA_NODE_TYPE node_type) {
465 pga_tree_node newnode =
new ga_tree_node();
466 newnode->node_type = node_type;
467 newnode->parent = pnode->parent;
468 newnode->pos = pnode->pos; newnode->expr = pnode->expr;
470 pnode->parent->replace_child(pnode, newnode);
473 newnode->adopt_child(pnode);
476 bool sub_tree_are_equal
477 (
const pga_tree_node pnode1,
const pga_tree_node pnode2,
478 const ga_workspace &workspace,
int version) {
480 if (ntype1 == GA_NODE_ZERO) ntype1 = GA_NODE_CONSTANT;
482 if (ntype2 == GA_NODE_ZERO) ntype2 = GA_NODE_CONSTANT;
484 if (ntype1 != ntype2)
return false;
485 if (pnode1->children.size() != pnode2->children.size())
return false;
489 if (pnode1->op_type != pnode2->op_type)
return false;
490 if (pnode1->symmetric_op != pnode2->symmetric_op)
return false;
492 case GA_NODE_OPERATOR:
493 if (pnode1->der1 != pnode2->der1 || pnode1->der2 != pnode2->der2)
495 case GA_NODE_PREDEF_FUNC:
case GA_NODE_SPEC_FUNC:
496 if (pnode1->name.compare(pnode2->name))
return false;
498 case GA_NODE_CONSTANT:
case GA_NODE_ZERO:
499 if (pnode1->tensor().size() != pnode2->tensor().size())
return false;
503 if (pnode1->test_function_type != pnode2->test_function_type)
505 if ((pnode1->test_function_type & 1) &&
506 pnode1->name_test1.compare(pnode2->name_test1) != 0)
508 if ((pnode1->test_function_type & 2) &&
509 pnode1->name_test2.compare(pnode2->name_test2) != 0)
513 if ((pnode1->test_function_type == 1 &&
514 pnode2->test_function_type == 1) ||
515 (pnode1->test_function_type == 2 &&
516 pnode2->test_function_type == 2))
518 if ((pnode1->test_function_type & 1) &&
519 pnode1->name_test1.compare(pnode2->name_test2) != 0)
521 if ((pnode1->test_function_type & 2) &&
522 pnode1->name_test2.compare(pnode2->name_test1) != 0)
526 if (pnode1->tensor().size() != 1 &&
527 pnode1->t.sizes().size() != pnode2->t.sizes().size())
return false;
528 for (
size_type i = 0; i < pnode1->t.sizes().size(); ++i)
529 if (pnode1->t.sizes()[i] != pnode2->t.sizes()[i])
return false;
530 for (
size_type i = 0; i < pnode1->tensor().size(); ++i)
531 if (gmm::abs(pnode1->tensor()[i] - pnode2->tensor()[i]) > 1E-25)
534 case GA_NODE_C_MATRIX:
535 if (pnode1->t.sizes().size() != pnode2->t.sizes().size())
return false;
536 for (
size_type i = 0; i < pnode1->t.sizes().size(); ++i)
537 if (pnode1->t.sizes()[i] != pnode2->t.sizes()[i])
return false;
538 if (pnode1->nbc1 != pnode2->nbc1)
return false;
540 case GA_NODE_INTERPOLATE_FILTER:
541 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
542 pnode1->nbc1 != pnode2->nbc1)
545 case GA_NODE_INTERPOLATE_X:
case GA_NODE_INTERPOLATE_NORMAL:
546 if (pnode1->interpolate_name.compare(pnode2->interpolate_name))
549 case GA_NODE_INTERPOLATE_DERIVATIVE:
550 if (pnode1->interpolate_name_der.compare(pnode2->interpolate_name_der))
553 case GA_NODE_INTERPOLATE_VAL_TEST:
case GA_NODE_INTERPOLATE_GRAD_TEST:
554 case GA_NODE_INTERPOLATE_HESS_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
555 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
556 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
557 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
558 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
559 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
560 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
561 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
562 pnode1->elementary_name.compare(pnode2->elementary_name))
565 case GA_NODE_VAL_TEST:
case GA_NODE_GRAD_TEST:
566 case GA_NODE_HESS_TEST:
case GA_NODE_DIVERG_TEST:
568 const mesh_fem *mf1 = workspace.associated_mf(pnode1->name);
569 const mesh_fem *mf2 = workspace.associated_mf(pnode2->name);
572 if (pnode1->name.compare(pnode2->name) ||
573 pnode1->test_function_type != pnode2->test_function_type)
578 workspace.qdim(pnode1->name) != workspace.qdim(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)
591 case GA_NODE_VAL:
case GA_NODE_GRAD:
592 case GA_NODE_HESS:
case GA_NODE_DIVERG:
593 if (pnode1->name.compare(pnode2->name))
return false;
595 case GA_NODE_INTERPOLATE_VAL:
case GA_NODE_INTERPOLATE_GRAD:
596 case GA_NODE_INTERPOLATE_HESS:
case GA_NODE_INTERPOLATE_DIVERG:
597 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
598 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
599 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
600 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
601 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
602 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
603 if (pnode1->interpolate_name.compare(pnode2->interpolate_name) ||
604 pnode1->elementary_name.compare(pnode2->elementary_name) ||
605 pnode1->name.compare(pnode2->name))
609 if (pnode1->nbc1 != pnode2->nbc1)
return false;
615 if (version && ntype1 == GA_NODE_OP && pnode1->symmetric_op) {
616 if (sub_tree_are_equal(pnode1->children[0], pnode2->children[0],
617 workspace, version) &&
618 sub_tree_are_equal(pnode1->children[1], pnode2->children[1],
621 if (sub_tree_are_equal(pnode1->children[1], pnode2->children[0],
622 workspace, version) &&
623 sub_tree_are_equal(pnode1->children[0], pnode2->children[1],
624 workspace, version) )
628 for (
size_type i = 0; i < pnode1->children.size(); ++i)
629 if (!(sub_tree_are_equal(pnode1->children[i], pnode2->children[i],
630 workspace, version)))
636 static void verify_tree(
const pga_tree_node pnode,
637 const pga_tree_node parent) {
638 GMM_ASSERT1(pnode->parent == parent,
639 "Invalid tree node " << pnode->node_type);
640 for (pga_tree_node &child : pnode->children)
641 verify_tree(child, pnode);
645 static void ga_print_constant_tensor(
const pga_tree_node pnode,
647 size_type nt = pnode->nb_test_functions();
648 switch (pnode->tensor_order()) {
650 str << (nt ? scalar_type(0) : pnode->tensor()[0]);
655 for (
size_type i = 0; i < pnode->tensor_proper_size(0); ++i) {
656 if (i != 0) str <<
",";
657 str << (nt ? scalar_type(0) : pnode->tensor()[i]);
662 case 2:
case 3:
case 4:
665 size_type n0 = pnode->tensor_proper_size(0);
666 size_type n1 = pnode->tensor_proper_size(1);
667 size_type n2 = ((pnode->tensor_order() > 2) ?
668 pnode->tensor_proper_size(2) : 1);
669 size_type n3 = ((pnode->tensor_order() > 3) ?
670 pnode->tensor_proper_size(3) : 1);
671 if (n3 > 1) str <<
"[";
673 if (l != 0) str <<
",";
674 if (n2 > 1) str <<
"[";
676 if (k != 0) str <<
",";
677 if (n1 > 1) str <<
"[";
679 if (j != 0) str <<
",";
680 if (n0 > 1) str <<
"[";
682 if (i != 0) str <<
",";
683 str << (nt ? scalar_type(0) : pnode->tensor()[ii++]);
685 if (n0 > 1) str <<
"]";
687 if (n1 > 1) str <<
"]";
689 if (n2 > 1) str <<
"]";
691 if (n3 > 1) str <<
"]";
695 case 5:
case 6:
case 7:
case 8:
697 for (
size_type i = 0; i < pnode->tensor_proper_size(); ++i) {
698 if (i != 0) str <<
";";
699 str << (nt ? scalar_type(0) : pnode->tensor()[i]);
702 for (
size_type i = 0; i < pnode->tensor_order(); ++i) {
703 if (i != 0) str <<
", ";
704 str << pnode->tensor_proper_size(i);
709 default: GMM_ASSERT1(
false,
"Invalid tensor dimension");
711 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
714 void ga_print_node(
const pga_tree_node pnode,
717 long prec = str.precision(16);
719 bool is_interpolate(
false), is_elementary(
false);
720 bool is_xfem_plus(
false), is_xfem_minus(
false);
721 switch(pnode->node_type) {
722 case GA_NODE_INTERPOLATE:
723 case GA_NODE_INTERPOLATE_FILTER:
724 case GA_NODE_INTERPOLATE_X:
725 case GA_NODE_INTERPOLATE_NORMAL:
726 case GA_NODE_INTERPOLATE_VAL:
727 case GA_NODE_INTERPOLATE_GRAD:
728 case GA_NODE_INTERPOLATE_HESS:
729 case GA_NODE_INTERPOLATE_DIVERG:
730 case GA_NODE_INTERPOLATE_VAL_TEST:
731 case GA_NODE_INTERPOLATE_GRAD_TEST:
732 case GA_NODE_INTERPOLATE_HESS_TEST:
733 case GA_NODE_INTERPOLATE_DIVERG_TEST:
734 str <<
"Interpolate(";
735 is_interpolate =
true;
737 case GA_NODE_ELEMENTARY:
738 case GA_NODE_ELEMENTARY_VAL:
739 case GA_NODE_ELEMENTARY_GRAD:
740 case GA_NODE_ELEMENTARY_HESS:
741 case GA_NODE_ELEMENTARY_DIVERG:
742 case GA_NODE_ELEMENTARY_VAL_TEST:
743 case GA_NODE_ELEMENTARY_GRAD_TEST:
744 case GA_NODE_ELEMENTARY_HESS_TEST:
745 case GA_NODE_ELEMENTARY_DIVERG_TEST:
746 is_elementary =
true;
747 str <<
"Elementary_transformation(";
749 case GA_NODE_XFEM_PLUS:
750 case GA_NODE_XFEM_PLUS_VAL:
751 case GA_NODE_XFEM_PLUS_GRAD:
752 case GA_NODE_XFEM_PLUS_HESS:
753 case GA_NODE_XFEM_PLUS_DIVERG:
754 case GA_NODE_XFEM_PLUS_VAL_TEST:
755 case GA_NODE_XFEM_PLUS_GRAD_TEST:
756 case GA_NODE_XFEM_PLUS_HESS_TEST:
757 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
761 case GA_NODE_XFEM_MINUS:
762 case GA_NODE_XFEM_MINUS_VAL:
763 case GA_NODE_XFEM_MINUS_GRAD:
764 case GA_NODE_XFEM_MINUS_HESS:
765 case GA_NODE_XFEM_MINUS_DIVERG:
766 case GA_NODE_XFEM_MINUS_VAL_TEST:
767 case GA_NODE_XFEM_MINUS_GRAD_TEST:
768 case GA_NODE_XFEM_MINUS_HESS_TEST:
769 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
770 is_xfem_minus =
true;
771 str <<
"Xfem_minus(";
777 switch(pnode->node_type) {
779 case GA_NODE_INTERPOLATE_GRAD:
780 case GA_NODE_ELEMENTARY_GRAD:
781 case GA_NODE_XFEM_PLUS_GRAD:
782 case GA_NODE_XFEM_MINUS_GRAD:
783 case GA_NODE_GRAD_TEST:
784 case GA_NODE_INTERPOLATE_GRAD_TEST:
785 case GA_NODE_ELEMENTARY_GRAD_TEST:
786 case GA_NODE_XFEM_PLUS_GRAD_TEST:
787 case GA_NODE_XFEM_MINUS_GRAD_TEST:
791 case GA_NODE_INTERPOLATE_HESS:
792 case GA_NODE_ELEMENTARY_HESS:
793 case GA_NODE_XFEM_PLUS_HESS:
794 case GA_NODE_XFEM_MINUS_HESS:
795 case GA_NODE_HESS_TEST:
796 case GA_NODE_INTERPOLATE_HESS_TEST:
797 case GA_NODE_ELEMENTARY_HESS_TEST:
798 case GA_NODE_XFEM_PLUS_HESS_TEST:
799 case GA_NODE_XFEM_MINUS_HESS_TEST:
803 case GA_NODE_INTERPOLATE_DIVERG:
804 case GA_NODE_ELEMENTARY_DIVERG:
805 case GA_NODE_XFEM_PLUS_DIVERG:
806 case GA_NODE_XFEM_MINUS_DIVERG:
807 case GA_NODE_DIVERG_TEST:
808 case GA_NODE_INTERPOLATE_DIVERG_TEST:
809 case GA_NODE_ELEMENTARY_DIVERG_TEST:
810 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
811 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
818 switch(pnode->node_type) {
823 if (pnode->parent->node_type == GA_NODE_OP &&
824 (ga_operator_priorities[pnode->op_type] >= 2 ||
825 ga_operator_priorities[pnode->op_type]
826 < ga_operator_priorities[pnode->parent->op_type]))
828 if (pnode->parent->node_type == GA_NODE_PARAMS) par =
true;
833 if (pnode->op_type == GA_UNARY_MINUS) {
834 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
835 str <<
"-"; ga_print_node(pnode->children[0], str);
836 }
else if (pnode->op_type == GA_QUOTE) {
837 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
838 ga_print_node(pnode->children[0], str); str <<
"'";
839 }
else if (pnode->op_type == GA_SYM) {
840 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
841 str <<
"Sym("; ga_print_node(pnode->children[0], str); str <<
")";
842 }
else if (pnode->op_type == GA_SKEW) {
843 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
844 str <<
"Skew("; ga_print_node(pnode->children[0], str); str <<
")";
845 }
else if (pnode->op_type == GA_TRACE) {
846 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
847 str <<
"Trace("; ga_print_node(pnode->children[0], str); str <<
")";
848 }
else if (pnode->op_type == GA_DEVIATOR) {
849 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree with " 850 << pnode->children.size() <<
" children instead of 1");
851 str <<
"Deviator("; ga_print_node(pnode->children[0], str); str<<
")";
852 }
else if (pnode->op_type == GA_PRINT) {
853 GMM_ASSERT1(pnode->children.size() == 1,
"Invalid tree");
854 str <<
"Print("; ga_print_node(pnode->children[0], str); str <<
")";
856 if (!par && pnode->op_type == GA_MULT &&
857 (pnode->children.size() == 1 ||
858 pnode->test_function_type ==
size_type(-1) ||
859 (pnode->children[0]->tensor_order() == 4 &&
860 pnode->children[1]->tensor_order() == 2)))
861 { par =
true; str <<
"("; }
862 ga_print_node(pnode->children[0], str);
863 switch (pnode->op_type) {
864 case GA_PLUS: str <<
"+";
break;
865 case GA_MINUS: str <<
"-";
break;
866 case GA_MULT: str <<
"*";
break;
867 case GA_DIV: str <<
"/";
break;
868 case GA_COLON: str <<
":";
break;
869 case GA_DOT: str <<
".";
break;
870 case GA_DOTMULT: str <<
".*";
break;
871 case GA_DOTDIV: str <<
"./";
break;
872 case GA_TMULT: str <<
"@";
break;
873 default: GMM_ASSERT1(
false,
"Invalid or not taken into account " 876 if (pnode->children.size() >= 2)
877 ga_print_node(pnode->children[1], str);
879 str <<
"(unknown second argument)";
886 if (pnode->nbc1) str <<
"X(" << pnode->nbc1 <<
")";
else str <<
"X";
888 case GA_NODE_ELT_SIZE: str <<
"element_size";
break;
889 case GA_NODE_ELT_K: str <<
"element_K";
break;
890 case GA_NODE_ELT_B: str <<
"element_B";
break;
891 case GA_NODE_NORMAL: str <<
"Normal";
break;
892 case GA_NODE_INTERPOLATE_FILTER:
893 str <<
"Interpolate_filter(" << pnode->interpolate_name <<
",";
894 ga_print_node(pnode->children[0], str);
895 if (pnode->children.size() == 2)
896 { str <<
","; ga_print_node(pnode->children[1], str); }
897 else if (pnode->nbc1 !=
size_type(-1)) str <<
"," << pnode->nbc1;
900 case GA_NODE_INTERPOLATE_X:
903 case GA_NODE_INTERPOLATE_NORMAL:
906 case GA_NODE_INTERPOLATE_DERIVATIVE:
907 str << (pnode->test_function_type == 1 ?
"Test_" :
"Test2_")
908 <<
"Interpolate_derivative(" << pnode->interpolate_name_der <<
"," 909 << pnode->interpolate_name <<
"," << pnode->name <<
")";
911 case GA_NODE_INTERPOLATE:
912 case GA_NODE_ELEMENTARY:
913 case GA_NODE_XFEM_PLUS:
914 case GA_NODE_XFEM_MINUS:
916 case GA_NODE_INTERPOLATE_VAL:
917 case GA_NODE_ELEMENTARY_VAL:
918 case GA_NODE_XFEM_PLUS_VAL:
919 case GA_NODE_XFEM_MINUS_VAL:
921 case GA_NODE_INTERPOLATE_GRAD:
922 case GA_NODE_ELEMENTARY_GRAD:
923 case GA_NODE_XFEM_PLUS_GRAD:
924 case GA_NODE_XFEM_MINUS_GRAD:
926 case GA_NODE_INTERPOLATE_HESS:
927 case GA_NODE_ELEMENTARY_HESS:
928 case GA_NODE_XFEM_PLUS_HESS:
929 case GA_NODE_XFEM_MINUS_HESS:
931 case GA_NODE_INTERPOLATE_DIVERG:
932 case GA_NODE_ELEMENTARY_DIVERG:
933 case GA_NODE_XFEM_PLUS_DIVERG:
934 case GA_NODE_XFEM_MINUS_DIVERG:
937 case GA_NODE_VAL_TEST:
938 case GA_NODE_INTERPOLATE_VAL_TEST:
939 case GA_NODE_ELEMENTARY_VAL_TEST:
940 case GA_NODE_XFEM_PLUS_VAL_TEST:
941 case GA_NODE_XFEM_MINUS_VAL_TEST:
942 case GA_NODE_GRAD_TEST:
943 case GA_NODE_INTERPOLATE_GRAD_TEST:
944 case GA_NODE_ELEMENTARY_GRAD_TEST:
945 case GA_NODE_XFEM_PLUS_GRAD_TEST:
946 case GA_NODE_XFEM_MINUS_GRAD_TEST:
947 case GA_NODE_HESS_TEST:
948 case GA_NODE_INTERPOLATE_HESS_TEST:
949 case GA_NODE_ELEMENTARY_HESS_TEST:
950 case GA_NODE_XFEM_PLUS_HESS_TEST:
951 case GA_NODE_XFEM_MINUS_HESS_TEST:
952 case GA_NODE_DIVERG_TEST:
953 case GA_NODE_INTERPOLATE_DIVERG_TEST:
954 case GA_NODE_ELEMENTARY_DIVERG_TEST:
955 case GA_NODE_XFEM_PLUS_DIVERG_TEST:
956 case GA_NODE_XFEM_MINUS_DIVERG_TEST:
957 str << (pnode->test_function_type == 1 ?
"Test_" :
"Test2_")
960 case GA_NODE_SPEC_FUNC: str << pnode->name;
break;
961 case GA_NODE_OPERATOR:
962 case GA_NODE_PREDEF_FUNC:
964 str <<
"Derivative_" << pnode->der1 <<
"_";
965 if (pnode->der2) str << pnode->der2 <<
"_";
967 str << pnode->name;
break;
969 GMM_ASSERT1(pnode->test_function_type !=
size_type(-1),
971 if (pnode->test_function_type) str <<
"(";
972 ga_print_constant_tensor(pnode, str);
973 if (pnode->name_test1.size()) {
974 GMM_ASSERT1(pnode->qdim1 > 0,
"Internal error");
975 if (pnode->qdim1 == 1)
976 str <<
"*Test_" << pnode->name_test1;
978 str <<
"*(Reshape(Test_" << pnode->name_test1 <<
"," 979 << pnode->qdim1<<
")(1))";
982 if (pnode->name_test2.size()) {
983 GMM_ASSERT1(pnode->qdim2 > 0,
"Internal error");
984 if (pnode->qdim2 == 1)
985 str <<
"*Test2_" << pnode->name_test2;
987 str <<
"*(Reshape(Test2_" << pnode->name_test2 <<
"," 988 << pnode->qdim2<<
")(1))";
991 if (pnode->test_function_type) str <<
")";
994 case GA_NODE_CONSTANT:
995 ga_print_constant_tensor(pnode, str);
998 case GA_NODE_ALLINDICES:
1000 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1003 case GA_NODE_PARAMS:
1004 GMM_ASSERT1(pnode->children.size(),
"Invalid tree");
1005 ga_print_node(pnode->children[0], str);
1007 for (
size_type i = 1; i < pnode->children.size(); ++i) {
1008 if (i > 1) str <<
", ";
1009 ga_print_node(pnode->children[i], str);
1016 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1019 case GA_NODE_MACRO_PARAM:
1020 if (pnode->nbc2 == 1) str <<
"Grad_";
1021 if (pnode->nbc2 == 2) str <<
"Hess_";
1022 if (pnode->nbc2 == 3) str <<
"Div_";
1023 if (pnode->nbc3 == 1) str <<
"Test_";
1024 if (pnode->nbc3 == 2) str <<
"Test2_";
1025 str <<
"P" << pnode->nbc1;
1026 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1029 case GA_NODE_RESHAPE:
1031 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1034 case GA_NODE_SWAP_IND:
1035 str <<
"Swap_indices";
1036 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1039 case GA_NODE_IND_MOVE_LAST:
1040 str <<
"Index_move_last";
1041 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1044 case GA_NODE_CONTRACT:
1046 GMM_ASSERT1(pnode->children.size() == 0,
"Invalid tree");
1049 case GA_NODE_C_MATRIX:
1050 GMM_ASSERT1(pnode->children.size(),
"Invalid tree");
1051 GMM_ASSERT1(pnode->nbc1 == pnode->tensor_order(),
"Invalid C_MATRIX");
1052 switch (pnode->tensor_order()) {
1054 ga_print_node(pnode->children[0], str);
1059 for (
size_type i = 0; i < pnode->tensor_proper_size(0); ++i) {
1060 if (i != 0) str <<
",";
1061 ga_print_node(pnode->children[i], str);
1066 case 2:
case 3:
case 4:
1069 size_type n0 = pnode->tensor_proper_size(0);
1070 size_type n1 = pnode->tensor_proper_size(1);
1071 size_type n2 = ((pnode->tensor_order() > 2) ?
1072 pnode->tensor_proper_size(2) : 1);
1073 size_type n3 = ((pnode->tensor_order() > 3) ?
1074 pnode->tensor_proper_size(3) : 1);
1075 if (n3 > 1) str <<
"[";
1077 if (l != 0) str <<
",";
1078 if (n2 > 1) str <<
"[";
1080 if (k != 0) str <<
",";
1081 if (n1 > 1) str <<
"[";
1083 if (j != 0) str <<
",";
1084 if (n0 > 1) str <<
"[";
1086 if (i != 0) str <<
",";
1087 ga_print_node(pnode->children[ii++], str);
1089 if (n0 > 1) str <<
"]";
1091 if (n1 > 1) str <<
"]";
1093 if (n2 > 1) str <<
"]";
1095 if (n3 > 1) str <<
"]";
1099 case 5:
case 6:
case 7:
case 8:
1101 for (
size_type i = 0; i < pnode->tensor_proper_size(); ++i) {
1102 if (i != 0) str <<
";";
1103 ga_print_node(pnode->children[i], str);
1106 for (
size_type i = 0; i < pnode->tensor_order(); ++i) {
1107 if (i != 0) str <<
", ";
1108 str << pnode->tensor_proper_size(i);
1113 default: GMM_ASSERT1(
false,
"Invalid tensor dimension");
1118 str <<
"Invalid or not taken into account node type " 1119 << pnode->node_type;
1124 str <<
"," << pnode->interpolate_name <<
")";
1125 else if (is_elementary)
1126 str <<
"," << pnode->elementary_name <<
")";
1127 else if (is_xfem_plus || is_xfem_minus)
1130 str.precision(prec);
1133 std::string ga_tree_to_string(
const ga_tree &tree) {
1134 std::stringstream str;
1136 if (tree.root) verify_tree(tree.root, 0);
1137 if (tree.root) ga_print_node(tree.root, str);
else str <<
"0";
1141 size_type ga_parse_prefix_operator(std::string &name) {
1142 if (name.size() >= 5 && name.compare(0, 5,
"Grad_") == 0)
1143 { name = name.substr(5);
return 1; }
1144 else if (name.size() >= 5 && name.compare(0, 5,
"Hess_") == 0)
1145 { name = name.substr(5);
return 2; }
1146 else if (name.size() >= 4 && name.compare(0, 4,
"Div_") == 0)
1147 { name = name.substr(4);
return 3; }
1151 size_type ga_parse_prefix_test(std::string &name) {
1152 if (name.size() >= 5 && name.compare(0, 5,
"Test_") == 0)
1153 { name = name.substr(5);
return 1; }
1154 else if (name.size() >= 6 && name.compare(0, 6,
"Test2_") == 0)
1155 { name = name.substr(6);
return 2; }
1163 int ga_check_name_validity(
const std::string &name) {
1165 if (name.compare(0, 11,
"Derivative_") == 0)
1168 const ga_predef_function_tab &PREDEF_FUNCTIONS
1170 const ga_predef_operator_tab &PREDEF_OPERATORS
1172 const ga_spec_function_tab &SPEC_FUNCTIONS
1174 const ga_spec_op_tab &SPEC_OP
1177 if (SPEC_OP.find(name) != SPEC_OP.end())
1180 if (PREDEF_FUNCTIONS.find(name) != PREDEF_FUNCTIONS.end())
1183 if (SPEC_FUNCTIONS.find(name) != SPEC_FUNCTIONS.end())
1186 if (PREDEF_OPERATORS.tab.find(name) != PREDEF_OPERATORS.tab.end())
1189 if (name.size() >= 5 && name.compare(0, 5,
"Grad_") == 0)
1192 if (name.size() >= 5 && name.compare(0, 5,
"Hess_") == 0)
1195 if (name.size() >= 4 && name.compare(0, 4,
"Div_") == 0)
1198 if (name.size() >= 6 && name.compare(0, 6,
"Test2_") == 0)
1201 if (name.size() >= 5 && name.compare(0, 5,
"Test_") == 0)
1224 ga_macro::ga_macro() : ptree(new ga_tree), nbp(0) {}
1225 ga_macro::~ga_macro() {
delete ptree; }
1226 ga_macro::ga_macro(
const std::string &name,
const ga_tree &t,
size_type nbp_)
1227 : ptree(new ga_tree(t)), macro_name_(name), nbp(nbp_) {}
1228 ga_macro::ga_macro(
const ga_macro &gam)
1229 : ptree(new ga_tree(gam.tree())), macro_name_(gam.name()),
1230 nbp(gam.nb_params()) {}
1231 ga_macro &ga_macro::operator =(
const ga_macro &gam) {
1232 delete ptree; ptree =
new ga_tree(gam.tree());
1233 macro_name_ = gam.name();
1234 nbp = gam.nb_params();
1238 static void ga_replace_macro_params
1239 (ga_tree &tree, pga_tree_node pnode,
1240 const std::vector<pga_tree_node> &children) {
1242 for (
size_type i = 0; i < pnode->children.size(); ++i)
1243 ga_replace_macro_params(tree, pnode->children[i], children);
1245 if (pnode->node_type == GA_NODE_MACRO_PARAM) {
1248 GMM_ASSERT1(pnode->nbc1+1 < children.size(),
"Internal error");
1249 pga_tree_node pchild = children[pnode->nbc1+1];
1252 if (!(pchild->children.empty()) || pchild->node_type != GA_NODE_NAME)
1253 ga_throw_error(pchild->expr, pchild->pos,
"Error in macro " 1254 "expansion. Only variable name are allowed for macro " 1255 "parameter preceded by Grad_ Hess_ Test_ or Test2_ " 1257 switch(pnode->op_type) {
1258 case GA_NAME : pnode->node_type = GA_NODE_NAME;
break;
1259 case GA_INTERPOLATE : pnode->node_type = GA_NODE_INTERPOLATE;
break;
1260 case GA_ELEMENTARY : pnode->node_type = GA_NODE_ELEMENTARY;
break;
1261 case GA_XFEM_PLUS : pnode->node_type = GA_NODE_XFEM_PLUS;
break;
1262 case GA_XFEM_MINUS: pnode->node_type = GA_NODE_XFEM_MINUS;
break;
1265 pnode->name = pchild->name;
1266 if (pt == 1) pnode->name =
"Test_" + pnode->name;
1267 if (pt == 2) pnode->name =
"Test2_" + pnode->name;
1268 if (po == 1) pnode->name =
"Grad_" + pnode->name;
1269 if (po == 2) pnode->name =
"Hess_" + pnode->name;
1270 if (po == 3) pnode->name =
"Div_" + pnode->name;
1272 pga_tree_node pnode_old = pnode;
1274 tree.copy_node(pchild, pnode_old->parent, pnode);
1275 if (pnode_old->parent)
1276 pnode_old->parent->replace_child(pnode_old, pnode);
1279 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1285 static void ga_expand_macro(ga_tree &tree, pga_tree_node pnode,
1286 const ga_macro_dictionnary ¯o_dict) {
1289 if (pnode->node_type == GA_NODE_PARAMS) {
1291 for (
size_type i = 1; i < pnode->children.size(); ++i)
1292 ga_expand_macro(tree, pnode->children[i], macro_dict);
1294 if (pnode->children[0]->node_type != GA_NODE_NAME) {
1295 ga_expand_macro(tree, pnode->children[0], macro_dict);
1298 if (macro_dict.macro_exists(pnode->children[0]->name)) {
1300 const ga_macro &gam = macro_dict.get_macro(pnode->children[0]->name);
1302 if (gam.nb_params()==0) {
1303 pga_tree_node pnode_old = pnode->children[0];
1304 pnode->children[0] =
nullptr;
1305 tree.copy_node(gam.tree().root,
1306 pnode_old->parent,pnode->children[0]);
1307 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1312 if (gam.nb_params()+1 != pnode->children.size())
1313 ga_throw_error(pnode->expr, pnode->pos,
1314 "Bad number of parameters in the use of macro '" 1315 << gam.name() <<
"'. Expected " << gam.nb_params()
1316 <<
" found " << pnode->children.size()-1 <<
".");
1318 pga_tree_node pnode_old = pnode;
1320 tree.copy_node(gam.tree().root, pnode_old->parent, pnode);
1321 if (pnode_old->parent)
1322 pnode_old->parent->replace_child(pnode_old, pnode);
1325 ga_replace_macro_params(tree, pnode, pnode_old->children);
1330 }
else if (pnode->node_type == GA_NODE_NAME &&
1331 macro_dict.macro_exists(pnode->name)) {
1333 const ga_macro &gam = macro_dict.get_macro(pnode->name);
1334 if (gam.nb_params() != 0)
1335 ga_throw_error(pnode->expr, pnode->pos,
1336 "Bad number of parameters in the use of macro '" 1337 << gam.name() <<
"'. Expected " << gam.nb_params()
1340 pga_tree_node pnode_old = pnode;
1342 tree.copy_node(gam.tree().root, pnode_old->parent, pnode);
1343 if (pnode_old->parent)
1344 pnode_old->parent->replace_child(pnode_old, pnode);
1347 GMM_ASSERT1(pnode_old->children.empty(),
"Internal error");
1350 for (
size_type i = 0; i < pnode->children.size(); ++i)
1351 ga_expand_macro(tree, pnode->children[i], macro_dict);
1355 static void ga_mark_macro_params_rec(
const pga_tree_node pnode,
1356 const std::vector<std::string> ¶ms) {
1358 for (
size_type i = 0; i < pnode->children.size(); ++i)
1359 ga_mark_macro_params_rec(pnode->children[i], params);
1361 if (pnode->node_type == GA_NODE_NAME ||
1362 pnode->node_type == GA_NODE_INTERPOLATE ||
1363 pnode->node_type == GA_NODE_ELEMENTARY ||
1364 pnode->node_type == GA_NODE_XFEM_PLUS ||
1365 pnode->node_type == GA_NODE_XFEM_MINUS) {
1366 std::string name = pnode->name;
1367 size_type po = ga_parse_prefix_operator(name);
1368 size_type pt = ga_parse_prefix_test(name);
1370 for (
size_type i = 0; i < params.size(); ++i)
1371 if (name.compare(params[i]) == 0) {
1373 switch(pnode->node_type) {
1374 case GA_NODE_NAME : pnode->op_type = GA_NAME;
break;
1375 case GA_NODE_INTERPOLATE : pnode->op_type = GA_INTERPOLATE;
break;
1376 case GA_NODE_ELEMENTARY : pnode->op_type = GA_ELEMENTARY;
break;
1377 case GA_NODE_XFEM_PLUS : pnode->op_type = GA_XFEM_PLUS;
break;
1378 case GA_NODE_XFEM_MINUS: pnode->op_type = GA_XFEM_MINUS;
break;
1381 pnode->node_type = GA_NODE_MACRO_PARAM;
1382 pnode->nbc1 = i; pnode->nbc2 = po; pnode->nbc3 = pt;
1387 static void ga_mark_macro_params(ga_macro &gam,
1388 const std::vector<std::string> ¶ms,
1389 const ga_macro_dictionnary ¯o_dict) {
1390 if (gam.tree().root) {
1391 ga_mark_macro_params_rec(gam.tree().root, params);
1392 ga_expand_macro(gam.tree(), gam.tree().root, macro_dict);
1396 bool ga_macro_dictionnary::macro_exists(
const std::string &name)
const {
1397 if (macros.find(name) != macros.end())
return true;
1398 if (parent && parent->macro_exists(name))
return true;
1404 ga_macro_dictionnary::get_macro(
const std::string &name)
const {
1405 auto it = macros.find(name);
1406 if (it != macros.end())
return it->second;
1407 if (parent)
return parent->get_macro(name);
1408 GMM_ASSERT1(
false,
"Undefined macro");
1411 void ga_macro_dictionnary::add_macro(
const ga_macro &gam)
1412 { macros[gam.name()] = gam; }
1414 void ga_macro_dictionnary::add_macro(
const std::string &name,
1415 const std::string &expr)
1416 { ga_tree tree; ga_read_string_reg(
"Def "+name+
":="+expr, tree, *
this); }
1418 void ga_macro_dictionnary::del_macro(
const std::string &name) {
1419 auto it = macros.find(name);
1420 GMM_ASSERT1(it != macros.end(),
"Undefined macro (at this level)");
1430 static GA_TOKEN_TYPE ga_read_term(pstring expr,
size_type &pos,
1432 ga_macro_dictionnary ¯o_dict) {
1434 GA_TOKEN_TYPE t_type;
1439 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1447 char *endptr;
const char *nptr = &((*expr)[token_pos]);
1448 scalar_type s_read = ::strtod(nptr, &endptr);
1450 ga_throw_error(expr, token_pos,
"Bad numeric format.");
1451 tree.add_scalar(s_read, token_pos, expr);
1456 tree.add_allindices(token_pos, expr);
1460 tree.add_name(&((*expr)[token_pos]), token_length, token_pos, expr);
1464 tree.add_op(GA_UNARY_MINUS, token_pos, expr);
1469 tree.add_op(GA_SYM, token_pos, expr);
1473 tree.add_op(GA_SKEW, token_pos, expr);
1477 tree.add_op(GA_TRACE, token_pos, expr);
1481 tree.add_op(GA_DEVIATOR, token_pos, expr);
1487 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1488 if (t_type != GA_NAME)
1489 ga_throw_error(expr, pos,
1490 "Macro definition should begin with macro name");
1491 gam.name() = std::string(&((*expr)[token_pos]), token_length);
1492 if (ga_check_name_validity(gam.name()))
1493 ga_throw_error(expr, pos-1,
"Invalid macro name.")
1494 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1495 std::vector<
std::
string> params;
1496 if (t_type == GA_LPAR) {
1497 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1498 while (t_type == GA_NAME) {
1499 params.push_back(std::string(&((*expr)[token_pos]),
1501 if (ga_check_name_validity(params.back()))
1502 ga_throw_error(expr, pos-1,
"Invalid macro parameter name.");
1503 for (
size_type i = 0; i+1 < params.size(); ++i)
1504 if (params.back().compare(params[i]) == 0)
1505 ga_throw_error(expr, pos-1,
1506 "Invalid repeated macro parameter name.");
1507 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1508 if (t_type == GA_COMMA)
1509 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1511 if (t_type != GA_RPAR)
1512 ga_throw_error(expr, pos-1,
1513 "Missing right parenthesis in macro definition.");
1514 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1516 if (t_type != GA_COLON_EQ)
1517 ga_throw_error(expr, pos-1,
"Missing := for macro definition.");
1519 t_type = ga_read_term(expr, pos, gam.tree(), macro_dict);
1520 if (gam.tree().root)
1521 ga_expand_macro(gam.tree(), gam.tree().root, macro_dict);
1522 gam.nb_params() = params.size();
1524 ga_mark_macro_params(gam, params, macro_dict);
1525 macro_dict.add_macro(gam);
1531 if (t_type == GA_END)
return t_type;
1532 else if (t_type != GA_SEMICOLON)
1533 ga_throw_error(expr, pos-1,
1534 "Syntax error at the end of macro definition.");
1539 case GA_INTERPOLATE:
1541 tree.add_scalar(scalar_type(0), token_pos, expr);
1542 tree.current_node->node_type = GA_NODE_INTERPOLATE;
1543 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1544 if (t_type != GA_LPAR)
1545 ga_throw_error(expr, pos-1,
"Missing interpolate arguments.");
1546 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1547 if (t_type != GA_NAME)
1548 ga_throw_error(expr, pos,
1549 "First argument of Interpolate should be a " 1550 "variable, test function, X or Normal.");
1551 tree.current_node->name = std::string(&((*expr)[token_pos]),
1554 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1555 if (t_type != GA_COMMA)
1556 ga_throw_error(expr, pos,
"Bad format for Interpolate " 1558 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1559 if (t_type != GA_NAME)
1560 ga_throw_error(expr, pos,
1561 "Second argument of Interpolate should be a " 1562 "transformation name.");
1563 tree.current_node->interpolate_name
1564 = std::string(&((*expr)[token_pos]), token_length);
1565 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1566 if (t_type != GA_RPAR)
1567 ga_throw_error(expr, pos-1,
"Missing a parenthesis after " 1568 "interpolate arguments.");
1575 tree.add_scalar(scalar_type(0), token_pos, expr);
1576 tree.current_node->node_type = GA_NODE_ELEMENTARY;
1577 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1578 if (t_type != GA_LPAR)
1579 ga_throw_error(expr, pos-1,
1580 "Missing Elementary_transformation arguments.");
1581 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1582 if (t_type != GA_NAME)
1583 ga_throw_error(expr, pos,
1584 "First argument of Elementary_transformation " 1585 "should be a variable or a test function.");
1586 tree.current_node->name = std::string(&((*expr)[token_pos]),
1589 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1590 if (t_type != GA_COMMA)
1591 ga_throw_error(expr, pos,
"Bad format for " 1592 "Elementary_transformation arguments.");
1593 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1594 if (t_type != GA_NAME)
1595 ga_throw_error(expr, pos,
1596 "Second argument of Elementary_transformation " 1597 "should be a transformation name.");
1598 tree.current_node->elementary_name
1599 = std::string(&((*expr)[token_pos]), token_length);
1600 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1601 if (t_type != GA_RPAR)
1602 ga_throw_error(expr, pos-1,
"Missing a parenthesis after " 1603 "Elementary_transformation arguments.");
1610 tree.add_scalar(scalar_type(0), token_pos, expr);
1611 tree.current_node->node_type = GA_NODE_XFEM_PLUS;
1612 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1613 if (t_type != GA_LPAR)
1614 ga_throw_error(expr, pos-1,
1615 "Missing Xfem_plus arguments.");
1616 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1617 if (t_type != GA_NAME)
1618 ga_throw_error(expr, pos,
1619 "The argument of Xfem_plus should be a " 1620 "variable or a test function.");
1621 tree.current_node->name = std::string(&((*expr)[token_pos]),
1623 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1624 if (t_type != GA_RPAR)
1625 ga_throw_error(expr, pos-1,
"Missing a parenthesis after " 1626 "Xfem_plus argument.");
1633 tree.add_scalar(scalar_type(0), token_pos, expr);
1634 tree.current_node->node_type = GA_NODE_XFEM_MINUS;
1635 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1636 if (t_type != GA_LPAR)
1637 ga_throw_error(expr, pos-1,
1638 "Missing Xfem_minus arguments.");
1639 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1640 if (t_type != GA_NAME)
1641 ga_throw_error(expr, pos,
1642 "The argument of Xfem_minus should be a " 1643 "variable or a test function.");
1644 tree.current_node->name = std::string(&((*expr)[token_pos]),
1646 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1647 if (t_type != GA_RPAR)
1648 ga_throw_error(expr, pos-1,
"Missing a parenthesis after " 1649 "Xfem_minus argument.");
1654 case GA_INTERPOLATE_FILTER:
1656 tree.add_scalar(scalar_type(0), token_pos, expr);
1657 tree.current_node->node_type = GA_NODE_INTERPOLATE_FILTER;
1658 tree.current_node->nbc1 =
size_type(-1);
1659 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1660 if (t_type != GA_LPAR)
1661 ga_throw_error(expr, pos-1,
"Missing interpolate arguments.");
1662 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1663 if (t_type != GA_NAME)
1664 ga_throw_error(expr, pos,
"First argument of Interpolate_filter " 1665 "should be a transformation name.");
1666 tree.current_node->interpolate_name
1667 = std::string(&((*expr)[token_pos]), token_length);
1668 t_type = ga_get_token(*expr, pos, token_pos, token_length);
1669 if (t_type != GA_COMMA)
1670 ga_throw_error(expr, pos,
1671 "Bad format for Interpolate_filter arguments.");
1673 t_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1674 if (t_type != GA_RPAR && t_type != GA_COMMA)
1675 ga_throw_error(expr, pos-1,
1676 "Bad format for Interpolate_filter arguments.");
1677 tree.add_sub_tree(sub_tree);
1678 if (t_type == GA_COMMA) {
1680 t_type = ga_read_term(expr, pos, sub_tree2, macro_dict);
1681 tree.add_sub_tree(sub_tree2);
1683 if (t_type != GA_RPAR)
1684 ga_throw_error(expr, pos-1,
"Unbalanced parenthesis.");
1690 tree.add_op(GA_PRINT, token_pos, expr);
1696 GA_TOKEN_TYPE r_type;
1697 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1698 if (r_type != GA_RPAR)
1699 ga_throw_error(expr, pos-1,
"Unbalanced parenthesis.");
1700 tree.add_sub_tree(sub_tree);
1708 GA_TOKEN_TYPE r_type;
1709 size_type nbc1(0), nbc2(0), nbc3(0), n1(0), n2(0), n3(0);
1711 bool foundcomma(
false), foundsemi(
false);
1713 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1715 tree.add_matrix(token_pos, expr);
1717 if (sub_tree.root->node_type == GA_NODE_C_MATRIX) {
1718 bgeot::multi_index mii;
1722 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1725 if (sub_tree.root->node_type != GA_NODE_C_MATRIX ||
1726 (r_type != GA_COMMA && r_type != GA_RBRACKET))
1727 ga_throw_error(expr, pos-1,
"Bad explicit " 1728 "vector/matrix/tensor format.");
1731 if (sub_tree.root->marked &&
1732 sub_tree.root->tensor().sizes()[0] == 1 &&
1733 sub_tree.root->tensor().size() != 1) {
1734 bgeot::multi_index mi = sub_tree.root->tensor().sizes();
1735 for (
size_type i = mi.size()-1; i > 0; i--)
1738 sub_tree.root->tensor().adjust_sizes(mi);
1740 if (!nb_comp) mii = sub_tree.root->tensor().sizes();
1742 const bgeot::multi_index &mi=sub_tree.root->tensor().sizes();
1744 if (mii.size() == mi.size()) {
1745 for (
size_type i = 0; i < mi.size(); ++i)
1746 if (mi[i] != mii[i]) cmp =
false;
1749 ga_throw_error(expr, pos-1,
"Bad explicit " 1750 "vector/matrix/tensor format.");
1752 for (
size_type i = 0; i < sub_tree.root->children.size(); ++i) {
1753 sub_tree.root->children[i]->parent = tree.current_node;
1754 tree.current_node->children.push_back
1755 (sub_tree.root->children[i]);
1757 sub_tree.root->children.resize(0);
1759 }
while (r_type != GA_RBRACKET);
1760 tree.current_node->marked =
false;
1761 mii.push_back(nb_comp);
1762 tree.current_node->tensor().adjust_sizes(mii);
1767 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1771 tree.add_sub_tree(sub_tree);
1774 if (tensor_order < 2) ++nbc1;
1775 if (tensor_order < 3) ++nbc2;
1776 if (tensor_order < 4) ++nbc3;
1778 if (r_type == GA_COMMA) {
1779 if (!foundcomma && tensor_order > 1)
1780 ga_throw_error(expr, pos-1,
"Bad explicit " 1781 "vector/matrix/tensor format.");
1783 }
else if (r_type == GA_SEMICOLON) {
1785 ga_throw_error(expr, pos-1,
"Bad explicit " 1786 "vector/matrix/tensor format.");
1788 tensor_order = std::max(tensor_order,
size_type(2));
1789 }
else if (r_type == GA_DCOMMA) {
1790 if (n1 != nbc1 || n2 != nbc2)
1791 ga_throw_error(expr, pos-1,
"Bad explicit " 1792 "vector/matrix/tensor format.");
1795 tensor_order = std::max(tensor_order,
size_type(3));
1796 }
else if (r_type == GA_DSEMICOLON) {
1797 if (n1 != nbc1 || n2 != nbc2 || n3 != nbc3 ||
1799 ga_throw_error(expr, pos-1,
"Bad explicit " 1800 "vector/matrix/tensor format.");
1802 tensor_order = std::max(tensor_order,
size_type(4));
1803 }
else if (r_type == GA_RBRACKET) {
1804 if (n1 != nbc1 || n2 != nbc2 || n3 != nbc3 ||
1806 ga_throw_error(expr, pos-1,
"Bad explicit " 1807 "vector/matrix/tensor format.");
1808 tree.current_node->nbc1 = nbc1;
1809 if (tensor_order == 4) {
1810 tree.current_node->nbc2 = nbc2/nbc1;
1811 tree.current_node->nbc3 = nbc3/nbc2;
1813 tree.current_node->nbc2 = tree.current_node->nbc3 = 1;
1816 ga_throw_error(expr, pos-1,
"The explicit " 1817 "vector/matrix/tensor components should be " 1818 "separated by ',', ';', ',,' and ';;' and " 1819 "be ended by ']'.");
1822 }
while (r_type != GA_RBRACKET);
1823 bgeot::multi_index mi;
1824 nbc1 = tree.current_node->nbc1; nbc2 = tree.current_node->nbc2;
1825 nbc3 = tree.current_node->nbc3;
1827 size_type nbl = tree.current_node->children.size()
1828 / (nbc2 * nbc1 * nbc3);
1829 switch(tensor_order) {
1831 mi.push_back(nbc1);
break;
1833 mi.push_back(nbl);
if (nbc1 > 1) mi.push_back(nbc1);
break;
1835 mi.push_back(nbl); mi.push_back(nbc2);
1839 mi.push_back(nbl); mi.push_back(nbc3);
1840 mi.push_back(nbc2); mi.push_back(nbc1);
1842 default: GMM_ASSERT1(
false,
"Internal error");
1844 tree.current_node->tensor().adjust_sizes(mi);
1845 std::vector<pga_tree_node> children = tree.current_node->children;
1846 auto it = tree.current_node->children.begin();
1850 for (
size_type l = 0; l < nbl; ++l, ++it)
1851 *it = children[i+nbc1*(j+nbc2*(k+nbc3*l))];
1852 tree.current_node->marked =
true;
1855 tree.current_node->nbc1 = tree.current_node->tensor().sizes().size();
1860 ga_throw_error(expr, token_pos,
"Unexpected token.");
1866 case GA_PLUS:
case GA_MINUS:
case GA_MULT:
case GA_DIV:
1867 case GA_COLON:
case GA_DOT:
case GA_DOTMULT:
case GA_DOTDIV:
1869 tree.add_op(t_type, token_pos, expr);
1872 tree.add_op(t_type, token_pos, expr);
1874 case GA_END:
case GA_RPAR:
case GA_COMMA:
case GA_DCOMMA:
1875 case GA_RBRACKET:
case GA_SEMICOLON:
case GA_DSEMICOLON:
1880 GA_TOKEN_TYPE r_type;
1881 tree.add_params(token_pos, expr);
1883 r_type = ga_read_term(expr, pos, sub_tree, macro_dict);
1884 if (r_type != GA_RPAR && r_type != GA_COMMA)
1885 ga_throw_error(expr, pos-((r_type != GA_END)?1:0),
1886 "Parameters should be separated " 1887 "by ',' and parameter list ended by ')'.");
1888 tree.add_sub_tree(sub_tree);
1889 }
while (r_type != GA_RPAR);
1895 ga_throw_error(expr, token_pos,
"Unexpected token.");
1905 void ga_read_string_reg(
const std::string &expr, ga_tree &tree,
1906 ga_macro_dictionnary ¯o_dict) {
1907 size_type pos = 0, token_pos, token_length;
1909 GA_TOKEN_TYPE t = ga_get_token(expr, pos, token_pos, token_length);
1910 if (t == GA_END)
return;
1912 pstring nexpr(
new std::string(expr));
1914 t = ga_read_term(nexpr, pos, tree, macro_dict);
1915 if (tree.root) ga_expand_macro(tree, tree.root, macro_dict);
1918 case GA_RPAR: ga_throw_error(nexpr, pos-1,
"Unbalanced parenthesis.");
1919 case GA_RBRACKET: ga_throw_error(nexpr, pos-1,
"Unbalanced braket.");
1921 default: ga_throw_error(nexpr, pos-1,
"Unexpected token.");
1927 void ga_read_string(
const std::string &expr, ga_tree &tree,
1928 const ga_macro_dictionnary ¯o_dict) {
1929 ga_macro_dictionnary macro_dict_loc(
true, macro_dict);
1930 ga_read_string_reg(expr, tree, macro_dict_loc);
1935 std::string ga_substitute(
const std::string &expr,
1936 const std::map<std::string, std::string> &dict) {
1938 size_type pos = 0, token_pos, token_length;
1939 std::stringstream exprs;
1942 GA_TOKEN_TYPE t_type = ga_get_token(expr, pos, token_pos, token_length);
1943 if (t_type == GA_END)
return exprs.str();
1944 std::string name(&(expr[token_pos]), token_length);
1945 if (t_type == GA_NAME && dict.find(name) != dict.end())
1946 exprs << dict.at(name);
else exprs << name;
static T & instance()
Instance from the current thread.
size_t size_type
used as the common size type in the library
GEneric Tool for Finite Element Methods.
Compilation and execution operations.