25 #include <getfem/getfem_generic_assembly_functions_and_operators.h> 27 #include <getfem/getfem_generic_assembly_compile_and_exec.h> 31 extern bool predef_operators_nonlinear_elasticity_initialized;
32 extern bool predef_operators_plasticity_initialized;
33 extern bool predef_operators_contact_initialized;
35 static void ga_node_derivation
36 (ga_tree &tree,
const ga_workspace &workspace,
const mesh &m,
37 pga_tree_node pnode,
const std::string &varname,
38 const std::string &interpolatename,
size_type order);
40 static void ga_node_grad(ga_tree &tree,
const ga_workspace &workspace,
41 const mesh &m, pga_tree_node pnode);
42 static bool ga_node_mark_tree_for_grad(pga_tree_node pnode);
43 static void ga_node_analysis(ga_tree &tree,
44 const ga_workspace &workspace,
45 pga_tree_node pnode,
const mesh &me,
46 size_type ref_elt_dim,
bool eval_fixed_size,
47 bool ignore_X,
int option);
50 bool ga_extract_variables(
const pga_tree_node pnode,
51 const ga_workspace &workspace,
53 std::set<var_trans_pair> &vars,
55 bool expand_groups = !ignore_data;
56 bool found_var =
false;
57 if (pnode->node_type == GA_NODE_VAL ||
58 pnode->node_type == GA_NODE_GRAD ||
59 pnode->node_type == GA_NODE_HESS ||
60 pnode->node_type == GA_NODE_DIVERG ||
61 pnode->node_type == GA_NODE_INTERPOLATE_VAL ||
62 pnode->node_type == GA_NODE_INTERPOLATE_GRAD ||
63 pnode->node_type == GA_NODE_INTERPOLATE_HESS ||
64 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG ||
65 pnode->node_type == GA_NODE_ELEMENTARY_VAL ||
66 pnode->node_type == GA_NODE_ELEMENTARY_GRAD ||
67 pnode->node_type == GA_NODE_ELEMENTARY_HESS ||
68 pnode->node_type == GA_NODE_ELEMENTARY_DIVERG ||
69 pnode->node_type == GA_NODE_XFEM_PLUS_VAL ||
70 pnode->node_type == GA_NODE_XFEM_PLUS_GRAD ||
71 pnode->node_type == GA_NODE_XFEM_PLUS_HESS ||
72 pnode->node_type == GA_NODE_XFEM_PLUS_DIVERG ||
73 pnode->node_type == GA_NODE_XFEM_MINUS_VAL ||
74 pnode->node_type == GA_NODE_XFEM_MINUS_GRAD ||
75 pnode->node_type == GA_NODE_XFEM_MINUS_HESS ||
76 pnode->node_type == GA_NODE_XFEM_MINUS_DIVERG) {
77 bool group = workspace.variable_group_exists(pnode->name);
78 bool iscte = (!group) && workspace.is_constant(pnode->name);
79 if (!iscte) found_var =
true;
80 if (!ignore_data || !iscte) {
81 if (group && expand_groups) {
82 for (
const std::string &t : workspace.variable_group(pnode->name))
83 vars.insert(var_trans_pair(t, pnode->interpolate_name));
85 vars.insert(var_trans_pair(pnode->name, pnode->interpolate_name));
88 if (pnode->node_type == GA_NODE_INTERPOLATE_VAL ||
89 pnode->node_type == GA_NODE_INTERPOLATE_GRAD ||
90 pnode->node_type == GA_NODE_INTERPOLATE_HESS ||
91 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG ||
92 pnode->node_type == GA_NODE_INTERPOLATE_VAL_TEST ||
93 pnode->node_type == GA_NODE_INTERPOLATE_GRAD_TEST ||
94 pnode->node_type == GA_NODE_INTERPOLATE_HESS_TEST ||
95 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG_TEST ||
96 pnode->node_type == GA_NODE_INTERPOLATE_X ||
97 pnode->node_type == GA_NODE_INTERPOLATE_NORMAL) {
98 workspace.interpolate_transformation(pnode->interpolate_name)
99 ->extract_variables(workspace, vars, ignore_data, m,
100 pnode->interpolate_name);
102 for (
auto&& child : pnode->children)
103 found_var = ga_extract_variables(child, workspace, m,
110 static bool ga_node_mark_tree_for_variable
111 (pga_tree_node pnode,
const ga_workspace &workspace,
const mesh &m,
112 const std::string &varname,
113 const std::string &interpolatename) {
115 for (
size_type i = 0; i < pnode->children.size(); ++i)
116 if (ga_node_mark_tree_for_variable(pnode->children[i], workspace, m,
117 varname, interpolatename))
120 bool plain_node(pnode->node_type == GA_NODE_VAL ||
121 pnode->node_type == GA_NODE_GRAD ||
122 pnode->node_type == GA_NODE_HESS ||
123 pnode->node_type == GA_NODE_DIVERG);
124 bool interpolate_node(pnode->node_type == GA_NODE_INTERPOLATE_VAL ||
125 pnode->node_type == GA_NODE_INTERPOLATE_GRAD ||
126 pnode->node_type == GA_NODE_INTERPOLATE_HESS ||
127 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG);
128 bool elementary_node(pnode->node_type == GA_NODE_ELEMENTARY_VAL ||
129 pnode->node_type == GA_NODE_ELEMENTARY_GRAD ||
130 pnode->node_type == GA_NODE_ELEMENTARY_HESS ||
131 pnode->node_type == GA_NODE_ELEMENTARY_DIVERG);
132 bool xfem_node(pnode->node_type == GA_NODE_XFEM_PLUS_VAL ||
133 pnode->node_type == GA_NODE_XFEM_PLUS_GRAD ||
134 pnode->node_type == GA_NODE_XFEM_PLUS_HESS ||
135 pnode->node_type == GA_NODE_XFEM_PLUS_DIVERG ||
136 pnode->node_type == GA_NODE_XFEM_MINUS_VAL ||
137 pnode->node_type == GA_NODE_XFEM_MINUS_GRAD ||
138 pnode->node_type == GA_NODE_XFEM_MINUS_HESS ||
139 pnode->node_type == GA_NODE_XFEM_MINUS_DIVERG);
140 bool interpolate_test_node
141 (pnode->node_type == GA_NODE_INTERPOLATE_VAL_TEST ||
142 pnode->node_type == GA_NODE_INTERPOLATE_GRAD_TEST ||
143 pnode->node_type == GA_NODE_INTERPOLATE_HESS_TEST ||
144 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG_TEST);
146 if ((plain_node || interpolate_node || elementary_node || xfem_node) &&
147 (pnode->name.compare(varname) == 0 &&
148 pnode->interpolate_name.compare(interpolatename) == 0)) marked =
true;
150 if (interpolate_node || interpolate_test_node ||
151 pnode->node_type == GA_NODE_INTERPOLATE_X ||
152 pnode->node_type == GA_NODE_INTERPOLATE_NORMAL) {
153 std::set<var_trans_pair> vars;
154 workspace.interpolate_transformation(pnode->interpolate_name)
155 ->extract_variables(workspace, vars,
true,
156 m, pnode->interpolate_name);
157 for (std::set<var_trans_pair>::iterator it=vars.begin();
158 it != vars.end(); ++it) {
159 if (it->varname.compare(varname) == 0 &&
160 it->transname.compare(interpolatename) == 0) marked =
true;
163 pnode->marked = marked;
167 static void ga_node_expand_expression_in_place_of_test
168 (ga_tree &tree,
const ga_workspace &workspace,
169 pga_tree_node &pnode,
const std::string &varname,
170 pga_tree_node pexpr, ga_tree &grad_expr, ga_tree &hess_expr,
172 bool ignore_X,
int option) {
173 pga_tree_node parent = pnode->parent;
174 for (
size_type i = 0; i < pnode->children.size(); ++i)
175 ga_node_expand_expression_in_place_of_test
176 (tree, workspace, pnode->children[i], varname, pexpr, grad_expr,
177 hess_expr, order, me, ref_elt_dim, eval_fixed_size, ignore_X, option);
178 const std::string &name = pnode->name;
179 size_type loc_order = pnode->test_function_type;
181 if (loc_order == order && !(name.compare(varname))) {
182 bool need_grad = (pnode->node_type == GA_NODE_GRAD_TEST ||
183 pnode->node_type == GA_NODE_DIVERG_TEST ||
184 pnode->node_type == GA_NODE_HESS_TEST);
185 bool need_hess = (pnode->node_type == GA_NODE_HESS_TEST);
187 if (need_grad && grad_expr.root ==
nullptr) {
188 tree.copy_node(pexpr,
nullptr, grad_expr.root);
189 if (ga_node_mark_tree_for_grad(grad_expr.root)) {
190 ga_node_grad(grad_expr, workspace, me, grad_expr.root);
191 ga_node_analysis(grad_expr, workspace, grad_expr.root, me,
192 ref_elt_dim, eval_fixed_size, ignore_X, option);
194 bgeot::multi_index mi = grad_expr.root->t.sizes();
195 mi.push_back(me.dim());
196 grad_expr.root->t.adjust_sizes(mi);
197 grad_expr.root->node_type = GA_NODE_ZERO;
198 gmm::clear(grad_expr.root->tensor().as_vector());
199 grad_expr.clear_children(grad_expr.root);
203 if (need_hess && hess_expr.root ==
nullptr) {
204 tree.copy_node(grad_expr.root,
nullptr, hess_expr.root);
205 if (ga_node_mark_tree_for_grad(hess_expr.root)) {
206 ga_node_grad(hess_expr, workspace, me, hess_expr.root);
207 ga_node_analysis(hess_expr, workspace, hess_expr.root, me,
208 ref_elt_dim, eval_fixed_size, ignore_X, option);
210 bgeot::multi_index mi = hess_expr.root->t.sizes();
211 mi.push_back(me.dim());
212 hess_expr.root->t.adjust_sizes(mi);
213 hess_expr.root->node_type = GA_NODE_ZERO;
214 gmm::clear(hess_expr.root->tensor().as_vector());
215 hess_expr.clear_children(grad_expr.root);
218 switch(pnode->node_type) {
219 case GA_NODE_VAL_TEST:
220 delete pnode; pnode =
nullptr;
221 tree.copy_node(pexpr, parent, pnode);
223 case GA_NODE_GRAD_TEST:
224 delete pnode; pnode =
nullptr;
225 tree.copy_node(grad_expr.root, parent, pnode);
227 case GA_NODE_HESS_TEST:
228 delete pnode; pnode =
nullptr;
229 tree.copy_node(hess_expr.root, parent, pnode);
231 case GA_NODE_DIVERG_TEST:
233 delete pnode; pnode =
nullptr;
234 tree.copy_node(grad_expr.root, parent, pnode);
235 tree.insert_node(pnode, GA_NODE_OP);
236 pnode->parent->op_type = GA_COLON;
237 tree.add_child(pnode->parent, GA_NODE_PARAMS);
238 pga_tree_node pid = pnode->parent->children[1];
239 tree.add_child(pid); tree.add_child(pid);
240 pid->children[0]->node_type = GA_NODE_NAME;
241 pid->children[0]->name =
"Id";
242 pid->children[1]->node_type = GA_NODE_CONSTANT;
243 pid->children[1]->init_scalar_tensor(me.dim());
246 case GA_NODE_INTERPOLATE_VAL_TEST:
case GA_NODE_INTERPOLATE_GRAD_TEST:
247 case GA_NODE_INTERPOLATE_HESS_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
249 "Sorry, directional derivative do not work for the moment " 250 "with interpolate transformations. Future work.");
251 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
252 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
254 "Sorry, directional derivative do not work for the moment " 255 "with elementary transformations. Future work.");
256 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
257 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
258 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
259 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
261 "Sorry, directional derivative do not work for the moment " 262 "with Xfem_plus and Xfem_minus operations. Future work.");
272 static scalar_type ga_hash_code(
const std::string &s) {
275 c += sin(M_E+scalar_type(s[i]))+M_PI*M_E*scalar_type(i+1);
279 static scalar_type ga_hash_code(
const base_tensor &t) {
282 c += sin(M_E+t[i]+M_E*M_E*scalar_type(i+1))+scalar_type(i+1)*M_PI;
286 static scalar_type ga_hash_code(GA_NODE_TYPE e) {
287 return cos(M_E + scalar_type((e == GA_NODE_ZERO) ? GA_NODE_CONSTANT : e));
290 static scalar_type ga_hash_code(
const pga_tree_node pnode) {
291 scalar_type c = ga_hash_code(pnode->node_type);
293 switch (pnode->node_type) {
294 case GA_NODE_CONSTANT:
case GA_NODE_ZERO:
295 c += ga_hash_code(pnode->tensor());
296 if (pnode->test_function_type & 1)
297 c += 34.731 * ga_hash_code(pnode->name_test1);
298 if (pnode->test_function_type & 2)
299 c += 34.731 * ga_hash_code(pnode->name_test2);
302 case GA_NODE_OP: c += scalar_type(pnode->op_type)*M_E*M_PI*M_PI;
break;
303 case GA_NODE_X: c += scalar_type(pnode->nbc1) + M_E*M_PI;
break;
304 case GA_NODE_VAL:
case GA_NODE_GRAD:
305 case GA_NODE_HESS:
case GA_NODE_DIVERG:
306 case GA_NODE_VAL_TEST:
case GA_NODE_GRAD_TEST:
307 case GA_NODE_HESS_TEST:
case GA_NODE_DIVERG_TEST:
308 c += ga_hash_code(pnode->name);
break;
310 case GA_NODE_INTERPOLATE_FILTER:
311 c += 1.73*ga_hash_code(pnode->interpolate_name)
312 + 2.486*double(pnode->nbc1 + 1);
314 case GA_NODE_INTERPOLATE_DERIVATIVE:
315 c += 2.321*ga_hash_code(pnode->interpolate_name_der);
317 case GA_NODE_INTERPOLATE_VAL:
case GA_NODE_INTERPOLATE_GRAD:
318 case GA_NODE_INTERPOLATE_HESS:
case GA_NODE_INTERPOLATE_DIVERG:
319 case GA_NODE_INTERPOLATE_VAL_TEST:
case GA_NODE_INTERPOLATE_GRAD_TEST:
320 case GA_NODE_INTERPOLATE_HESS_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
321 c += 1.33*(1.22+ga_hash_code(pnode->name))
322 + 1.66*ga_hash_code(pnode->interpolate_name);
324 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
325 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
326 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
327 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
328 c += 1.33*(1.22+ga_hash_code(pnode->name))
329 + 2.63*ga_hash_code(pnode->elementary_name);
331 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
332 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
333 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
334 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
335 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
336 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
337 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
338 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
339 c += 1.33*(1.22+ga_hash_code(pnode->name));
341 case GA_NODE_INTERPOLATE_X:
case GA_NODE_INTERPOLATE_NORMAL:
342 c += M_PI*1.33*ga_hash_code(pnode->interpolate_name);
344 case GA_NODE_PREDEF_FUNC:
case GA_NODE_SPEC_FUNC:
case GA_NODE_OPERATOR:
345 c += ga_hash_code(pnode->name)
346 + tanh(scalar_type(pnode->der1)/M_PI + scalar_type(pnode->der2)*M_PI);
353 # define ga_valid_operand(pnode) \ 355 if (pnode && (pnode->node_type == GA_NODE_PREDEF_FUNC || \ 356 pnode->node_type == GA_NODE_SPEC_FUNC || \ 357 pnode->node_type == GA_NODE_NAME || \ 358 pnode->node_type == GA_NODE_OPERATOR || \ 359 pnode->node_type == GA_NODE_ALLINDICES)) \ 360 ga_throw_error(pnode->expr, pnode->pos, "Invalid term"); \ 363 static void ga_node_analysis(ga_tree &tree,
364 const ga_workspace &workspace,
365 pga_tree_node pnode,
const mesh &me,
366 size_type ref_elt_dim,
bool eval_fixed_size,
367 bool ignore_X,
int option) {
368 bool all_cte =
true, all_sc =
true;
370 pnode->symmetric_op =
false;
372 for (
size_type i = 0; i < pnode->children.size(); ++i) {
373 ga_node_analysis(tree, workspace, pnode->children[i], me,
374 ref_elt_dim, eval_fixed_size, ignore_X, option);
375 all_cte = all_cte && (pnode->children[i]->node_type == GA_NODE_CONSTANT);
376 all_sc = all_sc && (pnode->children[i]->tensor_proper_size() == 1);
377 GMM_ASSERT1(pnode->children[i]->test_function_type !=
size_type(-1),
378 "internal error on child " << i);
379 if (pnode->node_type != GA_NODE_PARAMS)
380 ga_valid_operand(pnode->children[i]);
384 pga_tree_node child0 = (nbch > 0) ? pnode->children[0] : 0;
385 pga_tree_node child1 = (nbch > 1) ? pnode->children[1] : 0;
386 bgeot::multi_index mi;
387 const bgeot::multi_index &size0 = child0 ? child0->t.sizes() : mi;
388 const bgeot::multi_index &size1 = child1 ? child1->t.sizes() : mi;
389 size_type dim0 = child0 ? child0->tensor_order() : 0;
390 size_type dim1 = child1 ? child1->tensor_order() : 0;
392 const ga_predef_function_tab &PREDEF_FUNCTIONS
394 const ga_predef_operator_tab &PREDEF_OPERATORS
396 const ga_spec_function_tab &SPEC_FUNCTIONS
399 switch (pnode->node_type) {
400 case GA_NODE_PREDEF_FUNC:
case GA_NODE_OPERATOR:
case GA_NODE_SPEC_FUNC :
401 case GA_NODE_CONSTANT:
case GA_NODE_X:
case GA_NODE_ELT_SIZE:
402 case GA_NODE_ELT_K:
case GA_NODE_ELT_B:
case GA_NODE_NORMAL:
403 case GA_NODE_RESHAPE:
case GA_NODE_IND_MOVE_LAST:
case GA_NODE_SWAP_IND:
404 case GA_NODE_CONTRACT:
case GA_NODE_INTERPOLATE_X:
405 case GA_NODE_INTERPOLATE_NORMAL:
406 pnode->test_function_type = 0;
break;
408 case GA_NODE_ALLINDICES: pnode->test_function_type = 0;
break;
410 if (eval_fixed_size && !(workspace.associated_mf(pnode->name))
411 && !(workspace.associated_im_data(pnode->name))) {
412 gmm::copy(workspace.value(pnode->name), pnode->tensor().as_vector());
413 pnode->node_type = GA_NODE_CONSTANT;
417 case GA_NODE_ZERO:
case GA_NODE_GRAD:
418 case GA_NODE_HESS:
case GA_NODE_DIVERG:
419 case GA_NODE_INTERPOLATE_VAL:
case GA_NODE_INTERPOLATE_GRAD:
420 case GA_NODE_INTERPOLATE_HESS:
case GA_NODE_INTERPOLATE_DIVERG:
421 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
422 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
423 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
424 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
425 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
426 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
429 case GA_NODE_VAL_TEST:
case GA_NODE_GRAD_TEST:
430 case GA_NODE_HESS_TEST:
case GA_NODE_DIVERG_TEST:
431 case GA_NODE_INTERPOLATE_VAL_TEST:
case GA_NODE_INTERPOLATE_GRAD_TEST:
432 case GA_NODE_INTERPOLATE_HESS_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
433 case GA_NODE_INTERPOLATE_DERIVATIVE:
434 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
435 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
436 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
437 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
438 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
439 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
441 const mesh_fem *mf = workspace.associated_mf(pnode->name);
442 size_type t_type = pnode->test_function_type;
444 pnode->name_test1 = pnode->name;
445 pnode->interpolate_name_test1 = pnode->interpolate_name;
446 pnode->interpolate_name_test2 = pnode->name_test2 =
"";
447 pnode->qdim1 = (mf ? workspace.qdim(pnode->name)
448 : gmm::vect_size(workspace.value(pnode->name)));
450 workspace.test1.insert
451 (var_trans_pair(pnode->name_test1,
452 pnode->interpolate_name_test1));
454 ga_throw_error(pnode->expr, pnode->pos,
455 "Invalid null size of variable");
457 pnode->interpolate_name_test1 = pnode->name_test1 =
"";
458 pnode->name_test2 = pnode->name;
459 pnode->interpolate_name_test2 = pnode->interpolate_name;
460 pnode->qdim2 = (mf ? workspace.qdim(pnode->name)
461 : gmm::vect_size(workspace.value(pnode->name)));
463 workspace.test2.insert
464 (var_trans_pair(pnode->name_test2,
465 pnode->interpolate_name_test2));
467 ga_throw_error(pnode->expr, pnode->pos,
468 "Invalid null size of variable");
471 size_type n = workspace.qdim(pnode->name);
473 ga_throw_error(pnode->expr, pnode->pos,
474 "Invalid null size of variable");
476 pnode->init_vector_tensor(1);
477 pnode->tensor()[0] = scalar_type(1);
478 pnode->test_function_type = t_type;
480 pnode->init_matrix_tensor(n,n);
481 pnode->test_function_type = t_type;
484 pnode->tensor()(i,j) = (i==j) ? scalar_type(1) : scalar_type(0);
490 case GA_NODE_INTERPOLATE:
491 if (pnode->name.compare(
"X") == 0) {
492 pnode->node_type = GA_NODE_INTERPOLATE_X;
493 pnode->init_vector_tensor(meshdim);
496 if (pnode->name.compare(
"Normal") == 0) {
497 pnode->node_type = GA_NODE_INTERPOLATE_NORMAL;
498 pnode->init_vector_tensor(meshdim);
502 case GA_NODE_ELEMENTARY:
503 case GA_NODE_XFEM_PLUS:
504 case GA_NODE_XFEM_MINUS:
506 int ndt = ((pnode->node_type == GA_NODE_INTERPOLATE) ? 1 : 0)
507 + ((pnode->node_type == GA_NODE_ELEMENTARY) ? 2 : 0)
508 + ((pnode->node_type == GA_NODE_XFEM_PLUS) ? 3 : 0)
509 + ((pnode->node_type == GA_NODE_XFEM_MINUS) ? 4 : 0);
510 std::string op__name =
511 (pnode->node_type == GA_NODE_INTERPOLATE) ?
"Interpolation" :
"" 512 + (pnode->node_type == GA_NODE_ELEMENTARY) ?
513 "Elementary transformation" :
"" 514 + (pnode->node_type == GA_NODE_XFEM_PLUS) ?
"Xfem_plus" :
"" 515 + (pnode->node_type == GA_NODE_XFEM_MINUS) ?
"Xfem_minus" :
"";
517 std::string name = pnode->name;
518 size_type prefix_id = ga_parse_prefix_operator(name);
519 size_type test = ga_parse_prefix_test(name);
523 if (!(workspace.variable_or_group_exists(name)))
524 ga_throw_error(pnode->expr, pnode->pos,
525 "Unknown variable or group of variables \"" 528 const mesh_fem *mf = workspace.associated_mf(name);
530 ga_throw_error(pnode->expr, pnode->pos, op__name
531 <<
" can only apply to finite element variables/data");
533 size_type q = workspace.qdim(name), n = mf->linked_mesh().dim();
534 if (!q) ga_throw_error(pnode->expr, pnode->pos,
535 "Invalid null size of variable");
537 bgeot::multi_index mii = workspace.qdims(name);
539 ga_throw_error(pnode->expr, pnode->pos,
540 "Tensor with too many dimensions. Limited to 6");
543 pnode->name_test1 = name;
544 pnode->interpolate_name_test1 = pnode->interpolate_name;
546 workspace.test1.insert
547 (var_trans_pair(pnode->name_test1,
548 pnode->interpolate_name_test1));
549 pnode->qdim1 = workspace.qdim(name);
551 ga_throw_error(pnode->expr, pnode->pos,
552 "Invalid null size of variable");
553 }
else if (test == 2) {
554 pnode->name_test2 = name;
555 pnode->interpolate_name_test2 = pnode->interpolate_name;
557 workspace.test2.insert
558 (var_trans_pair(pnode->name_test2,
559 pnode->interpolate_name_test2));
560 pnode->qdim2 = workspace.qdim(name);
562 ga_throw_error(pnode->expr, pnode->pos,
563 "Invalid null size of variable");
570 case 1: pnode->node_type = GA_NODE_INTERPOLATE_VAL;
break;
571 case 2: pnode->node_type = GA_NODE_ELEMENTARY_VAL;
break;
572 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_VAL;
break;
573 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_VAL;
break;
574 default: GMM_ASSERT1(
false,
"internal error");
578 case 1: pnode->node_type = GA_NODE_INTERPOLATE_VAL_TEST;
break;
579 case 2: pnode->node_type = GA_NODE_ELEMENTARY_VAL_TEST;
break;
580 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_VAL_TEST;
break;
581 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_VAL_TEST;
break;
582 default: GMM_ASSERT1(
false,
"internal error");
584 if (q == 1 && mii.size() <= 1) {
588 mii.insert(mii.begin(), 2);
594 case 1: pnode->node_type = GA_NODE_INTERPOLATE_GRAD;
break;
595 case 2: pnode->node_type = GA_NODE_ELEMENTARY_GRAD;
break;
596 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_GRAD;
break;
597 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_GRAD;
break;
598 default: GMM_ASSERT1(
false,
"internal error");
601 if (q == 1 && mii.size() == 1) mii[0] = n;
602 else mii.push_back(n);
606 case 1: pnode->node_type = GA_NODE_INTERPOLATE_GRAD_TEST;
break;
607 case 2: pnode->node_type = GA_NODE_ELEMENTARY_GRAD_TEST;
break;
608 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_GRAD_TEST;
break;
609 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_GRAD_TEST;
break;
610 default: GMM_ASSERT1(
false,
"internal error");
612 if (q == 1 && mii.size() <= 1) {
616 mii.insert(mii.begin(), 2);
617 if (n > 1) mii.push_back(n);
623 case 1: pnode->node_type = GA_NODE_INTERPOLATE_HESS;
break;
624 case 2: pnode->node_type = GA_NODE_ELEMENTARY_HESS;
break;
625 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_HESS;
break;
626 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_HESS;
break;
627 default: GMM_ASSERT1(
false,
"internal error");
630 if (q == 1 && mii.size() == 1) { mii[0] = n; mii.push_back(n); }
631 else { mii.push_back(n); mii.push_back(n); }
635 case 1: pnode->node_type = GA_NODE_INTERPOLATE_HESS_TEST;
break;
636 case 2: pnode->node_type = GA_NODE_ELEMENTARY_HESS_TEST;
break;
637 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_HESS_TEST;
break;
638 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_HESS_TEST;
break;
639 default: GMM_ASSERT1(
false,
"internal error");
641 if (q == 1 && mii.size() <= 1) {
645 mii.insert(mii.begin(), 2);
646 if (n > 1) { mii.push_back(n); mii.push_back(n); }
651 ga_throw_error(pnode->expr, pnode->pos,
652 "Divergence operator requires fem qdim (" 653 << q <<
") to be equal to dim (" << n <<
")");
656 case 1: pnode->node_type = GA_NODE_INTERPOLATE_DIVERG;
break;
657 case 2: pnode->node_type = GA_NODE_ELEMENTARY_DIVERG;
break;
658 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_DIVERG;
break;
659 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_DIVERG;
break;
660 default: GMM_ASSERT1(
false,
"internal error");
666 case 1: pnode->node_type = GA_NODE_INTERPOLATE_DIVERG_TEST;
break;
667 case 2: pnode->node_type = GA_NODE_ELEMENTARY_DIVERG_TEST;
break;
668 case 3: pnode->node_type = GA_NODE_XFEM_PLUS_DIVERG_TEST;
break;
669 case 4: pnode->node_type = GA_NODE_XFEM_MINUS_DIVERG_TEST;
break;
670 default: GMM_ASSERT1(
false,
"internal error");
677 pnode->t.adjust_sizes(mii);
678 pnode->test_function_type = test;
681 if (!(workspace.interpolate_transformation_exists
682 (pnode->interpolate_name))) {
683 ga_throw_error(pnode->expr, pnode->pos,
684 "Unknown interpolate transformation");
686 }
else if (ndt == 2) {
687 if (!(workspace.elementary_transformation_exists
688 (pnode->elementary_name))) {
689 ga_throw_error(pnode->expr, pnode->pos,
690 "Unknown elementary transformation");
696 case GA_NODE_INTERPOLATE_FILTER:
698 if (pnode->children.size() == 2) {
699 bool valid = (child1->node_type == GA_NODE_CONSTANT);
700 int n = valid ? int(round(child1->tensor()[0])) : -1;
701 if (n < 0 || n > 100 || child1->tensor_order() > 0)
702 ga_throw_error(pnode->expr, pnode->pos,
"The third argument of " 703 "Interpolate_filter should be a (small) " 704 "non-negative integer.");
706 tree.clear_node(child1);
708 if (!(workspace.interpolate_transformation_exists
709 (pnode->interpolate_name)))
710 ga_throw_error(pnode->expr, pnode->pos,
711 "Unknown interpolate transformation");
712 pnode->t = child0->t;
713 pnode->test_function_type = child0->test_function_type;
714 pnode->name_test1 = child0->name_test1;
715 pnode->name_test2 = child0->name_test2;
716 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
717 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
718 pnode->qdim1 = child0->qdim1;
719 pnode->qdim2 = child0->qdim2;
725 switch(pnode->op_type) {
727 case GA_PLUS:
case GA_MINUS:
729 if (pnode->op_type == GA_PLUS) pnode->symmetric_op =
true;
730 size_type c_size = std::min(size0.size(), size1.size());
731 bool compatible =
true;
734 if (child0->test_function_type &&
735 child1->test_function_type == child0->test_function_type)
736 f_ind = (child0->test_function_type == 3) ? 2:1;
738 for (
size_type i = f_ind; i < c_size; ++i)
739 if (size0[i] != size1[i]) compatible =
false;
740 for (
size_type i = c_size; i < size0.size(); ++i)
741 if (size0[i] != 1) compatible =
false;
742 for (
size_type i = c_size; i < size1.size(); ++i)
743 if (size1[i] != 1) compatible =
false;
746 ga_throw_error(pnode->expr, pnode->pos,
747 "Addition or substraction of expressions of " 748 "different sizes: " << size0 <<
" != " << size1);
749 if (child0->test_function_type || child1->test_function_type) {
752 if (child0->name_test1.compare(child1->name_test1) ||
753 child0->name_test2.compare(child1->name_test2) ||
754 child0->interpolate_name_test1.compare
755 (child1->interpolate_name_test1) ||
756 child0->interpolate_name_test2.compare
757 (child1->interpolate_name_test2))
760 case 1:
case 3:
break;
761 default: GMM_ASSERT1(
false,
"Unknown option");
765 if (child0->test_function_type != child1->test_function_type ||
766 (!compatible && option != 2))
767 ga_throw_error(pnode->expr, pnode->pos,
"Addition or substraction " 768 "of incompatible test functions");
770 pnode->node_type = GA_NODE_CONSTANT;
771 pnode->test_function_type = 0;
772 pnode->tensor() = pnode->children[0]->tensor();
773 if (pnode->op_type == GA_MINUS)
774 pnode->tensor() -= pnode->children[1]->tensor();
776 pnode->tensor() += pnode->children[1]->tensor();
777 tree.clear_children(pnode);
779 pnode->t = child0->t;
780 pnode->test_function_type = child0->test_function_type;
781 pnode->name_test1 = child0->name_test1;
782 pnode->name_test2 = child0->name_test2;
783 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
784 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
785 pnode->qdim1 = child0->qdim1;
786 pnode->qdim2 = child0->qdim2;
789 if (child0->tensor_is_zero()) {
790 if (pnode->op_type == GA_MINUS) {
791 pnode->op_type = GA_UNARY_MINUS;
792 tree.clear_node(child0);
794 tree.replace_node_by_child(pnode, 1);
797 }
else if (child1->tensor_is_zero()) {
798 tree.replace_node_by_child(pnode, 0);
800 }
else if (option == 2 && !compatible) {
801 bool child0_compatible =
true, child1_compatible =
true;
802 if (pnode->test_function_type & 1) {
803 if (child0->name_test1.compare(workspace.selected_test1.varname)
804 || child0->interpolate_name_test1.compare
805 (workspace.selected_test1.transname))
806 child0_compatible =
false;
807 if (child1->name_test1.compare(workspace.selected_test1.varname)
808 || child1->interpolate_name_test1.compare
809 (workspace.selected_test1.transname))
810 child1_compatible =
false;
812 if (pnode->test_function_type & 2) {
813 if (child0->name_test2.compare(workspace.selected_test2.varname)
814 || child0->interpolate_name_test2.compare
815 (workspace.selected_test2.transname))
816 child0_compatible =
false;
817 if (child1->name_test2.compare(workspace.selected_test2.varname)
818 || child1->interpolate_name_test1.compare
819 (workspace.selected_test2.transname))
820 child1_compatible =
false;
822 if (child0_compatible) {
823 tree.replace_node_by_child(pnode, 0);
825 }
else if (child1_compatible) {
826 if (pnode->op_type == GA_MINUS) {
827 pnode->op_type = GA_UNARY_MINUS;
828 pnode->t = child1->t;
829 pnode->test_function_type = child1->test_function_type;
830 pnode->name_test1 = child1->name_test1;
831 pnode->name_test2 = child1->name_test2;
832 pnode->interpolate_name_test1=child1->interpolate_name_test1;
833 pnode->interpolate_name_test2=child1->interpolate_name_test2;
834 pnode->qdim1 = child1->qdim1;
835 pnode->qdim2 = child1->qdim2;
836 tree.clear_node(child0);
838 tree.replace_node_by_child(pnode, 1);
847 case GA_DOTMULT:
case GA_DOTDIV:
849 if (pnode->op_type == GA_DOTMULT) pnode->symmetric_op =
true;
850 bool compatible =
true;
851 if (child0->tensor_proper_size() != child1->tensor_proper_size())
854 if (child0->tensor_proper_size() != 1) {
855 if (child0->tensor_order() != child1->tensor_order())
858 for (
size_type i = 0; i < child0->tensor_order(); ++i)
859 if (child0->tensor_proper_size(i)!=child1->tensor_proper_size(i))
864 ga_throw_error(pnode->expr, pnode->pos,
865 "Arguments of different sizes for .* or ./");
867 if (pnode->op_type == GA_DOTDIV && child1->test_function_type)
868 ga_throw_error(pnode->expr, pnode->pos,
869 "Division by test functions is not allowed");
871 pnode->mult_test(child0, child1);
872 mi = pnode->t.sizes();
873 for (
size_type i = 0; i < child0->tensor_order(); ++i)
874 mi.push_back(child0->tensor_proper_size(i));
875 pnode->t.adjust_sizes(mi);
878 pnode->node_type = GA_NODE_CONSTANT;
879 pnode->test_function_type = 0;
880 if (pnode->op_type == GA_DOTMULT) {
881 for (
size_type i = 0; i < child0->tensor().size(); ++i)
882 pnode->tensor()[i] = child0->tensor()[i] * child1->tensor()[i];
884 for (
size_type i = 0; i < child0->tensor().size(); ++i) {
885 if (child1->tensor()[i] == scalar_type(0))
886 ga_throw_error(pnode->expr, pnode->pos,
"Division by zero.");
887 pnode->tensor()[i] = child0->tensor()[i] / child1->tensor()[i];
890 tree.clear_children(pnode);
892 if (child0->tensor_is_zero() || child1->tensor_is_zero()) {
894 pnode->node_type = GA_NODE_ZERO;
895 tree.clear_children(pnode);
897 if (child1->tensor_is_zero() && pnode->op_type == GA_DOTDIV)
898 ga_throw_error(pnode->expr, pnode->pos,
"Division by zero.");
904 pnode->t = child0->t;
905 pnode->test_function_type = child0->test_function_type;
906 pnode->name_test1 = child0->name_test1;
907 pnode->name_test2 = child0->name_test2;
908 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
909 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
910 pnode->qdim1 = child0->qdim1;
911 pnode->qdim2 = child0->qdim2;
913 pnode->node_type = GA_NODE_CONSTANT;
914 pnode->test_function_type = 0;
915 gmm::scale(pnode->tensor().as_vector(), scalar_type(-1));
916 tree.clear_children(pnode);
917 }
else if (child0->node_type == GA_NODE_ZERO) {
918 tree.replace_node_by_child(pnode, 0);
925 if (child0->tensor_proper_size() == 1)
926 { tree.replace_node_by_child(pnode, 0); pnode = child0;
break; }
928 {
size_type N = mi.back(); mi.back() = 1; mi.push_back(N); }
929 else std::swap(mi[child0->nb_test_functions()],
930 mi[child0->nb_test_functions()+1]);
933 pnode->t.adjust_sizes(mi);
934 pnode->test_function_type = child0->test_function_type;
935 pnode->name_test1 = child0->name_test1;
936 pnode->name_test2 = child0->name_test2;
937 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
938 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
939 pnode->qdim1 = child0->qdim1;
940 pnode->qdim2 = child0->qdim2;
941 if (child0->node_type == GA_NODE_ZERO) {
942 pnode->node_type = GA_NODE_ZERO;
944 tree.clear_children(pnode);
945 }
else if (all_cte) {
946 pnode->node_type = GA_NODE_CONSTANT;
947 pnode->test_function_type = 0;
950 for (
size_type i = 0; i < mi.back(); ++i)
951 pnode->tensor()(0, i) = child0->tensor()[i];
953 size_type n1 = child0->tensor_proper_size(0);
954 size_type n2 = child0->tensor_proper_size(1);
955 size_type nn = child0->tensor().size()/(n1*n2);
956 auto it = pnode->tensor().begin();
960 *it = child0->tensor()[j+k*n1+i*n1*n2];
961 GA_DEBUG_ASSERT(it == pnode->tensor().end(),
"Wrong sizes");
963 tree.clear_children(pnode);
967 case GA_SYM:
case GA_SKEW:
968 if (child0->tensor_proper_size() != 1 &&
969 (dim0 != 2 || size0.back() != size0[size0.size()-2]))
970 ga_throw_error(pnode->expr, pnode->pos,
"Sym and Skew operators are " 971 "for square matrices only.");
973 if (child0->tensor_proper_size() == 1) {
974 if (pnode->op_type == GA_SYM)
975 { tree.replace_node_by_child(pnode, 0); pnode = child0;
break; }
977 pnode->node_type = GA_NODE_ZERO;
979 tree.clear_children(pnode);
984 pnode->t.adjust_sizes(mi);
985 pnode->test_function_type = child0->test_function_type;
986 pnode->name_test1 = child0->name_test1;
987 pnode->name_test2 = child0->name_test2;
988 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
989 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
990 pnode->qdim1 = child0->qdim1;
991 pnode->qdim2 = child0->qdim2;
993 pnode->node_type = GA_NODE_CONSTANT;
994 pnode->test_function_type = 0;
995 for (
size_type i = 0; i < mi.back(); ++i)
996 for (
size_type j = 0; j < mi.back(); ++j)
997 if (pnode->op_type == GA_SYM)
998 pnode->tensor()(j, i) = 0.5*(child0->tensor()(j,i)
999 + child0->tensor()(i,j));
1001 pnode->tensor()(j, i) = 0.5*(child0->tensor()(j,i)
1002 - child0->tensor()(i,j));
1003 tree.clear_children(pnode);
1004 }
else if (child0->node_type == GA_NODE_ZERO) {
1005 pnode->node_type = GA_NODE_ZERO;
1007 tree.clear_children(pnode);
1014 size_type N = (child0->tensor_proper_size() == 1) ? 1 : mi.back();
1016 if (child0->tensor_proper_size() == 1)
1017 { tree.replace_node_by_child(pnode, 0); pnode = child0;
break; }
1019 if ((dim0 != 2 && child0->tensor_proper_size() != 1) ||
1020 (dim0 == 2 && mi[mi.size()-2] != N))
1021 ga_throw_error(pnode->expr, pnode->pos,
1022 "Trace operator is for square matrices only.");
1024 if (dim0 == 2) { mi.pop_back(); mi.pop_back(); }
1025 pnode->t.adjust_sizes(mi);
1026 pnode->test_function_type = child0->test_function_type;
1027 pnode->name_test1 = child0->name_test1;
1028 pnode->name_test2 = child0->name_test2;
1029 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
1030 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
1031 pnode->qdim1 = child0->qdim1;
1032 pnode->qdim2 = child0->qdim2;
1034 pnode->node_type = GA_NODE_CONSTANT;
1035 pnode->test_function_type = 0;
1037 pnode->tensor()[0] = scalar_type(0);
1039 pnode->tensor()[0] += child0->tensor()(i,i);
1041 pnode->tensor()[0] += child0->tensor()[0];
1043 tree.clear_children(pnode);
1044 }
else if (child0->node_type == GA_NODE_ZERO) {
1045 pnode->node_type = GA_NODE_ZERO;
1047 tree.clear_children(pnode);
1055 size_type N = (child0->tensor_proper_size() == 1) ? 1 : mi.back();
1057 if ((dim0 != 2 && child0->tensor_proper_size() != 1) ||
1058 (dim0 == 2 && mi[mi.size()-2] != N))
1059 ga_throw_error(pnode->expr, pnode->pos,
1060 "Deviator operator is for square matrices only.");
1062 if (child0->tensor_proper_size() == 1) {
1063 pnode->node_type = GA_NODE_ZERO;
1065 tree.clear_children(pnode);
1069 pnode->t.adjust_sizes(mi);
1070 pnode->test_function_type = child0->test_function_type;
1071 pnode->name_test1 = child0->name_test1;
1072 pnode->name_test2 = child0->name_test2;
1073 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
1074 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
1075 pnode->qdim1 = child0->qdim1;
1076 pnode->qdim2 = child0->qdim2;
1078 pnode->node_type = GA_NODE_CONSTANT;
1079 pnode->test_function_type = 0;
1082 gmm::copy(child0->tensor().as_vector(),
1083 pnode->tensor().as_vector());
1085 tr += child0->tensor()(i,i);
1087 pnode->tensor()(i,i) -= tr / scalar_type(N);
1089 pnode->tensor()[0] = scalar_type(0);
1091 tree.clear_children(pnode);
1092 }
else if (child0->node_type == GA_NODE_ZERO) {
1093 pnode->node_type = GA_NODE_ZERO;
1095 tree.clear_children(pnode);
1102 pnode->t = child0->t;
1103 pnode->test_function_type = child0->test_function_type;
1104 pnode->name_test1 = child0->name_test1;
1105 pnode->name_test2 = child0->name_test2;
1106 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
1107 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
1108 pnode->qdim1 = child0->qdim1;
1109 pnode->qdim2 = child0->qdim2;
1111 pnode->node_type = GA_NODE_CONSTANT;
1112 cout <<
"Print constant term "; ga_print_node(child0, cout);
1113 cout <<
": " << pnode->tensor() << endl;
1114 tree.clear_children(pnode);
1115 }
else if (child0->node_type == GA_NODE_ZERO) {
1116 pnode->node_type = GA_NODE_ZERO;
1118 cout <<
"Print zero term "; ga_print_node(child0, cout);
1119 cout <<
": " << pnode->tensor() << endl;
1120 tree.clear_children(pnode);
1127 size_type s0 = dim0 == 0 ? 1 : size0.back();
1128 size_type s1 = dim1 == 0 ? 1 : size1[size1.size()-dim1];
1130 if (s0 != s1) ga_throw_error(pnode->expr, pnode->pos,
"Dot product " 1131 "of expressions of different sizes (" 1132 << s0 <<
" != " << s1 <<
").");
1133 if (dim0 <= 1 && dim1 <= 1) pnode->symmetric_op =
true;
1134 pnode->mult_test(child0, child1);
1135 if (dim0 > 1 || dim1 > 1) {
1136 mi = pnode->t.sizes();
1138 mi.push_back(child0->tensor_proper_size(i-1));
1140 mi.push_back(child1->tensor_proper_size(i));
1141 pnode->t.adjust_sizes(mi);
1144 if (child0->tensor_is_zero() || child1->tensor_is_zero()) {
1146 pnode->node_type = GA_NODE_ZERO;
1147 tree.clear_children(pnode);
1148 }
else if (all_cte) {
1150 size_type m0 = child0->tensor().size() / s0;
1151 size_type m1 = child1->tensor().size() / s1;
1155 pnode->tensor()[i*m1+j]
1156 += child0->tensor()[i*s0+k] * child1->tensor()[k*m1+j];
1157 pnode->node_type = GA_NODE_CONSTANT;
1158 tree.clear_children(pnode);
1165 ga_throw_error(pnode->expr, pnode->pos,
1166 "Frobenius product acts only on matrices.")
1169 : (dim0 == 1 ? size0.back() : size0[size0.size()-2]);
1170 size_type s01 = (dim0 >= 2) ? size0.back() : 1;
1172 : (dim1 == 1 ? size1.back() : size1[size1.size()-2]);
1173 size_type s11 = (dim1 >= 2) ? size1.back() : 1;
1174 if (s00 != s10 || s01 != s11)
1175 ga_throw_error(pnode->expr, pnode->pos,
"Frobenius product " 1176 "of expressions of different sizes (" 1177 << s00 <<
"," << s01 <<
" != " << s10 <<
"," 1179 if (child0->tensor_order() <= 2) pnode->symmetric_op =
true;
1180 pnode->mult_test(child0, child1);
1182 mi = pnode->t.sizes();
1184 mi.push_back(child0->tensor_proper_size(i-2));
1185 pnode->t.adjust_sizes(mi);
1188 if (child0->tensor_is_zero() || child1->tensor_is_zero()) {
1190 pnode->node_type = GA_NODE_ZERO;
1191 tree.clear_children(pnode);
1192 }
else if (all_cte) {
1193 pnode->node_type = GA_NODE_CONSTANT;
1196 for (
size_type i = 0, j = 0; i < child0->tensor().size(); ++i) {
1197 pnode->tensor()[j] += child0->tensor()[i] * child1->tensor()[k];
1198 ++j;
if (j == pnode->tensor().size()) { j = 0; ++k; }
1200 GMM_ASSERT1(k == child1->tensor().size(),
"Internal error");
1201 tree.clear_children(pnode);
1208 pnode->node_type = GA_NODE_CONSTANT;
1209 pnode->test_function_type = 0;
1210 if (child0->tensor().size() == 1 && child1->tensor().size() == 1) {
1211 pnode->init_scalar_tensor
1212 (child0->tensor()[0] * child1->tensor()[0]);
1213 }
else if (child0->tensor().size() == 1) {
1214 pnode->t = child1->t;
1215 gmm::scale(pnode->tensor().as_vector(),
1216 scalar_type(child0->tensor()[0]));
1217 }
else if (child1->tensor().size() == 1) {
1218 pnode->t = child0->t;
1219 gmm::scale(pnode->tensor().as_vector(),
1220 scalar_type(child1->tensor()[0]));
1223 ga_throw_error(pnode->expr, pnode->pos,
"Unauthorized " 1224 "tensor multiplication.");
1226 mi.push_back(child0->tensor().size(i));
1228 mi.push_back(child1->tensor().size(i));
1229 pnode->t.adjust_sizes(mi);
1234 pnode->tensor()[i+j*n0]=child0->tensor()[i]*child1->tensor()[j];
1236 tree.clear_children(pnode);
1238 pnode->mult_test(child0, child1);
1239 mi = pnode->t.sizes();
1240 if (child0->tensor_proper_size() != 1
1241 || child1->tensor_proper_size() != 1) {
1242 if (child0->tensor_proper_size() == 1) {
1244 mi.push_back(child1->tensor_proper_size(i));
1245 }
else if (child1->tensor().size() == 1) {
1247 mi.push_back(child0->tensor_proper_size(i));
1250 ga_throw_error(pnode->expr, pnode->pos,
"Unauthorized " 1251 "tensor multiplication.");
1253 mi.push_back(child0->tensor_proper_size(i));
1255 mi.push_back(child1->tensor_proper_size(i));
1257 pnode->t.adjust_sizes(mi);
1259 if (child0->tensor_is_zero() || child1->tensor_is_zero()) {
1261 pnode->node_type = GA_NODE_ZERO;
1262 tree.clear_children(pnode);
1269 pnode->node_type = GA_NODE_CONSTANT;
1270 pnode->test_function_type = 0;
1271 if (child0->tensor_proper_size() == 1 &&
1272 child1->tensor_proper_size() == 1) {
1273 pnode->init_scalar_tensor(child0->tensor()[0]*child1->tensor()[0]);
1274 }
else if (child0->tensor_proper_size() == 1) {
1275 pnode->t = child1->t;
1276 gmm::scale(pnode->tensor().as_vector(), child0->tensor()[0]);
1277 }
else if (child1->tensor_proper_size() == 1) {
1278 pnode->t = child0->t;
1279 gmm::scale(pnode->tensor().as_vector(), child1->tensor()[0]);
1280 }
else if (dim0 == 2 && dim1 == 1) {
1281 size_type m=child0->tensor().size(0), n=child0->tensor().size(1);
1282 if (n != child1->tensor().size(0))
1283 ga_throw_error(pnode->expr, pnode->pos,
1284 "Incompatible sizes in matrix-vector " 1285 "multiplication (" << n <<
" != " 1286 << child1->tensor().size(0) <<
").");
1287 pnode->init_vector_tensor(m);
1291 pnode->tensor()[i] += child0->tensor()(i,j)*child1->tensor()[j];
1292 }
else if (dim0 == 2 && dim1 == 2) {
1296 if (n != child1->tensor().size(0))
1297 ga_throw_error(pnode->expr, pnode->pos,
1298 "Incompatible sizes in matrix-matrix " 1299 "multiplication (" << n <<
" != " 1300 << child1->tensor().size(0) <<
").");
1301 pnode->init_matrix_tensor(m,p);
1306 pnode->tensor()(i,k) += child0->tensor()(i,j)
1307 * child1->tensor()(j,k);
1309 else if (dim0 == 4 && dim1 == 2) {
1310 size_type m=child0->tensor().size(0), n=child0->tensor().size(1);
1311 size_type o=child0->tensor().size(2), p=child0->tensor().size(3);
1312 if (o != child1->tensor().size(0) || p != child1->tensor().size(1))
1313 ga_throw_error(pnode->expr, pnode->pos,
1314 "Incompatible sizes in tensor-matrix " 1315 "multiplication (" << o <<
"," << p <<
" != " 1316 << child1->tensor().size(0) <<
"," 1317 << child1->tensor().size(1) <<
").");
1318 pnode->init_matrix_tensor(m,n);
1324 pnode->tensor()(i,j) += child0->tensor()(i,j,k,l)
1325 * child1->tensor()(k,l);
1326 }
else ga_throw_error(pnode->expr, pnode->pos,
1327 "Unauthorized multiplication.");
1328 tree.clear_children(pnode);
1330 pnode->mult_test(child0, child1);
1331 mi = pnode->t.sizes();
1333 if (child0->tensor_proper_size() == 1 &&
1334 child1->tensor_proper_size() == 1) {
1335 pnode->symmetric_op =
true;
1336 }
else if (child0->tensor_proper_size() == 1) {
1337 pnode->symmetric_op =
true;
1339 mi.push_back(child1->tensor_proper_size(i));
1340 }
else if (child1->tensor_proper_size() == 1) {
1341 pnode->symmetric_op =
true;
1343 mi.push_back(child0->tensor_proper_size(i));
1344 }
else if (child0->tensor_order() == 2 &&
1345 child1->tensor_order() == 1) {
1346 size_type m = child0->tensor_proper_size(0);
1347 size_type n = child0->tensor_proper_size(1);
1349 if (n != child1->tensor_proper_size(0))
1350 ga_throw_error(pnode->expr, pnode->pos,
1351 "Incompatible sizes in matrix-vector " 1352 "multiplication (" << n <<
" != " 1353 << child1->tensor_proper_size(0) <<
").");
1354 }
else if (child0->tensor_order() == 2 &&
1355 child1->tensor_order() == 2) {
1356 size_type m = child0->tensor_proper_size(0);
1357 size_type n = child0->tensor_proper_size(1);
1358 size_type p = child1->tensor_proper_size(1);
1359 mi.push_back(m); mi.push_back(p);
1360 if (n != child1->tensor_proper_size(0))
1361 ga_throw_error(pnode->expr, pnode->pos,
1362 "Incompatible sizes in matrix-matrix " 1363 "multiplication (" << n <<
" != " 1364 << child1->tensor_proper_size(0) <<
").");
1366 else if (pnode->children[0]->tensor_order() == 4 &&
1367 pnode->children[1]->tensor_order() == 2) {
1368 size_type m = child0->tensor_proper_size(0);
1369 size_type n = child0->tensor_proper_size(1);
1370 size_type o = child0->tensor_proper_size(2);
1371 size_type p = child0->tensor_proper_size(3);
1372 mi.push_back(m); mi.push_back(n);
1373 if (o != child1->tensor_proper_size(0) ||
1374 p != child1->tensor_proper_size(1))
1375 ga_throw_error(pnode->expr, pnode->pos,
1376 "Incompatible sizes in tensor-matrix " 1377 "multiplication (" << o <<
"," << p <<
" != " 1378 << child1->tensor_proper_size(0) <<
"," 1379 << child1->tensor_proper_size(1) <<
").");
1380 }
else ga_throw_error(pnode->expr, pnode->pos,
1381 "Unauthorized multiplication.");
1382 pnode->t.adjust_sizes(mi);
1384 if (child0->tensor_is_zero() || child1->tensor_is_zero()) {
1386 pnode->node_type = GA_NODE_ZERO;
1387 tree.clear_children(pnode);
1388 }
else if (child0->node_type == GA_NODE_CONSTANT &&
1389 child0->tensor().size() == 1 &&
1390 child0->tensor()[0] == scalar_type(1)) {
1391 tree.replace_node_by_child(pnode, 1);
1393 }
else if (child1->node_type == GA_NODE_CONSTANT &&
1394 child1->tensor().size() == 1 &&
1395 child1->tensor()[0] == scalar_type(1)) {
1396 tree.replace_node_by_child(pnode, 0);
1403 if (child1->tensor_proper_size() > 1)
1404 ga_throw_error(pnode->expr, pnode->pos,
1405 "Only the division by a scalar is allowed. " 1406 "Got a size of " << child1->tensor_proper_size());
1407 if (child1->test_function_type)
1408 ga_throw_error(pnode->expr, pnode->pos,
1409 "Division by test functions is not allowed.");
1410 if (child1->node_type == GA_NODE_CONSTANT &&
1411 child1->tensor()[0] == scalar_type(0))
1412 ga_throw_error(pnode->expr, pnode->children[1]->pos,
1413 "Division by zero");
1415 pnode->t = child0->t;
1416 pnode->test_function_type = child0->test_function_type;
1417 pnode->name_test1 = child0->name_test1;
1418 pnode->name_test2 = child0->name_test2;
1419 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
1420 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
1421 pnode->qdim1 = child0->qdim1;
1422 pnode->qdim2 = child0->qdim2;
1425 pnode->node_type = GA_NODE_CONSTANT;
1426 pnode->t = pnode->children[0]->t;
1427 pnode->test_function_type = 0;
1428 gmm::scale(pnode->tensor().as_vector(),
1429 scalar_type(1) / pnode->children[1]->tensor()[0]);
1430 tree.clear_children(pnode);
1431 }
else if (child0->tensor_is_zero()) {
1433 pnode->node_type = GA_NODE_ZERO;
1434 tree.clear_children(pnode);
1435 }
else if (child1->node_type == GA_NODE_CONSTANT &&
1436 child1->tensor().size() == 1 &&
1437 child1->tensor()[0] == scalar_type(1)) {
1438 tree.replace_node_by_child(pnode, 0);
1443 default:GMM_ASSERT1(
false,
"Unexpected operation. Internal error.");
1447 case GA_NODE_C_MATRIX:
1449 if (!all_sc) ga_throw_error(pnode->expr, pnode->pos,
1450 "Constant vector/matrix/tensor " 1451 "components should be scalar valued.");
1452 GMM_ASSERT1(pnode->children.size() == pnode->tensor_proper_size(),
1455 pnode->test_function_type = 0;
1456 for (
size_type i = 0; i < pnode->children.size(); ++i) {
1457 if (pnode->children[i]->test_function_type) {
1458 if (pnode->test_function_type == 0) {
1459 pnode->test_function_type=pnode->children[i]->test_function_type;
1460 pnode->name_test1 = pnode->children[i]->name_test1;
1461 pnode->name_test2 = pnode->children[i]->name_test2;
1462 pnode->interpolate_name_test1
1463 = pnode->children[i]->interpolate_name_test1;
1464 pnode->interpolate_name_test2
1465 = pnode->children[i]->interpolate_name_test2;
1466 pnode->qdim1 = pnode->children[i]->qdim1;
1467 pnode->qdim2 = pnode->children[i]->qdim2;
1469 if (pnode->test_function_type !=
1470 pnode->children[i]->test_function_type ||
1471 pnode->name_test1.compare(pnode->children[i]->name_test1) ||
1472 pnode->name_test2.compare(pnode->children[i]->name_test2) ||
1473 pnode->interpolate_name_test1.compare
1474 (pnode->children[i]->interpolate_name_test1) ||
1475 pnode->interpolate_name_test2.compare
1476 (pnode->children[i]->interpolate_name_test2))
1477 ga_throw_error(pnode->expr, pnode->pos,
"Inconsistent use of " 1478 "test function in constant matrix.");
1482 int to_add = int(pnode->nb_test_functions() + pnode->nbc1)
1483 -
int(pnode->tensor().sizes().size());
1484 GMM_ASSERT1(to_add >= 0 && to_add <=2,
"Internal error");
1486 mi = pnode->tensor().sizes();
1487 mi.resize(pnode->nbc1+pnode->nb_test_functions());
1488 for (
int i =
int(mi.size()-1); i >= to_add; --i)
1489 mi[i] = mi[i-to_add];
1490 for (
int i = 0; i < to_add; ++i) mi[i] = 2;
1491 pnode->tensor().adjust_sizes(mi);
1495 bool all_zero =
true;
1496 for (
size_type i = 0; i < pnode->children.size(); ++i) {
1497 pnode->tensor()[i] = pnode->children[i]->tensor()[0];
1498 if (pnode->tensor()[i] != scalar_type(0)) all_zero =
false;
1501 pnode->node_type = GA_NODE_ZERO;
1503 pnode->node_type = GA_NODE_CONSTANT;
1504 tree.clear_children(pnode);
1512 std::string name = pnode->name;
1514 if (!ignore_X && !(name.compare(
"X"))) {
1515 pnode->node_type = GA_NODE_X;
1517 pnode->init_vector_tensor(meshdim);
1520 if (!(name.compare(
"Diff"))) {
1521 pnode->test_function_type = 0;
1524 if (!(name.compare(
"Grad"))) {
1525 pnode->test_function_type = 0;
1528 if (!(name.compare(
"element_size"))) {
1529 pnode->node_type = GA_NODE_ELT_SIZE;
1530 pnode->init_scalar_tensor(0);
1533 if (!(name.compare(
"element_K"))) {
1534 pnode->node_type = GA_NODE_ELT_K;
1535 if (ref_elt_dim == 1)
1536 pnode->init_vector_tensor(meshdim);
1538 pnode->init_matrix_tensor(meshdim, ref_elt_dim);
1541 if (!(name.compare(
"element_B"))) {
1542 pnode->node_type = GA_NODE_ELT_B;
1543 pnode->init_matrix_tensor(ref_elt_dim, meshdim);
1546 if (!(name.compare(
"Normal"))) {
1547 pnode->node_type = GA_NODE_NORMAL;
1548 pnode->init_vector_tensor(meshdim);
1551 if (!(name.compare(
"Reshape"))) {
1552 pnode->node_type = GA_NODE_RESHAPE;
1553 pnode->init_scalar_tensor(0);
1556 if (!(name.compare(
"Swap_indices"))) {
1557 pnode->node_type = GA_NODE_SWAP_IND;
1558 pnode->init_scalar_tensor(0);
1561 if (!(name.compare(
"Index_move_last"))) {
1562 pnode->node_type = GA_NODE_IND_MOVE_LAST;
1563 pnode->init_scalar_tensor(0);
1566 if (!(name.compare(
"Contract"))) {
1567 pnode->node_type = GA_NODE_CONTRACT;
1568 pnode->init_scalar_tensor(0);
1572 if (name.compare(0, 11,
"Derivative_") == 0) {
1573 name = name.substr(11);
1575 pnode->der1 = 1; pnode->der2 = 0;
1577 size_type d = strtol(name.c_str(), &p, 10);
1581 if (name[s] !=
'_') valid =
false;
else 1582 name = name.substr(s+1);
1584 d = strtol(name.c_str(), &p, 10);
1585 s = p - name.c_str();
1588 if (name[s] !=
'_') valid =
false;
else 1589 name = name.substr(s+1);
1591 if (!valid || pnode->der1 == 0)
1592 ga_throw_error(pnode->expr, pnode->pos,
"Invalid derivative format");
1595 ga_predef_function_tab::const_iterator it=PREDEF_FUNCTIONS.find(name);
1596 if (it != PREDEF_FUNCTIONS.end()) {
1598 pnode->node_type = GA_NODE_PREDEF_FUNC;
1600 pnode->test_function_type = 0;
1602 if (pnode->der1 > it->second.nbargs()
1603 || pnode->der2 > it->second.nbargs())
1604 ga_throw_error(pnode->expr, pnode->pos,
"Invalid derivative.");
1605 const ga_predef_function &F = it->second;
1606 if ((F.ftype() == 0 || F.dtype() == 2) && !(pnode->der2)) {
1607 pnode->name = ((pnode->der1 == 1) ?
1608 F.derivative1() : F.derivative2());
1609 pnode->der1 = pnode->der2 = 0;
1612 }
else if (SPEC_FUNCTIONS.find(name) != SPEC_FUNCTIONS.end()) {
1615 ga_throw_error(pnode->expr, pnode->pos,
"Special functions do not " 1616 "support derivatives.");
1617 pnode->node_type = GA_NODE_SPEC_FUNC;
1619 pnode->test_function_type = 0;
1620 if (!name.compare(
"pi")) {
1621 pnode->node_type = GA_NODE_CONSTANT;
1622 pnode->init_scalar_tensor(M_PI);
1623 }
else if (!name.compare(
"meshdim")) {
1624 pnode->node_type = GA_NODE_CONSTANT;
1625 pnode->init_scalar_tensor(scalar_type(meshdim));
1626 }
else if (!name.compare(
"timestep")) {
1627 pnode->node_type = GA_NODE_CONSTANT;
1628 pnode->init_scalar_tensor(scalar_type(workspace.get_time_step()));
1630 }
else if (PREDEF_OPERATORS.tab.find(name)
1631 != PREDEF_OPERATORS.tab.end()) {
1633 pnode->node_type = GA_NODE_OPERATOR;
1635 pnode->test_function_type = 0;
1640 size_type prefix_id = ga_parse_prefix_operator(name);
1641 size_type test = ga_parse_prefix_test(name);
1643 if (!(workspace.variable_exists(name)))
1644 ga_throw_error(pnode->expr, pnode->pos,
"Unknown variable, " 1645 "function, operator or data \"" + name +
"\"");
1648 ga_throw_error(pnode->expr, pnode->pos,
"Derivative is for " 1649 "functions or operators, not for variables. " 1650 "Use Grad instead.");
1653 const mesh_fem *mf = workspace.associated_mf(name);
1654 const im_data *imd = workspace.associated_im_data(name);
1656 if (test && workspace.is_constant(name) &&
1657 !(workspace.is_disabled_variable(name)))
1658 ga_throw_error(pnode->expr, pnode->pos,
"Test functions of " 1659 "constants are not allowed.");
1661 pnode->name_test1 = name;
1662 pnode->interpolate_name_test1 =
"";
1664 workspace.test1.insert
1665 (var_trans_pair(pnode->name_test1,
1666 pnode->interpolate_name_test1));
1667 pnode->qdim1 = mf ? workspace.qdim(name)
1668 : gmm::vect_size(workspace.value(name));
1669 if (!(pnode->qdim1))
1670 ga_throw_error(pnode->expr, pnode->pos,
1671 "Invalid null size of variable");
1672 }
else if (test == 2) {
1673 pnode->name_test2 = name;
1674 pnode->interpolate_name_test2 =
"";
1676 workspace.test2.insert
1677 (var_trans_pair(pnode->name_test2,
1678 pnode->interpolate_name_test2));
1679 pnode->qdim2 = mf ? workspace.qdim(name)
1680 : gmm::vect_size(workspace.value(name));
1681 if (!(pnode->qdim2))
1682 ga_throw_error(pnode->expr, pnode->pos,
1683 "Invalid null size of variable");
1686 if (!mf && (test || !imd)) {
1688 ga_throw_error(pnode->expr, pnode->pos,
"Gradient, Hessian or " 1689 "Divergence cannot be evaluated for fixed size data.");
1691 pnode->node_type = GA_NODE_VAL_TEST;
1692 else if (eval_fixed_size)
1693 pnode->node_type = GA_NODE_CONSTANT;
1695 pnode->node_type = GA_NODE_VAL;
1697 size_type n = gmm::vect_size(workspace.value(name));
1700 pnode->init_vector_tensor(1);
1701 pnode->tensor()[0]=scalar_type(1);
1703 else pnode->init_scalar_tensor(workspace.value(name)[0]);
1706 pnode->init_matrix_tensor(n,n);
1709 pnode->tensor()(i,j)
1710 = ((i == j) ? scalar_type(1) : scalar_type(0));
1712 pnode->t.adjust_sizes(workspace.qdims(name));
1713 gmm::copy(workspace.value(name), pnode->tensor().as_vector());
1716 }
else if (!test && imd) {
1718 ga_throw_error(pnode->expr, pnode->pos,
"Gradient, Hessian or " 1719 "Divergence cannot be evaluated for im data.");
1720 pnode->node_type = GA_NODE_VAL;
1721 pnode->t.adjust_sizes(workspace.qdims(name));
1725 bgeot::multi_index mii = workspace.qdims(name);
1727 if (!q) ga_throw_error(pnode->expr, pnode->pos,
1728 "Invalid null size of variable " << name);
1730 ga_throw_error(pnode->expr, pnode->pos,
1731 "Tensor with too much dimensions. Limited to 6");
1733 switch (prefix_id) {
1735 pnode->node_type = test ? GA_NODE_VAL_TEST : GA_NODE_VAL;
1738 if (test && q == 1 && mii.size() <= 1) {
1742 mii.insert(mii.begin(), 2);
1743 pnode->t.adjust_sizes(mii);
1747 pnode->node_type = test ? GA_NODE_GRAD_TEST : GA_NODE_GRAD;
1749 if (q == 1 && mii.size() <= 1) {
1753 mii.insert(mii.begin(), 2);
1756 if (mii.size() == 1 && mii[0] == 1) mii[0] = n;
1757 else mii.push_back(n);
1761 pnode->node_type = test ? GA_NODE_HESS_TEST : GA_NODE_HESS;
1763 if (q == 1 && mii.size() <= 1) {
1767 mii.insert(mii.begin(), 2);
1770 if (mii.size() == 1 && mii[0] == 1) mii[0] = n;
1771 else mii.push_back(n);
1776 pnode->node_type = test ? GA_NODE_DIVERG_TEST : GA_NODE_DIVERG;
1778 ga_throw_error(pnode->expr, pnode->pos,
1779 "Divergence operator can only be applied to" 1780 "Fields with qdim (" << q <<
") equal to dim (" 1783 mii[0] = test ? 2 : 1;
1786 pnode->t.adjust_sizes(mii);
1788 pnode->test_function_type = test;
1793 case GA_NODE_PARAMS:
1796 if (child0->node_type == GA_NODE_NAME) {
1797 if (child0->name.compare(
"Grad") == 0) {
1798 if (pnode->children.size() != 2)
1799 ga_throw_error(pnode->expr, child0->pos,
1800 "Bad number of parameters for Grad operator");
1801 if (ga_node_mark_tree_for_grad(child1)) {
1802 ga_node_grad(tree, workspace, me, child1);
1803 ga_node_analysis(tree, workspace, pnode->children[1], me,
1804 ref_elt_dim, eval_fixed_size, ignore_X, option);
1805 child1 = pnode->children[1];
1807 mi = child1->t.sizes(); mi.push_back(me.dim());
1808 child1->t.adjust_sizes(mi);
1809 child1->node_type = GA_NODE_ZERO;
1811 tree.clear_children(child1);
1813 tree.replace_node_by_child(pnode, 1);
1815 }
else if (child0->name.compare(
"Diff") == 0) {
1817 if (pnode->children.size() != 3 && pnode->children.size() != 4)
1818 ga_throw_error(pnode->expr, child0->pos,
1819 "Bad number of parameters for Diff operator");
1820 pga_tree_node child2 = pnode->children[2];
1821 if (child2->node_type != GA_NODE_VAL)
1822 ga_throw_error(pnode->expr, child2->pos,
"Second parameter of " 1823 "Diff operator has to be a variable name");
1824 std::string vardiff = child2->name;
1825 size_type order = child1->test_function_type;
1827 ga_throw_error(pnode->expr, child2->pos,
"Cannot derive further " 1828 "this order two expression");
1830 if (ga_node_mark_tree_for_variable(child1,workspace,me,vardiff,
"")) {
1831 ga_node_derivation(tree, workspace, me, child1, vardiff,
"",order+1);
1832 child1 = pnode->children[1];
1833 ga_node_analysis(tree, workspace, child1, me, ref_elt_dim,
1834 eval_fixed_size, ignore_X, option);
1835 child1 = pnode->children[1];
1837 mi = child1->t.sizes(); mi.insert(mi.begin(), 2);
1838 child1->t.adjust_sizes(mi);
1839 child1->node_type = GA_NODE_ZERO;
1840 child1->test_function_type = order ? 3 : 1;
1842 tree.clear_children(child1);
1844 if (pnode->children.size() == 4) {
1845 ga_tree grad_expr, hess_expr;
1846 ga_node_expand_expression_in_place_of_test
1847 (tree, workspace, pnode->children[1], vardiff, pnode->children[3],
1848 grad_expr, hess_expr, order+1, me, ref_elt_dim, eval_fixed_size,
1850 ga_node_analysis(tree, workspace, pnode->children[1], me,
1851 ref_elt_dim, eval_fixed_size, ignore_X, option);
1853 tree.replace_node_by_child(pnode, 1);
1856 ga_throw_error(pnode->expr, child0->pos,
"Unknown special operator");
1860 else if (child0->node_type == GA_NODE_X) {
1861 child0->init_scalar_tensor(0);
1862 if (pnode->children.size() != 2)
1863 ga_throw_error(pnode->expr, child1->pos,
1864 "X stands for the coordinates on " 1865 "the real elements. It accepts only one index.");
1866 if (!(child1->node_type == GA_NODE_CONSTANT) ||
1867 child1->tensor().size() != 1)
1868 ga_throw_error(pnode->expr, child1->pos,
1869 "Index for X has to be constant and of size 1.");
1870 child0->nbc1 =
size_type(round(child1->tensor()[0]));
1871 if (child0->nbc1 == 0 || child0->nbc1 > meshdim)
1872 ga_throw_error(pnode->expr, child1->pos,
"Index for X not convenient. " 1873 "Found " << child0->nbc1 <<
" with meshdim = " 1875 tree.replace_node_by_child(pnode, 0);
1880 else if (child0->node_type == GA_NODE_RESHAPE) {
1881 if (pnode->children.size() < 3)
1882 ga_throw_error(pnode->expr, child1->pos,
1883 "Not enough parameters for Reshape");
1884 if (pnode->children.size() > 12)
1885 ga_throw_error(pnode->expr, child1->pos,
1886 "Too many parameters for Reshape");
1887 pnode->t = child1->t;
1888 pnode->test_function_type = child1->test_function_type;
1889 pnode->name_test1 = child1->name_test1;
1890 pnode->name_test2 = child1->name_test2;
1891 pnode->interpolate_name_test1 = child1->interpolate_name_test1;
1892 pnode->interpolate_name_test2 = child1->interpolate_name_test2;
1893 pnode->qdim1 = child1->qdim1;
1894 pnode->qdim2 = child1->qdim2;
1896 for (
size_type i = 0; i < pnode->nb_test_functions(); ++i)
1897 mi.push_back(size1[i]);
1899 for (
size_type i = 2; i < pnode->children.size(); ++i) {
1900 if (pnode->children[i]->node_type != GA_NODE_CONSTANT)
1901 ga_throw_error(pnode->expr, pnode->children[i]->pos,
"Reshape sizes " 1902 "should be constant positive integers.");
1903 mi.push_back(
size_type(round(pnode->children[i]->tensor()[0])));
1905 ga_throw_error(pnode->expr, pnode->children[i]->pos,
1906 "Wrong zero size for Reshape.");
1909 for (
size_type i = pnode->nb_test_functions(); i < mi.size(); ++i)
1910 total_size *= mi[i];
1911 if (total_size != pnode->tensor_proper_size())
1912 ga_throw_error(pnode->expr, pnode->pos,
"Invalid sizes for reshape, " 1913 "found a total of " << total_size <<
" should be " <<
1914 pnode->tensor_proper_size() <<
".");
1915 pnode->t.adjust_sizes(mi);
1917 if (child1->node_type == GA_NODE_CONSTANT) {
1918 pnode->node_type = GA_NODE_CONSTANT;
1919 tree.clear_children(pnode);
1920 }
else if (child1->node_type == GA_NODE_ZERO) {
1921 pnode->node_type = GA_NODE_ZERO;
1922 tree.clear_children(pnode);
1927 else if (child0->node_type == GA_NODE_SWAP_IND) {
1928 if (pnode->children.size() != 4)
1929 ga_throw_error(pnode->expr, child1->pos,
1930 "Wrong number of parameters for Swap_indices");
1931 pnode->t = child1->t;
1932 pnode->test_function_type = child1->test_function_type;
1933 pnode->name_test1 = child1->name_test1;
1934 pnode->name_test2 = child1->name_test2;
1935 pnode->interpolate_name_test1 = child1->interpolate_name_test1;
1936 pnode->interpolate_name_test2 = child1->interpolate_name_test2;
1937 pnode->qdim1 = child1->qdim1;
1938 pnode->qdim2 = child1->qdim2;
1942 if (pnode->children[i]->node_type != GA_NODE_CONSTANT ||
1943 pnode->children[i]->tensor().size() != 1)
1944 ga_throw_error(pnode->expr, pnode->children[i]->pos,
"Indices " 1945 "for swap should be constant positive integers.");
1946 ind[i] =
size_type(round(pnode->children[i]->tensor()[0]));
1947 if (ind[i] < 1 || ind[i] > child1->tensor_proper_size())
1948 ga_throw_error(pnode->expr, pnode->children[i]->pos,
"Index " 1949 "out of range for Swap_indices.");
1952 if (ind[2] == ind[3]) {
1953 tree.replace_node_by_child(pnode, 1);
1956 mi = pnode->tensor().sizes();
1957 size_type nbtf = child1->nb_test_functions();
1958 std::swap(mi[ind[2]+nbtf], mi[ind[3]+nbtf]);
1959 pnode->t.adjust_sizes(mi);
1961 if (child1->node_type == GA_NODE_CONSTANT) {
1962 pnode->node_type = GA_NODE_CONSTANT;
1963 if (ind[2] > ind[3]) std::swap(ind[2], ind[3]);
1965 for (
size_type i = 0; i < child1->tensor_order(); ++i) {
1966 if (i<ind[2]) ii1 *= child1->tensor_proper_size(i);
1967 if (i>ind[2] && i<ind[3]) ii2 *= child1->tensor_proper_size(i);
1968 if (i>ind[3]) ii3 *= child1->tensor_proper_size(i);
1970 size_type nn1 = child1->tensor_proper_size(ind[2]);
1971 size_type nn2 = child1->tensor_proper_size(ind[3]);
1972 auto it = pnode->tensor().begin();
1977 for (
size_type m = 0; m < ii1; ++m, ++it)
1978 *it = child0->tensor()[m+j*ii1+k*ii1*nn1+l*ii1*nn1*ii2+
1980 tree.clear_children(pnode);
1981 }
else if (child1->node_type == GA_NODE_ZERO) {
1982 pnode->node_type = GA_NODE_ZERO;
1983 tree.clear_children(pnode);
1989 else if (child0->node_type == GA_NODE_IND_MOVE_LAST) {
1990 if (pnode->children.size() != 3)
1991 ga_throw_error(pnode->expr, child1->pos,
1992 "Wrong number of parameters for Index_move_last");
1993 pnode->t = child1->t;
1994 pnode->test_function_type = child1->test_function_type;
1995 pnode->name_test1 = child1->name_test1;
1996 pnode->name_test2 = child1->name_test2;
1997 pnode->interpolate_name_test1 = child1->interpolate_name_test1;
1998 pnode->interpolate_name_test2 = child1->interpolate_name_test2;
1999 pnode->qdim1 = child1->qdim1;
2000 pnode->qdim2 = child1->qdim2;
2003 if (pnode->children[2]->node_type != GA_NODE_CONSTANT ||
2004 pnode->children[2]->tensor().size() != 1)
2005 ga_throw_error(pnode->expr, pnode->children[2]->pos,
"Index for " 2006 "Index_move_last should be constant positive integers.");
2007 ind =
size_type(round(pnode->children[2]->tensor()[0]));
2008 if (ind < 1 || ind > child1->tensor_proper_size())
2009 ga_throw_error(pnode->expr, pnode->children[2]->pos,
"Index " 2010 "out of range for Index_move_last.");
2012 if (ind == child1->tensor_order()) {
2013 tree.replace_node_by_child(pnode, 1);
2016 mi = pnode->tensor().sizes();
2017 size_type nbtf = child1->nb_test_functions();
2018 for (
size_type i = ind; i < child1->tensor_order(); ++i)
2019 std::swap(mi[i-1+nbtf], mi[i+nbtf]);
2020 pnode->t.adjust_sizes(mi);
2022 if (child1->node_type == GA_NODE_CONSTANT) {
2023 pnode->node_type = GA_NODE_CONSTANT;
2026 for (
size_type i = 0; i < child1->tensor_order(); ++i) {
2027 if (i<ind) ii1 *= child1->tensor_proper_size(i);
2028 if (i>ind) ii2 *= child1->tensor_proper_size(i);
2030 size_type nn = child1->tensor_proper_size(ind);
2031 auto it = pnode->tensor().begin();
2034 for (
size_type k = 0; k < ii1; ++k, ++it)
2035 *it = child0->tensor()[k+i*ii1+j*ii1*nn];
2036 tree.clear_children(pnode);
2037 }
else if (child1->node_type == GA_NODE_ZERO) {
2038 pnode->node_type = GA_NODE_ZERO;
2039 tree.clear_children(pnode);
2045 else if (child0->node_type == GA_NODE_CONTRACT) {
2046 std::vector<size_type> ind(2), indsize(2);
2047 if (pnode->children.size() == 4)
2048 { ind[0] = 2; ind[1] = 3; }
2049 else if (pnode->children.size() == 5)
2050 { ind[0] = 2; ind[1] = 4; }
2051 else if (pnode->children.size() == 7) {
2052 ind.resize(4); indsize.resize(4);
2053 ind[0] = 2; ind[1] = 3; ind[2] = 5; ind[3] = 6;
2057 for (
size_type i = 1; i < pnode->children.size(); ++i) {
2059 if (pnode->children[i]->node_type != GA_NODE_CONSTANT ||
2060 pnode->children[i]->tensor().size() != 1)
2061 ga_throw_error(pnode->children[i]->expr, pnode->children[i]->pos,
2062 "Invalid parameter for Contract. " 2063 "Should be an index number.");
2064 ind[kk] =
size_type(round(pnode->children[i]->tensor()[0]));
2065 order = pnode->children[ll]->tensor_order();
2066 if (ind[kk] < 1 || ind[kk] > order)
2067 ga_throw_error(pnode->children[i]->expr, pnode->children[i]->pos,
2068 "Parameter out of range for Contract (should be " 2069 "between 1 and " << order <<
")");
2071 indsize[kk] = pnode->children[ll]->tensor_proper_size(ind[kk]);
2072 if (kk >= ind.size()/2 && indsize[kk] != indsize[kk-ind.size()/2])
2073 ga_throw_error(child0->expr, child0->pos,
2074 "Invalid parameters for Contract. Cannot " 2075 "contract on indices of different sizes");
2080 if (pnode->children.size() == 4) {
2082 pnode->test_function_type = child1->test_function_type;
2083 pnode->name_test1 = child1->name_test1;
2084 pnode->name_test2 = child1->name_test2;
2085 pnode->interpolate_name_test1 = child1->interpolate_name_test1;
2086 pnode->interpolate_name_test2 = child1->interpolate_name_test2;
2087 pnode->qdim1 = child1->qdim1;
2088 pnode->qdim2 = child1->qdim2;
2092 ga_throw_error(child0->expr, child0->pos,
2093 "Invalid parameters for Contract. Repeated index.");
2096 for (
size_type i = 0; i < pnode->nb_test_functions(); ++i)
2097 mi.push_back(size1[i]);
2099 if (i != i1 && i != i2)
2100 mi.push_back(child1->tensor_proper_size(i));
2101 pnode->t.adjust_sizes(mi);
2103 if (child1->node_type == GA_NODE_CONSTANT) {
2105 if (i1 > i2) std::swap(i1, i2);
2109 if (i < i1) ii1 *= child1->tensor_proper_size(i);
2110 if (i > i1 && i < i2) ii2 *= child1->tensor_proper_size(i);
2111 if (i > i2) ii3 *= child1->tensor_proper_size(i);
2114 auto it = pnode->tensor().begin();
2117 for (
size_type k = 0; k < ii1; ++k, ++it) {
2118 *it = scalar_type(0);
2119 size_type pre_ind = k+j*ii1*nn+i*ii1*nn*ii2*nn;
2121 *it += child1->tensor()[pre_ind+n*ii1+n*ii1*nn*ii2];
2124 pnode->node_type = GA_NODE_CONSTANT;
2125 tree.clear_children(pnode);
2126 }
else if (child1->node_type == GA_NODE_ZERO) {
2127 pnode->node_type = GA_NODE_ZERO;
2128 tree.clear_children(pnode);
2131 }
else if (pnode->children.size() == 5) {
2133 pga_tree_node child2 = pnode->children[3];
2134 pnode->mult_test(child1, child2);
2137 mi = pnode->tensor().sizes();
2139 if (i != i1) mi.push_back(child1->tensor_proper_size(i));
2141 if (i != i2) mi.push_back(child2->tensor_proper_size(i));
2142 pnode->t.adjust_sizes(mi);
2144 if (child1->node_type == GA_NODE_CONSTANT &&
2145 child2->node_type == GA_NODE_CONSTANT) {
2146 size_type ii1 = 1, ii2 = 1, ii3 = 1, ii4 = 1;
2149 if (i < i1) ii1 *= child1->tensor_proper_size(i);
2150 if (i > i1) ii2 *= child1->tensor_proper_size(i);
2153 if (i < i2) ii3 *= child2->tensor_proper_size(i);
2154 if (i > i2) ii4 *= child2->tensor_proper_size(i);
2157 auto it = pnode->tensor().begin();
2161 for (
size_type l = 0; l < ii1; ++l, ++it) {
2162 *it = scalar_type(0);
2164 *it += child1->tensor()[l+n*ii1+k*ii1*nn]
2165 * child2->tensor()[j+n*ii3+i*ii3*nn];
2168 }
else if (child1->tensor_is_zero() || child2->tensor_is_zero()) {
2169 pnode->node_type = GA_NODE_ZERO;
2170 tree.clear_children(pnode);
2173 }
else if (pnode->children.size() == 7) {
2175 pga_tree_node child2 = pnode->children[4];
2176 pnode->mult_test(child1, child2);
2177 if (ind[0] == ind[1] || ind[2] == ind[3])
2178 ga_throw_error(child0->expr, child0->pos,
2179 "Invalid parameters for Contract. Repeated index.");
2181 size_type i1 = ind[0], i2 = ind[1], i3 = ind[2], i4 = ind[3];
2182 mi = pnode->tensor().sizes();
2184 if (i != i1 && i != i2) mi.push_back(child1->tensor_proper_size(i));
2186 if (i != i3 && i != i4) mi.push_back(child2->tensor_proper_size(i));
2187 pnode->t.adjust_sizes(mi);
2189 if (child1->tensor_is_zero() || child2->tensor_is_zero()) {
2190 pnode->node_type = GA_NODE_ZERO;
2191 tree.clear_children(pnode);
2192 }
else if (child1->node_type == GA_NODE_CONSTANT &&
2193 child2->node_type == GA_NODE_CONSTANT) {
2194 size_type nn1 = indsize[0], nn2 = indsize[1];
2196 { std::swap(i1, i2); std::swap(i3, i4); std::swap(nn1, nn2); }
2198 size_type ii1 = 1, ii2 = 1, ii3 = 1, ii4 = 1, ii5 = 1, ii6 = 1;
2200 if (i < i1) ii1 *= child1->tensor_proper_size(i);
2201 if (i > i1 && i < i2) ii2 *= child1->tensor_proper_size(i);
2202 if (i > i2) ii3 *= child1->tensor_proper_size(i);
2205 if (i < i3 && i < i4) ii4 *= child2->tensor_proper_size(i);
2206 if ((i > i3 && i < i4) || (i > i4 && i < i3))
2207 ii5 *= child2->tensor_proper_size(i);
2208 if (i > i3 && i > i4) ii6 *= child2->tensor_proper_size(i);
2211 auto it = pnode->tensor().begin();
2213 if (i3 < i4) std::swap(m1, m2);
2219 for (
size_type p = 0; p < ii1; ++p, ++it) {
2220 *it = scalar_type(0);
2221 size_type q1 = p+m*ii1*nn1+l*ii1*nn1*ii2*nn2;
2222 size_type q2 = k+j*ii4*nn1+i*ii4*nn1*ii5*nn2;
2225 *it += child1->tensor()[q1+n1*ii1+n2*ii1*nn1*ii2]
2226 * child2->tensor()[q2+n1*m1+n2*m2];
2230 ga_throw_error(pnode->expr, child1->pos,
2231 "Wrong number of parameters for Contract");
2235 else if (child0->node_type == GA_NODE_PREDEF_FUNC) {
2237 for (
size_type i = 1; i < pnode->children.size(); ++i)
2238 ga_valid_operand(pnode->children[i]);
2239 std::string name = child0->name;
2240 ga_predef_function_tab::const_iterator it = PREDEF_FUNCTIONS.find(name);
2241 const ga_predef_function &F = it->second;
2243 if (nbargs+1 != pnode->children.size()) {
2244 ga_throw_error(pnode->expr, pnode->pos,
"Bad number of arguments " 2245 "for predefined function " << name <<
". Found " 2246 << pnode->children.size()-1 <<
", should be "<<nbargs <<
".");
2248 pnode->test_function_type = 0;
2249 pga_tree_node child2 = (nbargs == 2) ? pnode->children[2] : child1;
2250 all_cte = child1->node_type == GA_NODE_CONSTANT;
2252 all_cte = all_cte && (child2->node_type == GA_NODE_CONSTANT);
2253 if (child1->test_function_type || child2->test_function_type)
2254 ga_throw_error(pnode->expr, pnode->pos,
"Test functions cannot be " 2255 "passed as argument of a predefined function.");
2260 size_type s2 = (nbargs == 2) ? child2->tensor().size() : s1;
2261 if (s1 != s2 && (s1 != 1 || s2 != 1))
2262 ga_throw_error(pnode->expr, pnode->pos,
2263 "Invalid argument size for a scalar function. " 2264 "Size of first argument: " << s1 <<
2265 ". Size of second argument: " << s2 <<
".");
2268 pnode->t = child1->t;
2271 pnode->t = child1->t;
2272 }
else if (s1 == 1) {
2273 pnode->t = child2->t;
2275 pnode->t = child1->t;
2281 GMM_ASSERT1(
false,
"Sorry, to be done");
2282 pnode->node_type = GA_NODE_CONSTANT;
2285 pnode->tensor()[i] = F(child1->tensor()[i]);
2289 pnode->tensor()[i] = F(child1->tensor()[i],
2290 child2->tensor()[i]);
2291 }
else if (s1 == 1) {
2293 pnode->tensor()[i] = F(child1->tensor()[0],
2294 child2->tensor()[i]);
2297 pnode->tensor()[i] = F(child1->tensor()[i],
2298 child2->tensor()[0]);
2301 tree.clear_children(pnode);
2306 else if (child0->node_type == GA_NODE_SPEC_FUNC) {
2308 for (
size_type i = 1; i < pnode->children.size(); ++i)
2309 ga_valid_operand(pnode->children[i]);
2310 if (pnode->children.size() != 2)
2311 ga_throw_error(pnode->expr, pnode->pos,
2312 "One and only one argument is allowed for function " 2315 if (!(child0->name.compare(
"qdim"))) {
2316 if (child1->node_type != GA_NODE_VAL)
2317 ga_throw_error(pnode->expr, pnode->pos,
"The argument of qdim " 2318 "function can only be a variable name.");
2319 pnode->node_type = GA_NODE_CONSTANT;
2320 pnode->init_scalar_tensor(scalar_type(workspace.qdim(child1->name)));
2321 if (pnode->tensor()[0] <= 0)
2322 ga_throw_error(pnode->expr, pnode->pos,
2323 "Invalid null size of variable");
2324 }
else if (!(child0->name.compare(
"qdims"))) {
2325 if (child1->node_type != GA_NODE_VAL)
2326 ga_throw_error(pnode->expr, pnode->pos,
"The argument of qdim " 2327 "function can only be a variable name.");
2328 pnode->node_type = GA_NODE_CONSTANT;
2329 bgeot::multi_index mii = workspace.qdims(child1->name);
2331 ga_throw_error(pnode->expr, pnode->pos,
2332 "Tensor with too much dimensions. Limited to 6");
2333 if (mii.size() == 0 || scalar_type(mii[0]) <= 0)
2334 ga_throw_error(pnode->expr, pnode->pos,
2335 "Invalid null size of variable");
2336 if (mii.size() == 1)
2337 pnode->init_scalar_tensor(scalar_type(mii[0]));
2338 if (mii.size() >= 1) {
2339 pnode->init_vector_tensor(mii.size());
2340 for (
size_type i = 0; i < mii.size(); ++i)
2341 pnode->tensor()[i] = scalar_type(mii[i]);
2343 }
else if (!(child0->name.compare(
"Id"))) {
2344 bool valid = (child1->node_type == GA_NODE_CONSTANT);
2345 int n = valid ? int(round(child1->tensor()[0])) : -1;
2346 if (n <= 0 || n > 100 || child1->tensor_order() > 0)
2347 ga_throw_error(pnode->expr, pnode->pos,
"The argument of Id " 2348 "should be a (small) positive integer.");
2349 pnode->node_type = GA_NODE_CONSTANT;
2351 pnode->init_scalar_tensor(scalar_type(1));
2353 pnode->init_matrix_tensor(n,n);
2355 for (
int i = 0; i < n; ++i) pnode->tensor()(i,i) = scalar_type(1);
2357 }
else ga_throw_error(pnode->expr, pnode->children[0]->pos,
2358 "Unknown special function.");
2359 tree.clear_children(pnode);
2363 else if (child0->node_type == GA_NODE_OPERATOR) {
2365 for (
size_type i = 1; i < pnode->children.size(); ++i)
2366 ga_valid_operand(pnode->children[i]);
2368 ga_nonlinear_operator::arg_list args;
2369 for (
size_type i = 1; i < pnode->children.size(); ++i) {
2371 && (pnode->children[i]->node_type == GA_NODE_CONSTANT);
2372 args.push_back(&(pnode->children[i]->tensor()));
2373 if (pnode->children[i]->node_type == GA_NODE_ALLINDICES)
2374 ga_throw_error(pnode->expr, pnode->children[i]->pos,
2375 "Colon operator is not allowed in nonlinear " 2377 if (pnode->children[i]->test_function_type)
2378 ga_throw_error(pnode->expr, pnode->pos,
"Test functions cannot be " 2379 "passed as argument of a nonlinear operator.");
2380 if (pnode->children[i]->tensor_order() > 2)
2381 ga_throw_error(pnode->expr, pnode->pos,
2382 "Sorry, arguments to nonlinear operators should " 2383 "only be scalar, vector or matrices");
2385 ga_predef_operator_tab::T::const_iterator it
2386 = PREDEF_OPERATORS.tab.find(child0->name);
2387 const ga_nonlinear_operator &OP = *(it->second);
2389 if (!(OP.result_size(args, mi)))
2390 ga_throw_error(pnode->expr, pnode->pos,
2391 "Wrong number or wrong size of arguments for the " 2392 "call of nonlinear operator " + child0->name);
2394 pnode->test_function_type = 0;
2396 if (child0->der1 > args.size() || child0->der2 > args.size())
2397 ga_throw_error(pnode->expr, child0->pos,
2398 "Invalid derivative number for nonlinear operator " 2401 if (child0->der1 && child0->der2 == 0) {
2402 for (
size_type i = 0; i < args[child0->der1-1]->sizes().size(); ++i)
2403 mi.push_back(args[child0->der1-1]->sizes()[i]);
2404 pnode->t.adjust_sizes(mi);
2406 pnode->node_type = GA_NODE_CONSTANT;
2407 OP.derivative(args, child0->der1, pnode->tensor());
2408 tree.clear_children(pnode);
2410 }
else if (child0->der1 && child0->der2) {
2411 for (
size_type i = 0; i < args[child0->der1-1]->sizes().size(); ++i)
2412 mi.push_back(args[child0->der1-1]->sizes()[i]);
2413 for (
size_type i = 0; i < args[child0->der2-1]->sizes().size(); ++i)
2414 mi.push_back(args[child0->der2-1]->sizes()[i]);
2415 pnode->t.adjust_sizes(mi);
2417 pnode->node_type = GA_NODE_CONSTANT;
2418 OP.second_derivative(args, child0->der1, child0->der2,
2420 tree.clear_children(pnode);
2423 pnode->t.adjust_sizes(mi);
2425 pnode->node_type = GA_NODE_CONSTANT;
2426 OP.value(args, pnode->tensor());
2427 tree.clear_children(pnode);
2434 all_cte = (child0->node_type == GA_NODE_CONSTANT);
2435 if (pnode->children.size() != child0->tensor_order() + 1)
2436 ga_throw_error(pnode->expr, pnode->pos,
"Bad number of indices.");
2437 for (
size_type i = 1; i < pnode->children.size(); ++i)
2438 if (pnode->children[i]->node_type != GA_NODE_ALLINDICES &&
2439 (pnode->children[i]->node_type != GA_NODE_CONSTANT ||
2440 pnode->children[i]->tensor().size() != 1))
2441 ga_throw_error(pnode->expr, pnode->children[i]->pos,
2442 "Indices should be constant integers or colon.");
2444 bgeot::multi_index mi1(size0.size()), mi2, indices;
2445 for (
size_type i = 0; i < child0->tensor_order(); ++i) {
2446 if (pnode->children[i+1]->node_type == GA_NODE_ALLINDICES) {
2447 mi2.push_back(child0->tensor_proper_size(i));
2448 indices.push_back(i);
2451 mi1[i] =
size_type(round(pnode->children[i+1]->tensor()[0])-1);
2452 if (mi1[i] >= child0->tensor_proper_size(i))
2453 ga_throw_error(pnode->expr, pnode->children[i+1]->pos,
2454 "Index out of range, " << mi1[i]+1
2455 <<
". Should be between 1 and " 2456 << child0->tensor_proper_size(i) <<
".");
2460 for (
size_type i = 0; i < child0->nb_test_functions(); ++i)
2461 mi.push_back(child0->t.sizes()[i]);
2462 for (
size_type i = 0; i < mi2.size(); ++i) mi.push_back(mi2[i]);
2463 pnode->t.adjust_sizes(mi);
2464 pnode->test_function_type = child0->test_function_type;
2465 pnode->name_test1 = child0->name_test1;
2466 pnode->name_test2 = child0->name_test2;
2467 pnode->interpolate_name_test1 = child0->interpolate_name_test1;
2468 pnode->interpolate_name_test2 = child0->interpolate_name_test2;
2469 pnode->qdim1 = child0->qdim1;
2470 pnode->qdim2 = child0->qdim2;
2472 if (child0->tensor_is_zero()) {
2474 pnode->node_type = GA_NODE_ZERO;
2475 tree.clear_children(pnode);
2476 }
else if (all_cte) {
2477 pnode->node_type = GA_NODE_CONSTANT;
2478 for (bgeot::multi_index mi3(mi2.size()); !mi3.finished(mi2);
2479 mi3.incrementation(mi2)) {
2480 for (
size_type j = 0; j < mi2.size(); ++j) {
2481 mi1[indices[j]] = mi3[j];
2483 pnode->tensor()(mi3) = pnode->children[0]->tensor()(mi1);
2485 tree.clear_children(pnode);
2490 default:GMM_ASSERT1(
false,
"Unexpected node type " << pnode->node_type
2491 <<
" in semantic analysis. Internal error.");
2494 pnode->hash_value = ga_hash_code(pnode);
2497 for (
size_type i = 0; i < pnode->children.size(); ++i) {
2498 pnode->hash_value += (pnode->children[i]->hash_value)
2499 * 1.0101 * (pnode->symmetric_op ? scalar_type(1) : scalar_type(i+1));
2505 void ga_semantic_analysis(ga_tree &tree,
2506 const ga_workspace &workspace,
2509 bool eval_fixed_size,
2510 bool ignore_X,
int option) {
2511 GMM_ASSERT1(predef_operators_nonlinear_elasticity_initialized &&
2512 predef_operators_plasticity_initialized &&
2513 predef_operators_contact_initialized,
"Internal error");
2514 if (!(tree.root))
return;
2515 if (option == 1) { workspace.test1.clear(); workspace.test2.clear(); }
2516 ga_node_analysis(tree, workspace, tree.root, m, ref_elt_dim,
2517 eval_fixed_size, ignore_X, option);
2518 if (tree.root && option == 2) {
2519 if (((tree.root->test_function_type & 1) &&
2520 (tree.root->name_test1.compare(workspace.selected_test1.varname)
2521 || tree.root->interpolate_name_test1.compare
2522 (workspace.selected_test1.transname)))
2524 ((tree.root->test_function_type & 2) &&
2525 (tree.root->name_test2.compare(workspace.selected_test2.varname)
2526 || tree.root->interpolate_name_test2.compare
2527 (workspace.selected_test2.transname))))
2530 ga_valid_operand(tree.root);
2534 void ga_extract_factor(ga_tree &result_tree, pga_tree_node pnode,
2535 pga_tree_node &new_pnode) {
2536 result_tree.clear();
2537 result_tree.copy_node(pnode, 0, result_tree.root);
2538 new_pnode = result_tree.root;
2540 bool minus_sign =
false;
2542 pga_tree_node pnode_child = pnode;
2543 pnode = pnode->parent;
2547 size_type nbch = pnode->children.size();
2548 pga_tree_node child0 = (nbch > 0) ? pnode->children[0] : 0;
2549 pga_tree_node child1 = (nbch > 1) ? pnode->children[1] : 0;
2551 switch (pnode->node_type) {
2554 switch(pnode->op_type) {
2559 if (child1 == pnode_child) minus_sign = !(minus_sign);
2562 case GA_UNARY_MINUS:
case GA_QUOTE:
case GA_SYM:
case GA_SKEW:
2563 case GA_TRACE:
case GA_DEVIATOR:
case GA_PRINT:
2565 result_tree.insert_node(result_tree.root, pnode->node_type);
2566 result_tree.root->op_type = pnode->op_type;
2567 result_tree.root->pos = pnode->pos;
2568 result_tree.root->expr = pnode->expr;
2570 case GA_DOT:
case GA_MULT:
case GA_COLON:
case GA_TMULT:
2571 case GA_DOTMULT:
case GA_DIV:
case GA_DOTDIV:
2573 result_tree.insert_node(result_tree.root, pnode->node_type);
2574 result_tree.root->op_type = pnode->op_type;
2575 result_tree.root->pos = pnode->pos;
2576 result_tree.root->expr = pnode->expr;
2577 result_tree.root->children.resize(2,
nullptr);
2578 if (child0 == pnode_child) {
2579 result_tree.copy_node(child1, result_tree.root,
2580 result_tree.root->children[1]);
2581 }
else if (child1 == pnode_child) {
2582 std::swap(result_tree.root->children[1],
2583 result_tree.root->children[0]);
2584 result_tree.copy_node(child0, result_tree.root,
2585 result_tree.root->children[0]);
2586 }
else GMM_ASSERT1(
false,
"Corrupted tree");
2588 default: GMM_ASSERT1(
false,
"Unexpected operation. Internal error.");
2592 case GA_NODE_PARAMS:
2593 if (child0->node_type == GA_NODE_RESHAPE) {
2594 GMM_ASSERT1(child1 == pnode_child,
"Cannot extract a factor of a " 2595 "Reshape size parameter");
2597 result_tree.insert_node(result_tree.root, pnode->node_type);
2598 result_tree.root->pos = pnode->pos;
2599 result_tree.root->expr = pnode->expr;
2600 result_tree.root->children.resize(pnode->children.size(),
nullptr);
2601 std::swap(result_tree.root->children[1],
2602 result_tree.root->children[0]);
2603 for (
size_type i = 0; i < pnode->children.size(); ++i)
2605 result_tree.copy_node(pnode->children[i], result_tree.root,
2606 result_tree.root->children[i]);
2607 }
else if (child0->node_type == GA_NODE_SWAP_IND) {
2608 GMM_ASSERT1(child1 == pnode_child,
"Cannot extract a factor of a " 2609 "Swap_indices size parameter");
2611 result_tree.insert_node(result_tree.root, pnode->node_type);
2612 result_tree.root->pos = pnode->pos;
2613 result_tree.root->expr = pnode->expr;
2614 result_tree.root->children.resize(pnode->children.size(),
nullptr);
2615 for (
size_type i = 0; i < pnode->children.size(); ++i)
2616 if (pnode->children[i] == pnode_child)
2617 std::swap(result_tree.root->children[i],
2618 result_tree.root->children[0]);
2619 for (
size_type i = 0; i < pnode->children.size(); ++i)
2620 if (pnode->children[i] != pnode_child)
2621 result_tree.copy_node(pnode->children[i], result_tree.root,
2622 result_tree.root->children[i]);
2623 }
else if (child0->node_type == GA_NODE_IND_MOVE_LAST) {
2624 GMM_ASSERT1(child1 == pnode_child,
"Cannot extract a factor of a " 2625 "Index_move_last size parameter");
2627 result_tree.insert_node(result_tree.root, pnode->node_type);
2628 result_tree.root->pos = pnode->pos;
2629 result_tree.root->expr = pnode->expr;
2630 result_tree.root->children.resize(pnode->children.size(),
nullptr);
2631 for (
size_type i = 0; i < pnode->children.size(); ++i)
2632 if (pnode->children[i] == pnode_child)
2633 std::swap(result_tree.root->children[i],
2634 result_tree.root->children[0]);
2635 for (
size_type i = 0; i < pnode->children.size(); ++i)
2636 if (pnode->children[i] != pnode_child)
2637 result_tree.copy_node(pnode->children[i], result_tree.root,
2638 result_tree.root->children[i]);
2639 }
else if (child0->node_type == GA_NODE_CONTRACT) {
2641 result_tree.insert_node(result_tree.root, pnode->node_type);
2642 result_tree.root->pos = pnode->pos;
2643 result_tree.root->expr = pnode->expr;
2644 result_tree.root->children.resize(pnode->children.size(),
nullptr);
2645 for (
size_type i = 0; i < pnode->children.size(); ++i)
2646 if (pnode->children[i] == pnode_child)
2647 std::swap(result_tree.root->children[i],
2648 result_tree.root->children[0]);
2649 for (
size_type i = 0; i < pnode->children.size(); ++i)
2650 if (pnode->children[i] != pnode_child)
2651 result_tree.copy_node(pnode->children[i], result_tree.root,
2652 result_tree.root->children[i]);
2654 GMM_ASSERT1(
false,
"Cannot extract a factor which is a parameter " 2655 "of a nonlinear operator/function");
2658 case GA_NODE_C_MATRIX:
2659 result_tree.insert_node(result_tree.root, pnode->node_type);
2660 result_tree.root->pos = pnode->pos;
2661 result_tree.root->expr = pnode->expr;
2662 result_tree.root->children.resize(pnode->children.size());
2663 for (
size_type i = 0; i < pnode->children.size(); ++i)
2664 if (pnode_child == pnode->children[i]) {
2665 result_tree.root->children[i] = result_tree.root->children[0];
2666 result_tree.root->children[0] = 0;
2669 for (
size_type i = 0; i < pnode->children.size(); ++i) {
2670 if (pnode_child == pnode->children[i]) {
2672 =
new ga_tree_node(GA_NODE_ZERO, pnode->pos, pnode->expr);
2673 pnode->children[i]->init_scalar_tensor(scalar_type(0));
2674 pnode->children[i]->parent = pnode;
2679 default: GMM_ASSERT1(
false,
"Unexpected node type " << pnode->node_type
2680 <<
" in extract constant term. Internal error.");
2683 pnode_child = pnode;
2684 pnode = pnode->parent;
2688 result_tree.insert_node(result_tree.root, GA_NODE_OP);
2689 result_tree.root->op_type = GA_UNARY_MINUS;
2690 result_tree.root->pos = pnode->children[0]->pos;
2691 result_tree.root->expr = pnode->children[0]->expr;
2695 bool ga_node_extract_constant_term
2696 (ga_tree &tree, pga_tree_node pnode,
const ga_workspace &workspace,
2698 bool is_constant =
true;
2699 size_type nbch = pnode->children.size();
2700 pga_tree_node child0 = (nbch > 0) ? pnode->children[0] : 0;
2702 bool child_0_is_constant = (nbch <= 0) ?
true :
2703 ga_node_extract_constant_term(tree, pnode->children[0], workspace, m);
2704 bool child_1_is_constant = (nbch <= 1) ?
true :
2705 ga_node_extract_constant_term(tree, pnode->children[1], workspace, m);
2707 switch (pnode->node_type) {
2708 case GA_NODE_ZERO: is_constant =
false;
break;
2710 case GA_NODE_ELEMENTARY_VAL_TEST:
case GA_NODE_ELEMENTARY_GRAD_TEST:
2711 case GA_NODE_ELEMENTARY_HESS_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
2712 case GA_NODE_XFEM_PLUS_VAL_TEST:
case GA_NODE_XFEM_PLUS_GRAD_TEST:
2713 case GA_NODE_XFEM_PLUS_HESS_TEST:
case GA_NODE_XFEM_PLUS_DIVERG_TEST:
2714 case GA_NODE_XFEM_MINUS_VAL_TEST:
case GA_NODE_XFEM_MINUS_GRAD_TEST:
2715 case GA_NODE_XFEM_MINUS_HESS_TEST:
case GA_NODE_XFEM_MINUS_DIVERG_TEST:
2716 case GA_NODE_VAL_TEST:
case GA_NODE_GRAD_TEST:
case GA_NODE_PREDEF_FUNC:
2717 case GA_NODE_HESS_TEST:
case GA_NODE_DIVERG_TEST:
case GA_NODE_RESHAPE:
2718 case GA_NODE_SWAP_IND:
case GA_NODE_IND_MOVE_LAST:
case GA_NODE_CONTRACT:
2719 case GA_NODE_ELT_SIZE:
case GA_NODE_ELT_K:
case GA_NODE_ELT_B:
2720 case GA_NODE_CONSTANT:
case GA_NODE_X:
case GA_NODE_NORMAL:
2721 case GA_NODE_OPERATOR:
2722 is_constant =
true;
break;
2724 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
2725 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
2726 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
2727 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
2728 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
2729 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
2730 case GA_NODE_VAL:
case GA_NODE_GRAD:
case GA_NODE_HESS:
2731 case GA_NODE_DIVERG:
2732 is_constant = workspace.is_constant(pnode->name);
2735 case GA_NODE_INTERPOLATE_VAL:
2736 case GA_NODE_INTERPOLATE_GRAD:
2737 case GA_NODE_INTERPOLATE_HESS:
2738 case GA_NODE_INTERPOLATE_DIVERG:
2740 if (!(workspace.is_constant(pnode->name))) {
2741 is_constant =
false;
break;
2743 std::set<var_trans_pair> vars;
2744 workspace.interpolate_transformation(pnode->interpolate_name)
2745 ->extract_variables(workspace, vars,
true, m,
2746 pnode->interpolate_name);
2747 for (
const var_trans_pair &var : vars) {
2748 if (!(workspace.is_constant(var.varname)))
2749 { is_constant =
false;
break; }
2754 case GA_NODE_INTERPOLATE_FILTER:
2755 if (!child_0_is_constant) { is_constant =
false;
break; }
2757 case GA_NODE_INTERPOLATE_VAL_TEST:
2758 case GA_NODE_INTERPOLATE_GRAD_TEST:
2759 case GA_NODE_INTERPOLATE_DIVERG_TEST:
2760 case GA_NODE_INTERPOLATE_HESS_TEST:
2761 case GA_NODE_INTERPOLATE_X:
2762 case GA_NODE_INTERPOLATE_NORMAL:
2763 case GA_NODE_INTERPOLATE_DERIVATIVE:
2765 std::set<var_trans_pair> vars;
2766 workspace.interpolate_transformation(pnode->interpolate_name)
2767 ->extract_variables(workspace, vars,
true, m,
2768 pnode->interpolate_name);
2769 for (
const var_trans_pair &var : vars) {
2770 if (!(workspace.is_constant(var.varname)))
2771 { is_constant =
false;
break; }
2777 switch(pnode->op_type) {
2778 case GA_PLUS:
case GA_MINUS:
2779 if (!child_0_is_constant && !child_1_is_constant)
2780 { is_constant =
false;
break; }
2783 case GA_UNARY_MINUS:
case GA_QUOTE:
case GA_SYM:
case GA_SKEW:
2784 case GA_TRACE:
case GA_DEVIATOR:
case GA_PRINT:
2785 is_constant = child_0_is_constant;
2788 case GA_DOT:
case GA_MULT:
case GA_COLON:
case GA_TMULT:
2789 case GA_DOTMULT:
case GA_DIV:
case GA_DOTDIV:
2790 is_constant = (child_0_is_constant && child_1_is_constant);
2793 default: GMM_ASSERT1(
false,
"Unexpected operation. Internal error.");
2797 case GA_NODE_C_MATRIX:
2798 for (
size_type i = 0; i < pnode->children.size(); ++i) {
2799 if (!(ga_node_extract_constant_term(tree, pnode->children[i],
2801 { is_constant =
false;
break; }
2805 case GA_NODE_PARAMS:
2806 if (child0->node_type == GA_NODE_RESHAPE ||
2807 child0->node_type == GA_NODE_SWAP_IND ||
2808 child0->node_type == GA_NODE_IND_MOVE_LAST) {
2809 is_constant = child_1_is_constant;
2810 }
else if (child0->node_type == GA_NODE_CONTRACT) {
2811 for (
size_type i = 1; i < pnode->children.size(); ++i) {
2812 if (!(ga_node_extract_constant_term(tree, pnode->children[i],
2814 { is_constant =
false;
break; }
2816 }
else if (child0->node_type == GA_NODE_PREDEF_FUNC) {
2817 for (
size_type i = 1; i < pnode->children.size(); ++i) {
2818 if (!(ga_node_extract_constant_term(tree, pnode->children[i],
2820 { is_constant =
false;
break; }
2822 }
else if (child0->node_type == GA_NODE_SPEC_FUNC) {
2823 GMM_ASSERT1(
false,
"internal error");
2824 }
else if (child0->node_type == GA_NODE_OPERATOR) {
2825 for (
size_type i = 1; i < pnode->children.size(); ++i) {
2826 if (!(ga_node_extract_constant_term(tree, pnode->children[i],
2828 { is_constant =
false;
break; }
2831 is_constant = child_0_is_constant;
2835 default: GMM_ASSERT1(
false,
"Unexpected node type " << pnode->node_type
2836 <<
" in extract constant term. Internal error.");
2840 pnode->node_type = GA_NODE_ZERO;
2841 tree.clear_children(pnode);
2851 static std::string ga_extract_one_Neumann_term
2852 (
const std::string &varname,
2853 ga_workspace &workspace, pga_tree_node pnode) {
2855 const mesh_fem *mf = workspace.associated_mf(varname);
2856 GMM_ASSERT1(mf,
"Works only with fem variables.");
2857 size_type meshdim = mf->linked_mesh().dim();
2859 pga_tree_node new_pnode =
nullptr;
2860 ga_extract_factor(factor, pnode, new_pnode);
2862 pga_tree_node nnew_pnode = new_pnode;
2864 int cas = new_pnode->node_type == GA_NODE_GRAD_TEST ? 0 : 1;
2866 if (cas == 0 && new_pnode->parent &&
2867 new_pnode->parent->node_type == GA_NODE_OP &&
2868 new_pnode->parent->op_type == GA_TRACE) {
2869 cas = 2; nnew_pnode = new_pnode->parent;
2872 pga_tree_node colon_pnode =
nullptr;
2873 bool quote_before_colon =
false;
2881 while (nnew_pnode->parent) {
2882 pga_tree_node previous_node = nnew_pnode;
2883 nnew_pnode = nnew_pnode->parent;
2885 if (nnew_pnode->node_type == GA_NODE_OP &&
2886 nnew_pnode->op_type == GA_MULT &&
2887 nnew_pnode->children[0] == previous_node &&
2888 nnew_pnode->children[1]->tensor_proper_size() == 1) {
2889 }
else if (nnew_pnode->node_type == GA_NODE_OP &&
2890 nnew_pnode->op_type == GA_MULT &&
2891 nnew_pnode->children[1] == previous_node &&
2892 nnew_pnode->children[0]->tensor_proper_size() == 1) {
2894 }
else if (nnew_pnode->node_type == GA_NODE_OP &&
2895 nnew_pnode->op_type == GA_DIV &&
2896 nnew_pnode->children[0] == previous_node &&
2897 nnew_pnode->children[1]->tensor_proper_size() == 1) {
2899 }
else if (nnew_pnode->node_type == GA_NODE_OP &&
2900 nnew_pnode->op_type == GA_COLON &&
2901 nnew_pnode->children[0] == previous_node &&
2902 nnew_pnode->children[1]->tensor_order() == 2 &&
2903 colon_pnode == 0 && cas == 0) {
2904 std::swap(nnew_pnode->children[0], nnew_pnode->children[1]);
2905 colon_pnode = nnew_pnode;
2906 }
else if (nnew_pnode->node_type == GA_NODE_OP &&
2907 nnew_pnode->op_type == GA_COLON &&
2908 nnew_pnode->children[1] == previous_node &&
2909 nnew_pnode->children[0]->tensor_order() == 2 &&
2910 colon_pnode == 0 && cas == 0) {
2911 colon_pnode = nnew_pnode;
2912 }
else if (nnew_pnode->node_type == GA_NODE_OP &&
2913 nnew_pnode->op_type == GA_QUOTE &&
2914 colon_pnode == 0 && cas == 0 && !quote_before_colon) {
2915 quote_before_colon =
true;
2919 if (ok && cas == 0 && !colon_pnode) ok =
false;
2922 new_pnode->node_type = GA_NODE_NORMAL;
2923 result =
"(" + ga_tree_to_string(factor) +
")";
2927 new_pnode->node_type = GA_NODE_NORMAL;
2928 colon_pnode->op_type = GA_MULT;
2929 if (quote_before_colon) {
2930 factor.insert_node(colon_pnode->children[0], GA_NODE_OP);
2931 colon_pnode->children[0]->op_type = GA_QUOTE;
2932 nnew_pnode = new_pnode->parent;
2933 while(nnew_pnode->node_type != GA_NODE_OP ||
2934 nnew_pnode->op_type != GA_QUOTE)
2935 nnew_pnode = nnew_pnode->parent;
2936 factor.replace_node_by_child(nnew_pnode,0);
2940 new_pnode->node_type = GA_NODE_NORMAL;
2943 new_pnode->parent->node_type = GA_NODE_NORMAL;
2944 factor.clear_children(new_pnode->parent);
2947 result =
"(" + ga_tree_to_string(factor) +
")";
2953 bgeot::multi_index mi(2); mi[0] = N; mi[1] = meshdim;
2956 factor.clear_children(new_pnode);
2957 new_pnode->node_type = GA_NODE_C_MATRIX;
2958 new_pnode->t.adjust_sizes(mi);
2959 new_pnode->children.resize(N*meshdim);
2961 for (
size_type k = 0; k < meshdim; ++k) {
2963 pga_tree_node param_node = new_pnode->children[k*N+j]
2964 =
new ga_tree_node(GA_NODE_PARAMS, pnode->pos, pnode->expr);
2965 new_pnode->children[k+j*meshdim]->parent = new_pnode;
2966 param_node->children.resize(2);
2967 param_node->children[0]
2968 =
new ga_tree_node(GA_NODE_NORMAL, pnode->pos, pnode->expr);
2969 param_node->children[0]->parent = param_node;
2970 param_node->children[1]
2971 =
new ga_tree_node(GA_NODE_CONSTANT, pnode->pos, pnode->expr);
2972 param_node->children[1]->parent = param_node;
2973 param_node->children[1]->init_scalar_tensor(scalar_type(k));
2976 new_pnode->children[k+j*meshdim]
2977 =
new ga_tree_node(GA_NODE_ZERO, pnode->pos, pnode->expr);
2978 new_pnode->children[k+j*meshdim]
2979 ->init_scalar_tensor(scalar_type(0));
2980 new_pnode->children[k+j*meshdim]->parent = new_pnode;
2984 result +=
"(" + ga_tree_to_string(factor) +
")";
2985 if (i < N-1) result +=
";";
2988 GMM_TRACE2(
"Warning, generic Neumann term used: " << result);
2995 void ga_extract_Neumann_term
2996 (ga_tree &tree,
const std::string &varname,
2997 ga_workspace &workspace, pga_tree_node pnode, std::string &result) {
2999 for (
size_type i = 0; i < pnode->children.size(); ++i)
3000 ga_extract_Neumann_term(tree, varname, workspace,
3001 pnode->children[i], result);
3003 switch (pnode->node_type) {
3004 case GA_NODE_DIVERG_TEST:
case GA_NODE_GRAD_TEST:
3005 case GA_NODE_ELEMENTARY_GRAD_TEST:
case GA_NODE_ELEMENTARY_DIVERG_TEST:
3006 if (pnode->name.compare(varname) == 0) {
3007 if (result.size()) result +=
" + ";
3008 result += ga_extract_one_Neumann_term(varname, workspace, pnode);
3011 case GA_NODE_INTERPOLATE_GRAD_TEST:
case GA_NODE_INTERPOLATE_DIVERG_TEST:
3012 if (pnode->name.compare(varname) == 0)
3013 GMM_ASSERT1(
false,
"Do not know how to extract a " 3014 "Neumann term with an interpolate transformation");
3027 static void ga_node_derivation(ga_tree &tree,
const ga_workspace &workspace,
3029 pga_tree_node pnode,
3030 const std::string &varname,
3031 const std::string &interpolatename,
3034 size_type nbch = pnode->children.size();
3035 pga_tree_node child0 = (nbch > 0) ? pnode->children[0] : 0;
3036 pga_tree_node child1 = (nbch > 1) ? pnode->children[1] : 0;
3037 bool mark0 = ((nbch > 0) ? child0->marked :
false);
3038 bool mark1 = ((nbch > 1) ? child1->marked :
false);
3039 bgeot::multi_index mi;
3041 const ga_predef_function_tab &PREDEF_FUNCTIONS
3044 switch (pnode->node_type) {
3045 case GA_NODE_VAL:
case GA_NODE_GRAD:
3046 case GA_NODE_HESS:
case GA_NODE_DIVERG:
3047 mi.resize(1); mi[0] = 2;
3048 for (
size_type i = 0; i < pnode->tensor_order(); ++i)
3049 mi.push_back(pnode->tensor_proper_size(i));
3050 pnode->t.adjust_sizes(mi);
3051 if (pnode->node_type == GA_NODE_VAL)
3052 pnode->node_type = GA_NODE_VAL_TEST;
3053 else if (pnode->node_type == GA_NODE_GRAD)
3054 pnode->node_type = GA_NODE_GRAD_TEST;
3055 else if (pnode->node_type == GA_NODE_HESS)
3056 pnode->node_type = GA_NODE_HESS_TEST;
3057 else if (pnode->node_type == GA_NODE_DIVERG)
3058 pnode->node_type = GA_NODE_DIVERG_TEST;
3059 pnode->test_function_type = order;
3062 case GA_NODE_INTERPOLATE_VAL:
3063 case GA_NODE_INTERPOLATE_GRAD:
3064 case GA_NODE_INTERPOLATE_HESS:
3065 case GA_NODE_INTERPOLATE_DIVERG:
3067 bool is_val(pnode->node_type == GA_NODE_INTERPOLATE_VAL);
3068 bool is_grad(pnode->node_type == GA_NODE_INTERPOLATE_GRAD);
3069 bool is_hess(pnode->node_type == GA_NODE_INTERPOLATE_HESS);
3070 bool is_diverg(pnode->node_type == GA_NODE_INTERPOLATE_DIVERG);
3072 bool ivar = (pnode->name.compare(varname) == 0 &&
3073 pnode->interpolate_name.compare(interpolatename) == 0);
3074 bool itrans = !ivar;
3076 std::set<var_trans_pair> vars;
3077 workspace.interpolate_transformation(pnode->interpolate_name)
3078 ->extract_variables(workspace, vars,
true, m,
3079 pnode->interpolate_name);
3080 for (
const var_trans_pair &var : vars) {
3081 if (var.varname.compare(varname) == 0 &&
3082 var.transname.compare(interpolatename) == 0)
3087 pga_tree_node pnode_trans = pnode;
3089 GMM_ASSERT1(!itrans,
"Sorry, cannot derive a hessian once more");
3090 }
else if (itrans && ivar) {
3091 tree.duplicate_with_addition(pnode);
3092 pnode_trans = pnode->parent->children[1];
3096 mi.resize(1); mi[0] = 2;
3097 for (
size_type i = 0; i < pnode->tensor_order(); ++i)
3098 mi.push_back(pnode->tensor_proper_size(i));
3099 pnode->t.adjust_sizes(mi);
3101 pnode->node_type = GA_NODE_INTERPOLATE_VAL_TEST;
3103 pnode->node_type = GA_NODE_INTERPOLATE_GRAD_TEST;
3105 pnode->node_type = GA_NODE_INTERPOLATE_HESS_TEST;
3107 pnode->node_type = GA_NODE_INTERPOLATE_DIVERG_TEST;
3108 pnode->test_function_type = order;
3112 const mesh_fem *mf = workspace.associated_mf(pnode_trans->name);
3113 size_type q = workspace.qdim(pnode_trans->name);
3115 bgeot::multi_index mii = workspace.qdims(pnode_trans->name);
3118 pnode_trans->node_type = GA_NODE_INTERPOLATE_GRAD;
3119 else if (is_grad || is_diverg)
3120 pnode_trans->node_type = GA_NODE_INTERPOLATE_HESS;
3123 if (q == 1 && mii.size() <= 1) { mii.resize(1); mii[0] = n; }
3124 else mii.push_back(n);
3126 if (is_grad || is_diverg) mii.push_back(n);
3128 pnode_trans->t.adjust_sizes(mii);
3129 tree.duplicate_with_operation(pnode_trans,
3130 (n > 1) ? GA_DOT : GA_MULT);
3131 pga_tree_node pnode_der = pnode_trans->parent->children[1];
3132 pnode_der->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
3134 pnode_der->init_vector_tensor(2);
3136 pnode_der->init_matrix_tensor(2, n);
3137 pnode_der->test_function_type = order;
3138 pnode_der->name = varname;
3139 pnode_der->interpolate_name_der = pnode_der->interpolate_name;
3140 pnode_der->interpolate_name = interpolatename;
3143 tree.insert_node(pnode_trans->parent, GA_NODE_OP);
3144 pga_tree_node pnode_tr = pnode_trans->parent->parent;
3145 pnode_tr->op_type = GA_TRACE;
3146 pnode_tr->init_vector_tensor(2);
3155 case GA_NODE_INTERPOLATE_VAL_TEST:
3156 case GA_NODE_INTERPOLATE_GRAD_TEST:
3157 case GA_NODE_INTERPOLATE_DIVERG_TEST:
3159 bool is_val(pnode->node_type == GA_NODE_INTERPOLATE_VAL_TEST);
3160 bool is_grad(pnode->node_type == GA_NODE_INTERPOLATE_GRAD_TEST);
3161 bool is_diverg(pnode->node_type == GA_NODE_INTERPOLATE_DIVERG_TEST);
3163 pga_tree_node pnode_trans = pnode;
3164 const mesh_fem *mf = workspace.associated_mf(pnode_trans->name);
3165 size_type q = workspace.qdim(pnode_trans->name);
3167 bgeot::multi_index mii = workspace.qdims(pnode_trans->name);
3169 pnode_trans->node_type = GA_NODE_INTERPOLATE_GRAD_TEST;
3170 else if (is_grad || is_diverg)
3171 pnode_trans->node_type = GA_NODE_INTERPOLATE_HESS_TEST;
3173 if (q == 1 && mii.size() <= 1) { mii.resize(1); mii[0] = 2; }
3174 else mii.insert(mii.begin(), 2);
3178 if (is_grad || is_diverg) mii.push_back(n);
3180 pnode_trans->t.adjust_sizes(mii);
3182 tree.duplicate_with_operation(pnode_trans,
3183 (n > 1 ? GA_DOT : GA_MULT));
3184 pga_tree_node pnode_der = pnode_trans->parent->children[1];
3185 pnode_der->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
3187 pnode_der->init_vector_tensor(2);
3189 pnode_der->init_matrix_tensor(2, n);
3190 pnode_der->test_function_type = order;
3191 pnode_der->name = varname;
3192 pnode_der->interpolate_name_der = pnode_der->interpolate_name;
3193 pnode_der->interpolate_name = interpolatename;
3196 tree.insert_node(pnode_trans->parent, GA_NODE_OP);
3197 pga_tree_node pnode_tr = pnode_trans->parent->parent;
3198 pnode_tr->op_type = GA_TRACE;
3199 pnode_tr->init_vector_tensor(2);
3207 case GA_NODE_INTERPOLATE_HESS_TEST:
3208 GMM_ASSERT1(
false,
"Sorry, cannot derive a hessian once more");
3211 case GA_NODE_INTERPOLATE_X:
3214 pga_tree_node pnode_der = pnode;
3215 pnode_der->node_type = GA_NODE_INTERPOLATE_DERIVATIVE;
3217 pnode_der->init_vector_tensor(2);
3219 pnode_der->init_matrix_tensor(2, n);
3220 pnode_der->test_function_type = order;
3221 pnode_der->name = varname;
3222 pnode_der->interpolate_name_der = pnode_der->interpolate_name;
3223 pnode_der->interpolate_name = interpolatename;
3227 case GA_NODE_INTERPOLATE_NORMAL:
3228 GMM_ASSERT1(
false,
"Sorry, cannot derive the interpolated Normal");
3231 case GA_NODE_INTERPOLATE_DERIVATIVE:
3232 GMM_ASSERT1(
false,
"Sorry, second order transformation derivative " 3233 "not taken into account");
3236 case GA_NODE_INTERPOLATE_FILTER:
3237 ga_node_derivation(tree, workspace, m, child0, varname,
3238 interpolatename, order);
3241 case GA_NODE_ELEMENTARY_VAL:
3242 case GA_NODE_ELEMENTARY_GRAD:
3243 case GA_NODE_ELEMENTARY_HESS:
3244 case GA_NODE_ELEMENTARY_DIVERG:
3245 case GA_NODE_XFEM_PLUS_VAL:
3246 case GA_NODE_XFEM_PLUS_GRAD:
3247 case GA_NODE_XFEM_PLUS_HESS:
3248 case GA_NODE_XFEM_PLUS_DIVERG:
3249 case GA_NODE_XFEM_MINUS_VAL:
3250 case GA_NODE_XFEM_MINUS_GRAD:
3251 case GA_NODE_XFEM_MINUS_HESS:
3252 case GA_NODE_XFEM_MINUS_DIVERG:
3253 mi.resize(1); mi[0] = 2;
3254 for (
size_type i = 0; i < pnode->tensor_order(); ++i)
3255 mi.push_back(pnode->tensor_proper_size(i));
3256 pnode->t.adjust_sizes(mi);
3257 switch(pnode->node_type) {
3258 case GA_NODE_ELEMENTARY_VAL:
3259 pnode->node_type = GA_NODE_ELEMENTARY_VAL_TEST;
break;
3260 case GA_NODE_ELEMENTARY_GRAD:
3261 pnode->node_type = GA_NODE_ELEMENTARY_GRAD_TEST;
break;
3262 case GA_NODE_ELEMENTARY_HESS:
3263 pnode->node_type = GA_NODE_ELEMENTARY_HESS_TEST;
break;
3264 case GA_NODE_ELEMENTARY_DIVERG:
3265 pnode->node_type = GA_NODE_ELEMENTARY_DIVERG_TEST;
break;
3266 case GA_NODE_XFEM_PLUS_VAL:
3267 pnode->node_type = GA_NODE_XFEM_PLUS_VAL_TEST;
break;
3268 case GA_NODE_XFEM_PLUS_GRAD:
3269 pnode->node_type = GA_NODE_XFEM_PLUS_GRAD_TEST;
break;
3270 case GA_NODE_XFEM_PLUS_HESS:
3271 pnode->node_type = GA_NODE_XFEM_PLUS_HESS_TEST;
break;
3272 case GA_NODE_XFEM_PLUS_DIVERG:
3273 pnode->node_type = GA_NODE_XFEM_PLUS_DIVERG_TEST;
break;
3274 case GA_NODE_XFEM_MINUS_VAL:
3275 pnode->node_type = GA_NODE_XFEM_MINUS_VAL_TEST;
break;
3276 case GA_NODE_XFEM_MINUS_GRAD:
3277 pnode->node_type = GA_NODE_XFEM_MINUS_GRAD_TEST;
break;
3278 case GA_NODE_XFEM_MINUS_HESS:
3279 pnode->node_type = GA_NODE_XFEM_MINUS_HESS_TEST;
break;
3280 case GA_NODE_XFEM_MINUS_DIVERG:
3281 pnode->node_type = GA_NODE_XFEM_MINUS_DIVERG_TEST;
break;
3282 default : GMM_ASSERT1(
false,
"internal error");
3284 pnode->test_function_type = order;
3288 switch(pnode->op_type) {
3289 case GA_PLUS:
case GA_MINUS:
3290 if (mark0 && mark1) {
3291 ga_node_derivation(tree, workspace, m, child0, varname,
3292 interpolatename, order);
3293 ga_node_derivation(tree, workspace, m, child1, varname,
3294 interpolatename, order);
3296 ga_node_derivation(tree, workspace, m, child0, varname,
3297 interpolatename, order);
3298 tree.replace_node_by_child(pnode, 0);
3300 ga_node_derivation(tree, workspace, m, child1, varname,
3301 interpolatename, order);
3302 if (pnode->op_type == GA_MINUS) {
3303 pnode->op_type = GA_UNARY_MINUS;
3304 tree.clear_node(child0);
3307 tree.replace_node_by_child(pnode, 1);
3311 case GA_UNARY_MINUS:
case GA_QUOTE:
case GA_SYM:
case GA_SKEW:
3312 case GA_TRACE:
case GA_DEVIATOR:
case GA_PRINT:
3313 ga_node_derivation(tree, workspace, m, child0, varname,
3314 interpolatename, order);
3317 case GA_DOT:
case GA_MULT:
case GA_COLON:
case GA_TMULT:
3319 if (mark0 && mark1) {
3320 if (sub_tree_are_equal(child0, child1, workspace, 0) &&
3321 (pnode->op_type != GA_MULT || child0->tensor_order() < 2) &&
3322 (pnode->op_type != GA_DOT || child0->tensor_order() < 2)) {
3323 ga_node_derivation(tree, workspace, m, child1, varname,
3324 interpolatename, order);
3325 tree.insert_node(pnode, GA_NODE_OP);
3326 pnode->parent->op_type = GA_MULT;
3327 tree.add_child(pnode->parent);
3328 pnode->parent->children[1]->node_type = GA_NODE_CONSTANT;
3329 pnode->parent->children[1]->init_scalar_tensor(scalar_type(2));
3331 tree.duplicate_with_addition(pnode);
3332 if ((pnode->op_type == GA_COLON && child0->tensor_order() == 2) ||
3333 (pnode->op_type == GA_DOT && child0->tensor_order() == 1 &&
3334 child1->tensor_order() == 1) ||
3335 pnode->op_type == GA_DOTMULT ||
3336 (child0->tensor_proper_size()== 1 &&
3337 child1->tensor_proper_size()== 1))
3338 std::swap(pnode->children[0], pnode->children[1]);
3339 ga_node_derivation(tree, workspace, m, child0, varname,
3340 interpolatename, order);
3341 ga_node_derivation(tree, workspace, m,
3342 pnode->parent->children[1]->children[1],
3343 varname, interpolatename, order);
3346 ga_node_derivation(tree, workspace, m, child0, varname,
3347 interpolatename, order);
3349 ga_node_derivation(tree, workspace, m, child1, varname,
3350 interpolatename, order);
3353 case GA_DIV:
case GA_DOTDIV:
3355 if (pnode->children[0]->node_type == GA_NODE_CONSTANT)
3356 gmm::scale(pnode->children[0]->tensor().as_vector(),
3360 tree.duplicate_with_substraction(pnode);
3361 ga_node_derivation(tree, workspace, m, child0, varname,
3362 interpolatename, order);
3363 pnode = pnode->parent->children[1];
3365 tree.insert_node(pnode, GA_NODE_OP);
3366 pnode->parent->op_type = GA_UNARY_MINUS;
3369 tree.insert_node(pnode->children[1], GA_NODE_PARAMS);
3370 pga_tree_node pnode_param = pnode->children[1];
3371 tree.add_child(pnode_param);
3372 std::swap(pnode_param->children[0], pnode_param->children[1]);
3373 pnode_param->children[0]->node_type = GA_NODE_PREDEF_FUNC;
3374 pnode_param->children[0]->name =
"sqr";
3375 tree.insert_node(pnode, GA_NODE_OP);
3376 pga_tree_node pnode_mult = pnode->parent;
3377 if (pnode->op_type == GA_DOTDIV)
3378 pnode_mult->op_type = GA_DOTMULT;
3380 pnode_mult->op_type = GA_MULT;
3381 pnode_mult->children.resize(2,
nullptr);
3382 tree.copy_node(pnode_param->children[1],
3383 pnode_mult, pnode_mult->children[1]);
3384 ga_node_derivation(tree, workspace, m, pnode_mult->children[1],
3385 varname, interpolatename, order);
3387 ga_node_derivation(tree, workspace, m, child0, varname,
3388 interpolatename, order);
3392 default: GMM_ASSERT1(
false,
"Unexpected operation. Internal error.");
3396 case GA_NODE_C_MATRIX:
3397 for (
size_type i = 0; i < pnode->children.size(); ++i) {
3398 if (pnode->children[i]->marked)
3399 ga_node_derivation(tree, workspace, m, pnode->children[i],
3400 varname, interpolatename, order);
3402 pnode->children[i]->init_scalar_tensor(scalar_type(0));
3403 pnode->children[i]->node_type = GA_NODE_ZERO;
3404 tree.clear_children(pnode->children[i]);
3409 case GA_NODE_PARAMS:
3410 if (child0->node_type == GA_NODE_RESHAPE ||
3411 child0->node_type == GA_NODE_SWAP_IND||
3412 child0->node_type == GA_NODE_IND_MOVE_LAST) {
3413 ga_node_derivation(tree, workspace, m, pnode->children[1],
3414 varname, interpolatename, order);
3415 }
else if (child0->node_type == GA_NODE_CONTRACT) {
3417 if (pnode->children.size() == 4) {
3418 ga_node_derivation(tree, workspace, m, pnode->children[1],
3419 varname, interpolatename, order);
3420 }
else if (pnode->children.size() == 5 || pnode->children.size() == 7) {
3421 size_type n2 = (pnode->children.size()==5) ? 3 : 4;
3422 pga_tree_node child2 = pnode->children[n2];
3424 if (mark1 && child2->marked) {
3425 tree.duplicate_with_addition(pnode);
3426 ga_node_derivation(tree, workspace, m, child1, varname,
3427 interpolatename, order);
3428 ga_node_derivation(tree, workspace, m,
3429 pnode->parent->children[1]->children[n2],
3430 varname, interpolatename, order);
3432 ga_node_derivation(tree, workspace, m, child1, varname,
3433 interpolatename, order);
3435 ga_node_derivation(tree, workspace, m, child2, varname,
3436 interpolatename, order);
3438 }
else GMM_ASSERT1(
false,
"internal error");
3439 }
else if (child0->node_type == GA_NODE_PREDEF_FUNC) {
3440 std::string name = child0->name;
3441 ga_predef_function_tab::const_iterator it = PREDEF_FUNCTIONS.find(name);
3442 const ga_predef_function &F = it->second;
3444 if (F.nbargs() == 1) {
3445 switch (F.dtype()) {
3447 GMM_ASSERT1(
false,
"Cannot derive function " << child0->name
3448 <<
". No derivative provided or not derivable function.");
3450 child0->name = F.derivative1();
3454 child0->name =
"DER_PDFUNC_" + child0->name;
3455 if (!(ga_function_exists(child0->name))) {
3457 ga_define_function(child0->name, 1, F.derivative1());
3459 std::string expr=ga_derivative_scalar_function(F.expr(),
"t");
3460 ga_define_function(child0->name, 1, expr);
3465 ga_predef_function_tab::const_iterator
3466 itp = PREDEF_FUNCTIONS.find(child0->name);
3467 const ga_predef_function &Fp = itp->second;
3468 if (Fp.is_affine(
"t")) {
3469 scalar_type b = Fp(scalar_type(0));
3470 scalar_type a = Fp(scalar_type(1)) - b;
3471 pnode->node_type = GA_NODE_OP;
3472 pnode->op_type = GA_MULT;
3473 child0->init_scalar_tensor(a);
3474 child0->node_type = ((a == scalar_type(0)) ?
3475 GA_NODE_ZERO : GA_NODE_CONSTANT);
3476 if (b != scalar_type(0)) {
3477 tree.insert_node(pnode, GA_NODE_OP);
3478 pnode->parent->op_type = (b > 0) ? GA_PLUS : GA_MINUS;
3479 tree.add_child(pnode->parent);
3480 pga_tree_node pnode_cte = pnode->parent->children[1];
3481 pnode_cte->node_type = GA_NODE_CONSTANT;
3482 pnode_cte->t = pnode->t;
3483 std::fill(pnode_cte->tensor().begin(),
3484 pnode_cte->tensor().end(), gmm::abs(b));
3485 pnode = pnode->parent;
3491 if (pnode->children.size() >= 2) {
3492 tree.insert_node(pnode, GA_NODE_OP);
3493 pga_tree_node pnode_op = pnode->parent;
3494 if (child1->tensor_order() == 0)
3495 pnode_op->op_type = GA_MULT;
3497 pnode_op->op_type = GA_DOTMULT;
3498 pnode_op->children.resize(2,
nullptr);
3499 tree.copy_node(child1, pnode_op, pnode_op->children[1]);
3500 ga_node_derivation(tree, workspace, m, pnode_op->children[1],
3501 varname, interpolatename, order);
3504 pga_tree_node child2 = pnode->children[2];
3505 pga_tree_node pg2 = pnode;
3507 if (child1->marked && child2->marked) {
3508 tree.duplicate_with_addition(pnode);
3509 pg2 = pnode->parent->children[1];
3512 if (child1->marked) {
3513 switch (F.dtype()) {
3515 GMM_ASSERT1(
false,
"Cannot derive function " << child0->name
3516 <<
". No derivative provided");
3518 child0->name = F.derivative1();
3521 child0->name =
"DER_PDFUNC1_" + child0->name;
3522 if (!(ga_function_exists(child0->name)))
3523 ga_define_function(child0->name, 2, F.derivative1());
3526 child0->name =
"DER_PDFUNC1_" + child0->name;
3527 if (!(ga_function_exists(child0->name))) {
3528 std::string expr = ga_derivative_scalar_function(F.expr(),
"t");
3529 ga_define_function(child0->name, 2, expr);
3533 tree.insert_node(pnode, GA_NODE_OP);
3534 pga_tree_node pnode_op = pnode->parent;
3535 if (child1->tensor_order() == 0)
3536 pnode_op->op_type = GA_MULT;
3538 pnode_op->op_type = GA_DOTMULT;
3539 pnode_op->children.resize(2,
nullptr);
3540 tree.copy_node(child1, pnode_op, pnode_op->children[1]);
3541 ga_node_derivation(tree, workspace, m, pnode_op->children[1],
3542 varname, interpolatename, order);
3544 if (child2->marked) {
3546 child0 = pnode->children[0]; child1 = pnode->children[1];
3547 child2 = pnode->children[2];
3549 switch (F.dtype()) {
3551 GMM_ASSERT1(
false,
"Cannot derive function " << child0->name
3552 <<
". No derivative provided");
3554 child0->name = F.derivative2();
3557 child0->name =
"DER_PDFUNC2_" + child0->name;
3558 if (!(ga_function_exists(child0->name)))
3559 ga_define_function(child0->name, 2, F.derivative2());
3562 child0->name =
"DER_PDFUNC2_" + child0->name;
3563 if (!(ga_function_exists(child0->name))) {
3564 std::string expr = ga_derivative_scalar_function(F.expr(),
"u");
3565 ga_define_function(child0->name, 2, expr);
3569 tree.insert_node(pnode, GA_NODE_OP);
3570 pga_tree_node pnode_op = pnode->parent;
3571 if (child2->tensor_order() == 0)
3572 pnode_op->op_type = GA_MULT;
3574 pnode_op->op_type = GA_DOTMULT;
3575 pnode_op->children.resize(2,
nullptr);
3576 tree.copy_node(child2, pnode_op, pnode_op->children[1]);
3577 ga_node_derivation(tree, workspace, m, pnode_op->children[1],
3578 varname, interpolatename, order);
3581 }
else if (child0->node_type == GA_NODE_SPEC_FUNC) {
3582 GMM_ASSERT1(
false,
"internal error");
3583 }
else if (child0->node_type == GA_NODE_OPERATOR) {
3585 GMM_ASSERT1(
false,
"Error in derivation of the assembly string. " 3586 "Cannot derive again operator " << child0->name);
3589 for (
size_type i = 1; i < pnode->children.size(); ++i)
3590 if (pnode->children[i]->marked) ++nbargs_der;
3591 pga_tree_node pnode2 = 0;
3594 for (
size_type i = 1; i < pnode->children.size(); ++i) {
3595 if (pnode->children[i]->marked) {
3597 if (j != nbargs_der) {
3598 tree.insert_node(pnode, GA_NODE_OP);
3599 pga_tree_node pnode_op = pnode->parent;
3600 pnode_op->node_type = GA_NODE_OP;
3601 pnode_op->op_type = GA_PLUS;
3602 pnode_op->children.resize(2,
nullptr);
3603 tree.copy_node(pnode, pnode_op , pnode_op->children[1]);
3604 pnode2 = pnode_op->children[1];
3606 else pnode2 = pnode;
3609 pnode2->children[0]->der2 = i;
3611 pnode2->children[0]->der1 = i;
3612 tree.insert_node(pnode2, GA_NODE_OP);
3613 pga_tree_node pnode_op = pnode2->parent;
3615 size_type red = pnode->children[i]->tensor_order();
3617 case 0 : pnode_op->op_type = GA_MULT;
break;
3618 case 1 : pnode_op->op_type = GA_DOT;
break;
3619 case 2 : pnode_op->op_type = GA_COLON;
break;
3620 default: GMM_ASSERT1(
false,
"Error in derivation of the assembly " 3621 "string. Bad reduction order.")
3623 pnode_op->children.resize(2,
nullptr);
3624 tree.copy_node(pnode->children[i], pnode_op,
3625 pnode_op->children[1]);
3626 ga_node_derivation(tree, workspace, m, pnode_op->children[1],
3627 varname, interpolatename, order);
3629 if (pnode2->children[0]->name.compare(
"Norm_sqr") == 0
3630 && pnode2->children[0]->der1 == 1) {
3631 pnode2->node_type = GA_NODE_OP;
3632 pnode2->op_type = GA_MULT;
3633 pnode2->children[0]->node_type = GA_NODE_CONSTANT;
3634 pnode2->children[0]->init_scalar_tensor(scalar_type(2));
3642 ga_node_derivation(tree, workspace, m, child0, varname,
3643 interpolatename, order);
3647 default: GMM_ASSERT1(
false,
"Unexpected node type " << pnode->node_type
3648 <<
" in derivation. Internal error.");
3654 void ga_derivative(ga_tree &tree,
const ga_workspace &workspace,
3655 const mesh &m,
const std::string &varname,
3656 const std::string &interpolatename,
size_type order) {
3658 if (!(tree.root))
return;
3659 if (ga_node_mark_tree_for_variable(tree.root, workspace, m, varname,
3661 ga_node_derivation(tree, workspace, m, tree.root, varname,
3662 interpolatename, order);
3674 static bool ga_node_mark_tree_for_grad(pga_tree_node pnode) {
3675 bool marked =
false;
3676 for (
size_type i = 0; i < pnode->children.size(); ++i)
3677 if (ga_node_mark_tree_for_grad(pnode->children[i]))
3680 bool plain_node(pnode->node_type == GA_NODE_VAL ||
3681 pnode->node_type == GA_NODE_GRAD ||
3682 pnode->node_type == GA_NODE_HESS ||
3683 pnode->node_type == GA_NODE_DIVERG);
3684 bool test_node(pnode->node_type == GA_NODE_VAL_TEST ||
3685 pnode->node_type == GA_NODE_GRAD_TEST ||
3686 pnode->node_type == GA_NODE_HESS_TEST ||
3687 pnode->node_type == GA_NODE_DIVERG_TEST);
3688 bool interpolate_node(pnode->node_type == GA_NODE_INTERPOLATE_VAL ||
3689 pnode->node_type == GA_NODE_INTERPOLATE_GRAD ||
3690 pnode->node_type == GA_NODE_INTERPOLATE_HESS ||
3691 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG);
3692 bool elementary_node(pnode->node_type == GA_NODE_ELEMENTARY_VAL ||
3693 pnode->node_type == GA_NODE_ELEMENTARY_GRAD ||
3694 pnode->node_type == GA_NODE_ELEMENTARY_HESS ||
3695 pnode->node_type == GA_NODE_ELEMENTARY_DIVERG);
3696 bool xfem_node(pnode->node_type == GA_NODE_XFEM_PLUS_VAL ||
3697 pnode->node_type == GA_NODE_XFEM_PLUS_GRAD ||
3698 pnode->node_type == GA_NODE_XFEM_PLUS_HESS ||
3699 pnode->node_type == GA_NODE_XFEM_PLUS_DIVERG ||
3700 pnode->node_type == GA_NODE_XFEM_MINUS_VAL ||
3701 pnode->node_type == GA_NODE_XFEM_MINUS_GRAD ||
3702 pnode->node_type == GA_NODE_XFEM_MINUS_HESS ||
3703 pnode->node_type == GA_NODE_XFEM_MINUS_DIVERG);
3704 bool interpolate_test_node
3705 (pnode->node_type == GA_NODE_INTERPOLATE_VAL_TEST ||
3706 pnode->node_type == GA_NODE_INTERPOLATE_GRAD_TEST ||
3707 pnode->node_type == GA_NODE_INTERPOLATE_HESS_TEST ||
3708 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG_TEST);
3710 if (plain_node || test_node || interpolate_node ||
3711 elementary_node || xfem_node ||
3712 pnode->node_type == GA_NODE_X ||
3713 pnode->node_type == GA_NODE_NORMAL) marked =
true;
3715 if (interpolate_node || interpolate_test_node ||
3716 pnode->node_type == GA_NODE_INTERPOLATE_X ||
3717 pnode->node_type == GA_NODE_INTERPOLATE_NORMAL) marked =
true;
3719 pnode->marked = marked;
3723 static void ga_node_grad(ga_tree &tree,
const ga_workspace &workspace,
3724 const mesh &m, pga_tree_node pnode) {
3727 size_type nbch = pnode->children.size();
3728 pga_tree_node child0 = (nbch > 0) ? pnode->children[0] : 0;
3729 pga_tree_node child1 = (nbch > 1) ? pnode->children[1] : 0;
3730 bool mark0 = ((nbch > 0) ? child0->marked :
false);
3731 bool mark1 = ((nbch > 1) ? child1->marked :
false);
3732 bgeot::multi_index mi;
3734 const ga_predef_function_tab &PREDEF_FUNCTIONS
3737 switch (pnode->node_type) {
3739 pnode->node_type = GA_NODE_GRAD;
3740 mi = pnode->tensor().sizes();
3741 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3742 pnode->t.adjust_sizes(mi);
3745 pnode->node_type = GA_NODE_HESS;
3746 mi = pnode->tensor().sizes();
3747 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3748 pnode->t.adjust_sizes(mi);
3751 GMM_ASSERT1(
false,
"Sorry, cannot derive an Hessian once more");
3752 case GA_NODE_DIVERG:
3753 pnode->node_type = GA_NODE_HESS;
3754 mi = pnode->tensor().sizes();
3755 mi.pop_back(), mi.push_back(m.dim());
3756 if (m.dim() > 1) mi.push_back(m.dim());
3757 pnode->t.adjust_sizes(mi);
3758 tree.duplicate_with_operation(pnode, GA_COLON);
3759 child0 = pnode; pnode = pnode->parent; child1 = pnode->children[1];
3760 child1->init_matrix_tensor(meshdim, meshdim);
3763 child1->tensor()(i,i) = scalar_type(1);
3764 child1->node_type = GA_NODE_CONSTANT;
3767 case GA_NODE_INTERPOLATE_HESS_TEST:
3768 case GA_NODE_INTERPOLATE_HESS:
3769 GMM_ASSERT1(
false,
"Sorry, cannot derive a hessian once more");
3772 case GA_NODE_INTERPOLATE_VAL:
3773 case GA_NODE_INTERPOLATE_GRAD:
3774 case GA_NODE_INTERPOLATE_DIVERG:
3775 case GA_NODE_INTERPOLATE_VAL_TEST:
3776 case GA_NODE_INTERPOLATE_GRAD_TEST:
3777 case GA_NODE_INTERPOLATE_DIVERG_TEST:
3778 case GA_NODE_INTERPOLATE_X:
3780 std::string &tname = pnode->interpolate_name;
3781 auto ptrans = workspace.interpolate_transformation(tname);
3782 std::string expr_trans = ptrans->expression();
3783 if (expr_trans.size() == 0)
3784 GMM_ASSERT1(
false,
"Sorry, the gradient of tranformation " 3785 << tname <<
" cannot be calculated. " 3786 "The gradient computation is available only for " 3787 "transformations having an explicit expression");
3790 ga_read_string(expr_trans, trans_tree, workspace.macro_dictionnary());
3791 ga_semantic_analysis(trans_tree, workspace, m,
3792 ref_elt_dim_of_mesh(m),
false,
false, 1);
3793 if (trans_tree.root) {
3794 ga_node_grad(trans_tree, workspace, m, trans_tree.root);
3795 ga_semantic_analysis(trans_tree, workspace, m,
3796 ref_elt_dim_of_mesh(m),
false,
false, 1);
3798 GMM_ASSERT1(trans_tree.root->tensor().sizes().size() == 2,
3799 "Problem in transformation" << tname);
3800 size_type trans_dim = trans_tree.root->tensor().sizes()[1];
3802 tree.duplicate_with_operation(pnode, GA_DOT);
3804 if (pnode->node_type == GA_NODE_INTERPOLATE_VAL) {
3805 pnode->node_type = GA_NODE_INTERPOLATE_GRAD;
3806 mi = pnode->tensor().sizes();
3807 if (mi.back() != 1) mi.push_back(trans_dim);
3808 else mi.back() = trans_dim;
3809 pnode->t.adjust_sizes(mi);
3810 }
else if (pnode->node_type == GA_NODE_INTERPOLATE_GRAD) {
3811 pnode->node_type = GA_NODE_INTERPOLATE_HESS;
3812 mi = pnode->tensor().sizes();
3813 if (mi.back() != 1) mi.push_back(trans_dim);
3814 else mi.back() = trans_dim;
3815 pnode->t.adjust_sizes(mi);
3816 }
else if (pnode->node_type == GA_NODE_INTERPOLATE_VAL_TEST) {
3817 pnode->node_type = GA_NODE_INTERPOLATE_GRAD_TEST;
3818 mi = pnode->tensor().sizes();
3819 if (mi.back() != 1) mi.push_back(trans_dim);
3820 else mi.back() = trans_dim;
3821 pnode->t.adjust_sizes(mi);
3822 }
else if (pnode->node_type == GA_NODE_INTERPOLATE_GRAD_TEST) {
3823 pnode->node_type = GA_NODE_INTERPOLATE_HESS_TEST;
3824 mi = pnode->tensor().sizes();
3825 if (mi.back() != 1) mi.push_back(trans_dim);
3826 else mi.back() = trans_dim;
3827 pnode->t.adjust_sizes(mi);
3828 }
else if (pnode->node_type == GA_NODE_INTERPOLATE_DIVERG ||
3829 pnode->node_type == GA_NODE_INTERPOLATE_DIVERG_TEST) {
3830 if (pnode->node_type == GA_NODE_INTERPOLATE_DIVERG)
3831 pnode->node_type = GA_NODE_INTERPOLATE_HESS;
3833 pnode->node_type = GA_NODE_INTERPOLATE_HESS_TEST;
3834 mi = pnode->tensor().sizes();
3835 mi.pop_back(), mi.push_back(trans_dim);
3836 if (trans_dim > 1) mi.push_back(trans_dim);
3837 pnode->t.adjust_sizes(mi);
3838 tree.duplicate_with_operation(pnode, GA_COLON);
3839 child0 = pnode; pnode = pnode->parent; child1 = pnode->children[1];
3840 child1->init_matrix_tensor(trans_dim, trans_dim);
3842 for (
size_type i = 0; i < trans_dim; ++i)
3843 child1->tensor()(i,i) = scalar_type(1);
3844 child1->node_type = GA_NODE_CONSTANT;
3845 }
else if (pnode->node_type == GA_NODE_INTERPOLATE_X) {
3846 pnode->node_type = GA_NODE_CONSTANT;
3848 pnode->init_vector_tensor(trans_dim);
3850 pnode->tensor()[pnode->nbc1-1] = scalar_type(1);
3852 pnode->init_matrix_tensor(trans_dim, trans_dim);
3854 for (
size_type i = 0; i < trans_dim; ++i)
3855 pnode->tensor()(i,i) = scalar_type(1);
3859 tree.clear_node_rec(pnode->parent->children[1]);
3860 pnode->parent->children[1] =
nullptr;
3861 tree.copy_node(trans_tree.root, pnode->parent,
3862 pnode->parent->children[1]);
3864 pnode->node_type = GA_NODE_ZERO;
3865 mi = pnode->tensor().sizes(); mi.push_back(m.dim());
3872 pnode->node_type = GA_NODE_CONSTANT;
3874 pnode->init_vector_tensor(meshdim);
3876 pnode->tensor()[pnode->nbc1-1] = scalar_type(1);
3878 pnode->init_matrix_tensor(meshdim, meshdim);
3881 pnode->tensor()(i,i) = scalar_type(1);
3885 case GA_NODE_NORMAL:
3886 case GA_NODE_INTERPOLATE_NORMAL:
3887 GMM_ASSERT1(
false,
"Sorry, Gradient of Normal vector not implemented");
3889 case GA_NODE_INTERPOLATE_DERIVATIVE:
3890 GMM_ASSERT1(
false,
"Sorry, gradient of the derivative of a " 3891 "tranformation not implemented");
3894 case GA_NODE_INTERPOLATE_FILTER:
3895 ga_node_grad(tree, workspace, m, child0);
3898 case GA_NODE_ELEMENTARY_VAL:
3899 pnode->node_type = GA_NODE_ELEMENTARY_GRAD;
3900 mi = pnode->tensor().sizes();
3901 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3902 pnode->t.adjust_sizes(mi);
3904 case GA_NODE_ELEMENTARY_GRAD:
3905 pnode->node_type = GA_NODE_ELEMENTARY_HESS;
3906 mi = pnode->tensor().sizes();
3907 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3908 pnode->t.adjust_sizes(mi);
3910 case GA_NODE_ELEMENTARY_HESS:
3911 GMM_ASSERT1(
false,
"Sorry, cannot derive an Hessian once more");
3912 case GA_NODE_ELEMENTARY_DIVERG:
3913 pnode->node_type = GA_NODE_ELEMENTARY_HESS;
3914 mi = pnode->tensor().sizes();
3915 mi.pop_back(), mi.push_back(m.dim());
3916 if (m.dim() > 1) mi.push_back(m.dim());
3917 pnode->t.adjust_sizes(mi);
3918 tree.duplicate_with_operation(pnode, GA_COLON);
3919 child0 = pnode; pnode = pnode->parent; child1 = pnode->children[1];
3920 child1->init_matrix_tensor(meshdim, meshdim);
3923 child1->tensor()(i,i) = scalar_type(1);
3924 child1->node_type = GA_NODE_CONSTANT;
3927 case GA_NODE_XFEM_PLUS_VAL:
3928 pnode->node_type = GA_NODE_XFEM_PLUS_GRAD;
3929 mi = pnode->tensor().sizes();
3930 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3931 pnode->t.adjust_sizes(mi);
3933 case GA_NODE_XFEM_PLUS_GRAD:
3934 pnode->node_type = GA_NODE_XFEM_PLUS_HESS;
3935 mi = pnode->tensor().sizes();
3936 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3937 pnode->t.adjust_sizes(mi);
3939 case GA_NODE_XFEM_PLUS_HESS:
3940 GMM_ASSERT1(
false,
"Sorry, cannot derive an Hessian once more");
3941 case GA_NODE_XFEM_PLUS_DIVERG:
3942 pnode->node_type = GA_NODE_XFEM_PLUS_HESS;
3943 mi = pnode->tensor().sizes();
3944 mi.pop_back(), mi.push_back(m.dim());
3945 if (m.dim() > 1) mi.push_back(m.dim());
3946 pnode->t.adjust_sizes(mi);
3947 tree.duplicate_with_operation(pnode, GA_COLON);
3948 child0 = pnode; pnode = pnode->parent; child1 = pnode->children[1];
3949 child1->init_matrix_tensor(meshdim, meshdim);
3952 child1->tensor()(i,i) = scalar_type(1);
3953 child1->node_type = GA_NODE_CONSTANT;
3956 case GA_NODE_XFEM_MINUS_VAL:
3957 pnode->node_type = GA_NODE_XFEM_MINUS_GRAD;
3958 mi = pnode->tensor().sizes();
3959 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3960 pnode->t.adjust_sizes(mi);
3962 case GA_NODE_XFEM_MINUS_GRAD:
3963 pnode->node_type = GA_NODE_XFEM_MINUS_HESS;
3964 mi = pnode->tensor().sizes();
3965 if (mi.back() != 1) mi.push_back(m.dim());
else mi.back() = m.dim();
3966 pnode->t.adjust_sizes(mi);
3968 case GA_NODE_XFEM_MINUS_HESS:
3969 GMM_ASSERT1(
false,
"Sorry, cannot derive an Hessian once more");
3970 case GA_NODE_XFEM_MINUS_DIVERG:
3971 pnode->node_type = GA_NODE_XFEM_MINUS_HESS;
3972 mi = pnode->tensor().sizes();
3973 mi.pop_back(), mi.push_back(m.dim());
3974 if (m.dim() > 1) mi.push_back(m.dim());
3975 pnode->t.adjust_sizes(mi);
3976 tree.duplicate_with_operation(pnode, GA_COLON);
3977 child0 = pnode; pnode = pnode->parent; child1 = pnode->children[1];
3978 child1->init_matrix_tensor(meshdim, meshdim);
3981 child1->tensor()(i,i) = scalar_type(1);
3982 child1->node_type = GA_NODE_CONSTANT;
3986 switch(pnode->op_type) {
3987 case GA_PLUS:
case GA_MINUS:
3988 if (mark0 && mark1) {
3989 ga_node_grad(tree, workspace, m, child0);
3990 ga_node_grad(tree, workspace, m, child1);
3992 ga_node_grad(tree, workspace, m, child0);
3993 tree.replace_node_by_child(pnode, 0);
3995 ga_node_grad(tree, workspace, m, child1);
3996 if (pnode->op_type == GA_MINUS) {
3997 pnode->op_type = GA_UNARY_MINUS;
3998 tree.clear_node(child0);
4001 tree.replace_node_by_child(pnode, 1);
4005 case GA_UNARY_MINUS:
case GA_PRINT:
4006 ga_node_grad(tree, workspace, m, child0);
4010 if (child0->tensor_order() == 1) {
4011 size_type nn = child0->tensor_proper_size(0);
4012 ga_node_grad(tree, workspace, m, child0);
4013 pnode->node_type = GA_NODE_PARAMS;
4014 tree.add_child(pnode);
4015 std::swap(pnode->children[0], pnode->children[1]);
4016 pnode->children[0]->node_type = GA_NODE_RESHAPE;
4017 tree.add_child(pnode); tree.add_child(pnode); tree.add_child(pnode);
4018 pnode->children[2]->node_type = GA_NODE_CONSTANT;
4019 pnode->children[3]->node_type = GA_NODE_CONSTANT;
4020 pnode->children[4]->node_type = GA_NODE_CONSTANT;
4021 pnode->children[2]->init_scalar_tensor(scalar_type(1));
4022 pnode->children[3]->init_scalar_tensor(scalar_type(nn));
4023 pnode->children[4]->init_scalar_tensor(scalar_type(m.dim()));
4025 ga_node_grad(tree, workspace, m, child0);
4030 tree.replace_node_by_child(pnode, 0);
4031 tree.duplicate_with_addition(child0);
4032 tree.insert_node(child0->parent, GA_NODE_OP);
4033 tree.add_child(child0->parent->parent);
4034 child0->parent->parent->op_type = GA_MULT;
4035 child0->parent->parent->children[1]->node_type = GA_NODE_CONSTANT;
4036 child0->parent->parent->children[1]->init_scalar_tensor(0.5);
4037 tree.insert_node(child0->parent->children[1], GA_NODE_OP);
4038 child0->parent->children[1]->op_type = GA_QUOTE;
4039 ga_node_grad(tree, workspace, m, child0);
4040 ga_node_grad(tree, workspace, m,
4041 child0->parent->children[1]->children[0]);
4046 tree.replace_node_by_child(pnode, 0);
4047 tree.duplicate_with_substraction(child0);
4048 tree.insert_node(child0->parent, GA_NODE_OP);
4049 tree.add_child(child0->parent->parent);
4050 child0->parent->parent->op_type = GA_MULT;
4051 child0->parent->parent->children[1]->node_type = GA_NODE_CONSTANT;
4052 child0->parent->parent->children[1]->init_scalar_tensor(0.5);
4053 tree.insert_node(child0->parent->children[1], GA_NODE_OP);
4054 child0->parent->children[1]->op_type = GA_QUOTE;
4055 ga_node_grad(tree, workspace, m, child0);
4056 ga_node_grad(tree, workspace, m,
4057 child0->parent->children[1]->children[0]);
4061 ga_node_grad(tree, workspace, m, child0);
4062 pnode->node_type = GA_NODE_PARAMS;
4063 tree.add_child(pnode);
4064 std::swap(pnode->children[0], pnode->children[1]);
4065 pnode->children[0]->node_type = GA_NODE_NAME;
4066 pnode->children[0]->name =
"Contract";
4067 tree.add_child(pnode); tree.add_child(pnode);
4068 pnode->children[2]->node_type = GA_NODE_CONSTANT;
4069 pnode->children[3]->node_type = GA_NODE_CONSTANT;
4070 pnode->children[2]->init_scalar_tensor(scalar_type(1));
4071 pnode->children[3]->init_scalar_tensor(scalar_type(2));
4076 tree.duplicate_with_substraction(child0);
4077 child1 = child0->parent->children[1];
4078 tree.insert_node(child1, GA_NODE_OP);
4079 child1->parent->op_type = GA_TRACE;
4080 tree.insert_node(child1->parent, GA_NODE_OP);
4081 child1->parent->parent->op_type = GA_TMULT;
4082 tree.add_child(child1->parent->parent);
4083 std::swap(child1->parent->parent->children[0],
4084 child1->parent->parent->children[1]);
4085 pga_tree_node pid = child1->parent->parent->children[0];
4086 tree.duplicate_with_operation(pid, GA_DIV);
4087 pid->parent->children[1]->node_type = GA_NODE_CONSTANT;
4088 pid->parent->children[1]->init_scalar_tensor(m.dim());
4089 pid->node_type = GA_NODE_PARAMS;
4090 tree.add_child(pid); tree.add_child(pid);
4091 pid->children[0]->node_type = GA_NODE_NAME;
4092 pid->children[0]->name =
"Id";
4093 pid->children[1]->node_type = GA_NODE_CONSTANT;
4094 pid->children[1]->init_scalar_tensor(m.dim());
4095 ga_node_grad(tree, workspace, m, child0);
4096 child1->parent->marked =
true;
4097 ga_node_grad(tree, workspace, m, child1->parent);
4098 tree.replace_node_by_child(pnode, 0);
4103 case GA_DOT:
case GA_MULT:
case GA_DOTMULT:
case GA_COLON:
case GA_TMULT:
4105 pga_tree_node pg1(0), pg2(0);
4106 if (mark0 && mark1) {
4107 if (sub_tree_are_equal(child0, child1, workspace, 0) &&
4108 (pnode->op_type != GA_MULT || child0->tensor_order() < 2) &&
4109 (pnode->op_type != GA_DOT || child0->tensor_order() < 2)) {
4111 tree.insert_node(pnode, GA_NODE_OP);
4112 pnode->parent->op_type = GA_MULT;
4113 tree.add_child(pnode->parent);
4114 pnode->parent->children[1]->node_type = GA_NODE_CONSTANT;
4115 pnode->parent->children[1]->init_scalar_tensor(scalar_type(2));
4117 tree.duplicate_with_addition(pnode);
4119 pg2 = pnode->parent->children[1];
4121 }
else if (mark0) pg1 = pnode;
else pg2 = pnode;
4124 if ((pg1->op_type == GA_COLON && child0->tensor_order() == 2) ||
4125 (pg1->op_type == GA_DOT && child0->tensor_order() == 1 &&
4126 child1->tensor_order() == 1) ||
4127 pg1->op_type == GA_DOTMULT ||
4128 (child0->tensor_proper_size()== 1 ||
4129 child1->tensor_proper_size()== 1)) {
4130 std::swap(pg1->children[0], pg1->children[1]);
4133 if (pnode->op_type == GA_MULT || pnode->op_type == GA_COLON ||
4134 pnode->op_type == GA_DOT) {
4135 if ((pg1->children[0]->tensor_order() <= 2 &&
4136 pnode->op_type == GA_MULT) ||
4137 pnode->op_type == GA_DOT) {
4138 nred = pg1->children[0]->tensor_order();
4139 pg1->node_type = GA_NODE_PARAMS;
4140 tree.add_child(pg1);tree.add_child(pg1);tree.add_child(pg1);
4141 std::swap(pg1->children[1], pg1->children[3]);
4142 std::swap(pg1->children[0], pg1->children[1]);
4143 pg1->children[0]->node_type = GA_NODE_NAME;
4144 pg1->children[0]->name =
"Contract";
4145 pg1->children[2]->node_type = GA_NODE_CONSTANT;
4146 pg1->children[2]->init_scalar_tensor
4147 (scalar_type(pg1->children[1]->tensor_order()));
4148 pg1->children[4]->node_type = GA_NODE_CONSTANT;
4149 pg1->children[4]->init_scalar_tensor(scalar_type(1));
4150 ga_node_grad(tree, workspace, m, pg1->children[1]);
4152 nred = pg1->children[0]->tensor_order()-1;
4153 pg1->node_type = GA_NODE_PARAMS;
4154 tree.add_child(pg1);tree.add_child(pg1);tree.add_child(pg1);
4155 tree.add_child(pg1);tree.add_child(pg1);
4156 std::swap(pg1->children[1], pg1->children[4]);
4157 std::swap(pg1->children[0], pg1->children[1]);
4158 pg1->children[0]->node_type = GA_NODE_NAME;
4159 pg1->children[0]->name =
"Contract";
4160 pg1->children[2]->node_type = GA_NODE_CONSTANT;
4161 pg1->children[2]->init_scalar_tensor
4162 (scalar_type(pg1->children[1]->tensor_order()-1));
4163 pg1->children[3]->node_type = GA_NODE_CONSTANT;
4164 pg1->children[3]->init_scalar_tensor
4165 (scalar_type(pg1->children[1]->tensor_order()));
4166 pg1->children[5]->node_type = GA_NODE_CONSTANT;
4167 pg1->children[5]->init_scalar_tensor(scalar_type(1));
4168 pg1->children[6]->node_type = GA_NODE_CONSTANT;
4169 pg1->children[6]->init_scalar_tensor(scalar_type(2));
4170 ga_node_grad(tree, workspace, m, pg1->children[1]);
4172 }
else if (pnode->op_type == GA_TMULT) {
4173 nred = pg1->children[0]->tensor_order()+1;
4174 ga_node_grad(tree, workspace, m, pg1->children[0]);
4175 }
else GMM_ASSERT1(
false,
"internal error");
4176 tree.insert_node(pg1, GA_NODE_PARAMS);
4177 tree.add_child(pg1->parent); tree.add_child(pg1->parent);
4178 std::swap(pg1->parent->children[0], pg1->parent->children[1]);
4179 pg1->parent->children[0]->node_type = GA_NODE_IND_MOVE_LAST;
4180 pg1->parent->children[2]->node_type = GA_NODE_CONSTANT;
4181 pg1->parent->children[2]->init_scalar_tensor(scalar_type(nred));
4186 for (; pg2||pg1;pg2=pg1, pg1=0) {
4188 if (pnode->op_type == GA_MULT || pnode->op_type == GA_COLON ||
4189 pnode->op_type == GA_DOT) {
4190 if (pg2->children[1]->tensor_proper_size() == 1) {
4191 pg2->op_type = GA_TMULT;
4192 ga_node_grad(tree, workspace, m, pg2->children[1]);
4193 }
else if (pg2->children[0]->tensor_proper_size() == 1) {
4194 pg2->op_type = GA_MULT;
4195 ga_node_grad(tree, workspace, m, pg2->children[1]);
4196 }
else if ((pg2->children[0]->tensor_order() <= 2 &&
4197 pnode->op_type == GA_MULT) ||
4198 pnode->op_type == GA_DOT) {
4199 pg2->op_type = GA_DOT;
4200 ga_node_grad(tree, workspace, m, pg2->children[1]);
4202 pg2->node_type = GA_NODE_PARAMS;
4203 tree.add_child(pg2);tree.add_child(pg2);tree.add_child(pg2);
4204 tree.add_child(pg2);tree.add_child(pg2);
4205 std::swap(pg2->children[1], pg2->children[4]);
4206 std::swap(pg2->children[0], pg2->children[1]);
4207 pg2->children[0]->node_type = GA_NODE_NAME;
4208 pg2->children[0]->name =
"Contract";
4209 pg2->children[2]->node_type = GA_NODE_CONSTANT;
4210 pg2->children[2]->init_scalar_tensor
4211 (scalar_type(pg2->children[4]->tensor_order()-1));
4212 pg2->children[3]->node_type = GA_NODE_CONSTANT;
4213 pg2->children[3]->init_scalar_tensor
4214 (scalar_type(pg2->children[4]->tensor_order()));
4215 pg2->children[5]->node_type = GA_NODE_CONSTANT;
4216 pg2->children[5]->init_scalar_tensor(scalar_type(1));
4217 pg2->children[6]->node_type = GA_NODE_CONSTANT;
4218 pg2->children[6]->init_scalar_tensor(scalar_type(2));
4219 ga_node_grad(tree, workspace, m, pg2->children[4]);
4221 }
else if (pnode->op_type == GA_TMULT) {
4222 ga_node_grad(tree, workspace, m, pg2->children[1]);
4223 }
else if (pnode->op_type == GA_DOTMULT) {
4224 if (pg2->children[0]->tensor_proper_size() == 1) {
4225 pg2->op_type = GA_MULT;
4226 ga_node_grad(tree, workspace, m, pg2->children[1]);
4228 tree.insert_node(pg2->children[0], GA_NODE_OP);
4229 tree.add_child(pg2->children[0], GA_NODE_CONSTANT);
4230 pg2->children[0]->op_type = GA_TMULT;
4231 pg2->children[0]->children[1]->init_vector_tensor(m.dim());
4232 gmm::fill(pg2->children[0]->children[1]->tensor().as_vector(),
4234 ga_node_grad(tree, workspace, m, pg2->children[1]);
4242 case GA_DIV:
case GA_DOTDIV:
4244 pga_tree_node pg1 = child0;
4246 if (pnode->children[0]->node_type == GA_NODE_CONSTANT) {
4247 gmm::scale(pnode->children[0]->tensor().as_vector(),
4252 tree.duplicate_with_substraction(pnode);
4253 pnode = pnode->parent->children[1];
4256 tree.insert_node(pnode, GA_NODE_OP);
4257 pnode->parent->op_type = GA_UNARY_MINUS;
4261 tree.insert_node(pnode->children[1], GA_NODE_PARAMS);
4262 pga_tree_node pnode_param = pnode->children[1];
4263 tree.add_child(pnode_param);
4264 std::swap(pnode_param->children[0], pnode_param->children[1]);
4265 pnode_param->children[0]->node_type = GA_NODE_PREDEF_FUNC;
4266 pnode_param->children[0]->name =
"sqr";
4267 tree.insert_node(pnode, GA_NODE_OP);
4268 pga_tree_node pnode_mult = pnode->parent;
4269 if (pnode->op_type == GA_DOTDIV) {
4270 pnode_mult->op_type = GA_DOTMULT;
4271 tree.insert_node(pnode_mult->children[0], GA_NODE_OP);
4272 pga_tree_node ptmult = pnode_mult->children[0];
4273 ptmult->op_type = GA_TMULT;
4274 tree.add_child(ptmult, GA_NODE_CONSTANT);
4275 ptmult->children[1]->init_vector_tensor(m.dim());
4276 gmm::fill(ptmult->children[1]->tensor().as_vector(),
4279 pnode_mult->op_type = GA_TMULT;
4281 pnode_mult->children.resize(2,
nullptr);
4282 tree.copy_node(pnode_param->children[1],
4283 pnode_mult, pnode_mult->children[1]);
4284 ga_node_grad(tree, workspace, m, pnode_mult->children[1]);
4288 ga_node_grad(tree, workspace, m, pg1);
4289 if (pnode->op_type == GA_DOTDIV) {
4290 tree.insert_node(pg1->parent->children[1], GA_NODE_OP);
4291 pga_tree_node ptmult = pg1->parent->children[1];
4292 ptmult->op_type = GA_TMULT;
4293 tree.add_child(ptmult, GA_NODE_CONSTANT);
4294 ptmult->children[1]->init_vector_tensor(m.dim());
4295 gmm::fill(ptmult->children[1]->tensor().as_vector(),
4301 default: GMM_ASSERT1(
false,
"Unexpected operation. Internal error.");
4305 case GA_NODE_C_MATRIX:
4307 for (
size_type i = 0; i < pnode->children.size(); ++i) {
4308 if (pnode->children[i]->marked)
4309 ga_node_grad(tree, workspace, m, pnode->children[i]);
4311 pnode->children[i]->init_scalar_tensor(scalar_type(0));
4312 pnode->children[i]->node_type = GA_NODE_ZERO;
4313 tree.clear_children(pnode->children[i]);
4317 size_type orgsize = pnode->children.size();
4318 mi = pnode->tensor().sizes();
4319 mi.push_back(m.dim());
4321 pnode->tensor().adjust_sizes(mi);
4323 pnode->children.resize(orgsize*m.dim(),
nullptr);
4324 for (
size_type i = orgsize; i < pnode->children.size(); ++i) {
4325 tree.copy_node(pnode->children[i % orgsize], pnode,
4326 pnode->children[i]);
4328 for (
size_type i = 0; i < pnode->children.size(); ++i) {
4329 pga_tree_node child = pnode->children[i];
4330 if (child->node_type != GA_NODE_ZERO) {
4331 tree.insert_node(child, GA_NODE_PARAMS);
4332 tree.add_child(child->parent, GA_NODE_CONSTANT);
4333 child->parent->children[1]
4334 ->init_scalar_tensor(scalar_type(1+i/orgsize));
4341 case GA_NODE_PARAMS:
4342 if (child0->node_type == GA_NODE_RESHAPE) {
4343 ga_node_grad(tree, workspace, m, pnode->children[1]);
4344 tree.add_child(pnode, GA_NODE_CONSTANT);
4345 pnode->children.back()->init_scalar_tensor(scalar_type(m.dim()));
4346 }
else if (child0->node_type == GA_NODE_IND_MOVE_LAST) {
4347 size_type order = pnode->tensor_order();
4348 ga_node_grad(tree, workspace, m, pnode->children[1]);
4349 tree.insert_node(pnode, GA_NODE_PARAMS);
4350 tree.add_child(pnode->parent); tree.add_child(pnode->parent);
4351 tree.add_child(pnode->parent);
4352 std::swap(pnode->parent->children[0], pnode->parent->children[1]);
4353 pnode->parent->children[0]->node_type = GA_NODE_SWAP_IND;
4354 pnode->parent->children[2]->node_type = GA_NODE_CONSTANT;
4355 pnode->parent->children[3]->node_type = GA_NODE_CONSTANT;
4356 pnode->parent->children[2]->init_scalar_tensor(scalar_type(order));
4357 pnode->parent->children[3]->init_scalar_tensor(scalar_type(order+1));
4358 }
else if (child0->node_type == GA_NODE_SWAP_IND) {
4359 ga_node_grad(tree, workspace, m, pnode->children[1]);
4360 }
else if (child0->node_type == GA_NODE_CONTRACT) {
4363 if (pnode->children.size() == 5) ch2 = 3;
4364 if (pnode->children.size() == 7) ch2 = 4;
4365 mark1 = pnode->children[ch2]->marked;
4367 if (pnode->children.size() == 4) {
4368 ga_node_grad(tree, workspace, m, pnode->children[1]);
4370 pga_tree_node pg1(pnode), pg2(pnode);
4371 if (mark0 && mark1) {
4372 tree.duplicate_with_addition(pnode);
4373 pg2 = pnode->parent->children[1];
4376 size_type nred = pg1->children[1]->tensor_order();
4377 if (pnode->children.size() == 7) nred--;
4378 ga_node_grad(tree, workspace, m, pg1->children[1]);
4379 tree.insert_node(pg1, GA_NODE_PARAMS);
4380 tree.add_child(pg1->parent); tree.add_child(pg1->parent);
4381 std::swap(pg1->parent->children[0], pg1->parent->children[1]);
4382 pg1->parent->children[0]->node_type = GA_NODE_IND_MOVE_LAST;
4383 pg1->parent->children[2]->node_type = GA_NODE_CONSTANT;
4384 pg1->parent->children[2]->init_scalar_tensor(scalar_type(nred));
4387 ga_node_grad(tree, workspace, m, pg2->children[ch2]);
4391 }
else if (child0->node_type == GA_NODE_PREDEF_FUNC) {
4392 std::string name = child0->name;
4393 ga_predef_function_tab::const_iterator it = PREDEF_FUNCTIONS.find(name);
4394 const ga_predef_function &F = it->second;
4396 if (F.nbargs() == 1) {
4397 switch (F.dtype()) {
4399 GMM_ASSERT1(
false,
"Cannot derive function " << child0->name
4400 <<
". No derivative provided or not derivable function.");
4402 child0->name = F.derivative1();
4406 child0->name =
"DER_PDFUNC_" + child0->name;
4407 if (!(ga_function_exists(child0->name))) {
4409 ga_define_function(child0->name, 1, F.derivative1());
4411 std::string expr=ga_derivative_scalar_function(F.expr(),
"t");
4412 ga_define_function(child0->name, 1, expr);
4417 ga_predef_function_tab::const_iterator
4418 itp = PREDEF_FUNCTIONS.find(child0->name);
4419 const ga_predef_function &Fp = itp->second;
4420 if (Fp.is_affine(
"t")) {
4421 scalar_type b = Fp(scalar_type(0));
4422 scalar_type a = Fp(scalar_type(1)) - b;
4423 pnode->node_type = GA_NODE_OP;
4424 pnode->op_type = GA_MULT;
4425 child0->init_scalar_tensor(a);
4426 child0->node_type = ((a == scalar_type(0)) ?
4427 GA_NODE_ZERO : GA_NODE_CONSTANT);
4428 if (b != scalar_type(0)) {
4429 tree.insert_node(pnode, GA_NODE_OP);
4430 pnode->parent->op_type = (b > 0) ? GA_PLUS : GA_MINUS;
4431 tree.add_child(pnode->parent);
4432 pga_tree_node pnode_cte = pnode->parent->children[1];
4433 pnode_cte->node_type = GA_NODE_CONSTANT;
4434 pnode_cte->t = pnode->t;
4435 std::fill(pnode_cte->tensor().begin(),
4436 pnode_cte->tensor().end(), gmm::abs(b));
4437 pnode = pnode->parent;
4443 if (pnode->children.size() >= 2) {
4444 tree.insert_node(pnode, GA_NODE_OP);
4445 pga_tree_node pnode_op = pnode->parent;
4446 if (child1->tensor_order() == 0)
4447 pnode_op->op_type = GA_MULT;
4449 pnode_op->op_type = GA_DOTMULT;
4450 tree.insert_node(pnode, GA_NODE_OP);
4451 pnode->parent->op_type = GA_TMULT;
4452 tree.add_child(pnode->parent, GA_NODE_CONSTANT);
4453 pnode->parent->children[1]->init_vector_tensor(m.dim());
4454 gmm::fill(pnode->parent->children[1]->tensor().as_vector(),
4457 pnode_op->children.resize(2,
nullptr);
4458 tree.copy_node(child1, pnode_op, pnode_op->children[1]);
4459 ga_node_grad(tree, workspace, m, pnode_op->children[1]);
4462 pga_tree_node child2 = pnode->children[2];
4463 pga_tree_node pg2 = pnode;
4465 if (child1->marked && child2->marked) {
4466 tree.duplicate_with_addition(pnode);
4467 pg2 = pnode->parent->children[1];
4470 if (child1->marked) {
4471 switch (F.dtype()) {
4473 GMM_ASSERT1(
false,
"Cannot derive function " << child0->name
4474 <<
". No derivative provided");
4476 child0->name = F.derivative1();
4479 child0->name =
"DER_PDFUNC1_" + child0->name;
4480 if (!(ga_function_exists(child0->name)))
4481 ga_define_function(child0->name, 2, F.derivative1());
4484 child0->name =
"DER_PDFUNC1_" + child0->name;
4485 if (!(ga_function_exists(child0->name))) {
4486 std::string expr = ga_derivative_scalar_function(F.expr(),
"t");
4487 ga_define_function(child0->name, 2, expr);
4491 tree.insert_node(pnode, GA_NODE_OP);
4492 pga_tree_node pnode_op = pnode->parent;
4493 if (child1->tensor_order() == 0)
4494 pnode_op->op_type = GA_MULT;
4496 pnode_op->op_type = GA_DOTMULT;
4497 tree.insert_node(pnode, GA_NODE_OP);
4498 pnode->parent->op_type = GA_TMULT;
4499 tree.add_child(pnode->parent, GA_NODE_CONSTANT);
4500 pnode->parent->children[1]->init_vector_tensor(m.dim());
4501 gmm::fill(pnode->parent->children[1]->tensor().as_vector(),
4504 pnode_op->children.resize(2,
nullptr);
4505 tree.copy_node(child1, pnode_op, pnode_op->children[1]);
4506 ga_node_grad(tree, workspace, m, pnode_op->children[1]);
4508 if (child2->marked) {
4510 child0 = pnode->children[0]; child1 = pnode->children[1];
4511 child2 = pnode->children[2];
4513 switch (F.dtype()) {
4515 GMM_ASSERT1(
false,
"Cannot derive function " << child0->name
4516 <<
". No derivative provided");
4518 child0->name = F.derivative2();
4521 child0->name =
"DER_PDFUNC2_" + child0->name;
4522 if (!(ga_function_exists(child0->name)))
4523 ga_define_function(child0->name, 2, F.derivative2());
4526 child0->name =
"DER_PDFUNC2_" + child0->name;
4527 if (!(ga_function_exists(child0->name))) {
4528 std::string expr = ga_derivative_scalar_function(F.expr(),
"u");
4529 ga_define_function(child0->name, 2, expr);
4533 tree.insert_node(pnode, GA_NODE_OP);
4534 pga_tree_node pnode_op = pnode->parent;
4535 if (child2->tensor_order() == 0)
4536 pnode_op->op_type = GA_MULT;
4538 pnode_op->op_type = GA_DOTMULT;
4539 tree.insert_node(pnode, GA_NODE_OP);
4540 pnode->parent->op_type = GA_TMULT;
4541 tree.add_child(pnode->parent, GA_NODE_CONSTANT);
4542 pnode->parent->children[1]->init_vector_tensor(m.dim());
4543 gmm::fill(pnode->parent->children[1]->tensor().as_vector(),
4546 pnode_op->children.resize(2,
nullptr);
4547 tree.copy_node(child2, pnode_op, pnode_op->children[1]);
4548 ga_node_grad(tree, workspace, m, pnode_op->children[1]);
4551 }
else if (child0->node_type == GA_NODE_SPEC_FUNC) {
4552 GMM_ASSERT1(
false,
"internal error");
4553 }
else if (child0->node_type == GA_NODE_OPERATOR) {
4555 GMM_ASSERT1(
false,
"Error in derivation of the assembly string. " 4556 "Cannot derive again operator " << child0->name);
4559 for (
size_type i = 1; i < pnode->children.size(); ++i)
4560 if (pnode->children[i]->marked) ++nbargs_der;
4561 pga_tree_node pnode2 = 0;
4564 for (
size_type i = 1; i < pnode->children.size(); ++i) {
4565 if (pnode->children[i]->marked) {
4567 if (j != nbargs_der) {
4568 tree.insert_node(pnode, GA_NODE_OP);
4569 pga_tree_node pnode_op = pnode->parent;
4570 pnode_op->node_type = GA_NODE_OP;
4571 pnode_op->op_type = GA_PLUS;
4572 pnode_op->children.resize(2,
nullptr);
4573 tree.copy_node(pnode, pnode_op , pnode_op->children[1]);
4574 pnode2 = pnode_op->children[1];
4576 else pnode2 = pnode;
4579 pnode2->children[0]->der2 = i;
4581 pnode2->children[0]->der1 = i;
4582 tree.insert_node(pnode2, GA_NODE_OP);
4583 pga_tree_node pnode_op = pnode2->parent;
4585 size_type red = pnode->children[i]->tensor_order();
4587 case 0 : pnode_op->op_type = GA_MULT;
break;
4588 case 1 : pnode_op->op_type = GA_DOT;
break;
4589 case 2 : pnode_op->op_type = GA_COLON;
break;
4590 default: GMM_ASSERT1(
false,
"Error in derivation of the assembly " 4591 "string. Bad reduction order.")
4593 pnode_op->children.resize(2,
nullptr);
4594 tree.copy_node(pnode->children[i], pnode_op,
4595 pnode_op->children[1]);
4596 ga_node_grad(tree, workspace, m, pnode_op->children[1]);
4598 if (pnode2->children[0]->name.compare(
"Norm_sqr") == 0
4599 && pnode2->children[0]->der1 == 1) {
4600 pnode2->node_type = GA_NODE_OP;
4601 pnode2->op_type = GA_MULT;
4602 pnode2->children[0]->node_type = GA_NODE_CONSTANT;
4603 pnode2->children[0]->init_scalar_tensor(scalar_type(2));
4608 ga_node_grad(tree, workspace, m, child0);
4609 tree.add_child(pnode, GA_NODE_ALLINDICES);
4614 default: GMM_ASSERT1(
false,
"Unexpected node type " << pnode->node_type
4615 <<
" in derivation. Internal error.");
4622 void ga_grad(ga_tree &tree,
const ga_workspace &workspace,
const mesh &m) {
4623 if (!(tree.root))
return;
4624 if (ga_node_mark_tree_for_grad(tree.root))
4625 ga_node_grad(tree, workspace, m, tree.root);
4632 static void ga_replace_test_by_cte(pga_tree_node pnode,
bool full_replace) {
4633 for (
size_type i = 0; i < pnode->children.size(); ++i)
4634 ga_replace_test_by_cte(pnode->children[i], full_replace);
4635 GMM_ASSERT1(pnode->node_type != GA_NODE_GRAD_TEST,
"Invalid tree");
4636 GMM_ASSERT1(pnode->node_type != GA_NODE_HESS_TEST,
"Invalid tree");
4637 GMM_ASSERT1(pnode->node_type != GA_NODE_DIVERG_TEST,
"Invalid tree");
4638 if (pnode->node_type == GA_NODE_VAL_TEST) {
4639 pnode->node_type = GA_NODE_CONSTANT;
4640 if (full_replace) pnode->init_scalar_tensor(scalar_type(1));
4644 std::string ga_derivative_scalar_function(
const std::string &expr,
4645 const std::string &var) {
4646 base_vector t(1), u(1);
4647 ga_workspace workspace;
4648 workspace.add_fixed_size_variable(
"t", gmm::sub_interval(0,1), t);
4649 workspace.add_fixed_size_variable(
"u", gmm::sub_interval(0,1), u);
4650 workspace.add_function_expression(expr);
4651 GMM_ASSERT1(workspace.nb_trees() <= 1,
"Internal error");
4652 if (workspace.nb_trees()) {
4653 ga_tree tree = *(workspace.tree_info(0).ptree);
4654 ga_derivative(tree, workspace, *((
const mesh *)(0)), var,
"", 1);
4656 ga_replace_test_by_cte(tree.root,
true);
4657 ga_semantic_analysis(tree, workspace, *((
const mesh *)(0)), 1,
4660 return ga_tree_to_string(tree);
4664 static bool ga_node_is_affine(
const pga_tree_node pnode) {
4666 size_type nbch = pnode->children.size();
4667 pga_tree_node child0 = (nbch > 0) ? pnode->children[0] : 0;
4668 pga_tree_node child1 = (nbch > 1) ? pnode->children[1] : 0;
4669 bool mark0 = ((nbch > 0) ? child0->marked :
false);
4670 bool mark1 = ((nbch > 1) ? child1->marked :
false);
4672 switch (pnode->node_type) {
4673 case GA_NODE_VAL:
case GA_NODE_GRAD:
4674 case GA_NODE_HESS:
case GA_NODE_DIVERG:
4675 case GA_NODE_INTERPOLATE_VAL:
case GA_NODE_INTERPOLATE_GRAD:
4676 case GA_NODE_INTERPOLATE_HESS:
case GA_NODE_INTERPOLATE_DIVERG:
4677 case GA_NODE_INTERPOLATE_DERIVATIVE:
4678 case GA_NODE_ELEMENTARY_VAL:
case GA_NODE_ELEMENTARY_GRAD:
4679 case GA_NODE_ELEMENTARY_HESS:
case GA_NODE_ELEMENTARY_DIVERG:
4680 case GA_NODE_XFEM_PLUS_VAL:
case GA_NODE_XFEM_PLUS_GRAD:
4681 case GA_NODE_XFEM_PLUS_HESS:
case GA_NODE_XFEM_PLUS_DIVERG:
4682 case GA_NODE_XFEM_MINUS_VAL:
case GA_NODE_XFEM_MINUS_GRAD:
4683 case GA_NODE_XFEM_MINUS_HESS:
case GA_NODE_XFEM_MINUS_DIVERG:
4685 case GA_NODE_INTERPOLATE_FILTER:
4686 return ga_node_is_affine(child0);
4688 switch(pnode->op_type) {
4689 case GA_PLUS:
case GA_MINUS:
4691 return ga_node_is_affine(child0) &&
4692 ga_node_is_affine(child1);
4693 if (mark0)
return ga_node_is_affine(child0);
4694 return ga_node_is_affine(child1);
4696 case GA_UNARY_MINUS:
case GA_QUOTE:
case GA_SYM:
case GA_SKEW:
4697 case GA_TRACE:
case GA_DEVIATOR:
case GA_PRINT:
4698 return ga_node_is_affine(child0);
4700 case GA_DOT:
case GA_MULT:
case GA_COLON:
case GA_TMULT:
4702 if (mark0 && mark1)
return false;
4703 if (mark0)
return ga_node_is_affine(child0);
4704 return ga_node_is_affine(child1);
4706 case GA_DIV:
case GA_DOTDIV:
4707 if (mark1)
return false;
4708 if (mark0)
return ga_node_is_affine(child0);
4710 default: GMM_ASSERT1(
false,
"Unexpected operation. Internal error.");
4714 case GA_NODE_C_MATRIX:
4715 for (
size_type i = 0; i < pnode->children.size(); ++i)
4716 if (pnode->children[i]->marked &&
4717 !(ga_node_is_affine(pnode->children[i])))
4721 case GA_NODE_PARAMS:
4722 if (child0->node_type == GA_NODE_RESHAPE ||
4723 child0->node_type == GA_NODE_SWAP_IND ||
4724 child0->node_type == GA_NODE_IND_MOVE_LAST)
4725 return ga_node_is_affine(child1);
4726 if (child0->node_type == GA_NODE_CONTRACT) {
4727 if (pnode->children.size() == 4) {
4728 return ga_node_is_affine(child1);
4729 }
else if (pnode->children.size() == 5) {
4730 if (mark1 && pnode->children[3]->marked)
return false;
4731 if (mark1)
return ga_node_is_affine(child1);
4732 return ga_node_is_affine(pnode->children[3]);
4733 }
else if (pnode->children.size() == 7) {
4734 if (mark1 && pnode->children[4]->marked)
return false;
4735 if (mark1)
return ga_node_is_affine(child1);
4736 return ga_node_is_affine(pnode->children[4]);
4739 if (child0->node_type == GA_NODE_PREDEF_FUNC)
4741 if (child0->node_type == GA_NODE_OPERATOR)
4743 return ga_node_is_affine(child0);
4745 default: GMM_ASSERT1(
false,
"Unexpected node type " << pnode->node_type
4746 <<
" in derivation. Internal error.");
4750 bool ga_is_affine(
const ga_tree &tree,
const ga_workspace &workspace,
4751 const std::string &varname,
4752 const std::string &interpolatename) {
4753 const mesh &m = *((
const mesh *)(0));
4754 if (tree.root && ga_node_mark_tree_for_variable(tree.root, workspace, m,
4755 varname, interpolatename))
4756 return ga_node_is_affine(tree.root);
Semantic analysis of assembly trees and semantic manipulations.
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.
void clear(L &l)
clear (fill with zeros) a vector or matrix.