GetFEM  5.4.3
getfem_models.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2009-2020 Yves Renard
5 
6  This file is a part of GetFEM
7 
8  GetFEM is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /**
33  @file getfem_models.h
34  @author Yves Renard <Yves.Renard@insa-lyon.fr>
35  @date March 21, 2009.
36  @brief Model representation in Getfem.
37 */
38 
39 #ifndef GETFEM_MODELS_H__
40 #define GETFEM_MODELS_H__
41 
43 #include "getfem_assembling.h"
45 #include "getfem_im_data.h"
46 
47 namespace getfem {
48 
49  class virtual_brick;
50  /** type of pointer on a brick */
51  typedef std::shared_ptr<const virtual_brick> pbrick;
52 
53  class virtual_dispatcher;
54  typedef std::shared_ptr<const virtual_dispatcher> pdispatcher;
55 
56  class virtual_time_scheme;
57  typedef std::shared_ptr<const virtual_time_scheme> ptime_scheme;
58 
59  // Event management : The model has to react when something has changed in
60  // the context and ask for corresponding (linear) bricks to recompute
61  // some terms.
62  // For the moment two events are taken into account
63  // - Change in a mesh_fem
64  // - Change in the data of a variable
65  // For this, a brick has to declare on which variable it depends and
66  // on which data. When a linear brick depend on a variable, the
67  // recomputation is done when the eventual corresponding mesh_fem
68  // is changed (or the size of the variable for a fixed size variable).
69  // When a linear brick depend on a data, the recomputation is done
70  // when the corresponding vector value is changed. If a variable is used
71  // as a data, it has to be declared as a data by the brick.
72  // A nonlinear brick is recomputed at each assembly of the tangent system.
73  // Remember this behavior when some changed are done on the variable
74  // and/or data.
75  // The change on a mesh_im is not taken into account for the moment.
76  // The different versions of the variables is not taken into account
77  // separately.
78 
79 
80 
81 
82  //=========================================================================
83  //
84  // Model object.
85  //
86  //=========================================================================
87 
88  // For backward compatibility with version 3.0
89  typedef model_real_plain_vector modeling_standard_plain_vector;
91  typedef model_real_sparse_matrix modeling_standard_sparse_matrix;
92  typedef model_complex_plain_vector modeling_standard_complex_plain_vector;
94  typedef model_complex_sparse_matrix modeling_standard_complex_sparse_matrix;
95 
96 
97  /** A prefix to refer to the previous version of a variable*/
98  const auto PREFIX_OLD = std::string{"Old_"};
99  const auto PREFIX_OLD_LENGTH = 4;
100 
101  /** Does the variable have Old_ prefix*/
102  bool is_old(const std::string &name);
103 
104  /** Strip the variable name from prefix Old_ if it has one*/
105  std::string no_old_prefix_name(const std::string &name);
106 
107  std::string sup_previous_and_dot_to_varname(std::string v);
108 
109  /** ``Model'' variables store the variables, the data and the
110  description of a model. This includes the global tangent matrix, the
111  right hand side and the constraints. There are two kinds of models, the
112  ``real'' and the ``complex'' models.
113  */
114  class APIDECL model : public context_dependencies,
115  virtual public dal::static_stored_object {
116 
117  protected:
118 
119  // State variables of the model
120  bool complex_version;
121  bool is_linear_;
122  bool is_symmetric_;
123  bool is_coercive_;
124  mutable model_real_sparse_matrix
125  rTM, // tangent matrix (only primary variables), real version
126  internal_rTM; // coupling matrix between internal and primary vars (no empty rows)
127  mutable model_complex_sparse_matrix cTM; // tangent matrix, complex version
128  mutable model_real_plain_vector
129  rrhs, // residual vector of primary variables (after condensation)
130  full_rrhs, // residual vector of primary and internal variables (pre-condensation)
131  internal_sol; // partial solution for internal variables (after condensation)
132  mutable model_complex_plain_vector crhs;
133  mutable bool act_size_to_be_done;
134  dim_type leading_dim;
135  getfem::lock_factory locks_;
136 
137  // Variables and parameters of the model
138 
139  enum var_description_filter {
140  VDESCRFILTER_NO = 0, // Variable being directly the dofs of a given fem
141  VDESCRFILTER_REGION = 1, /* Variable being the dofs of a fem on a mesh
142  * region (uses mf.dof_on_region). */
143  VDESCRFILTER_INFSUP = 2, /* Variable being the dofs of a fem on a mesh
144  * region with an additional filter on a mass
145  * matrix with respect to another fem. */
146  VDESCRFILTER_CTERM = 4, /* Variable being the dofs of a fem on a mesh
147  * region with an additional filter with the
148  * coupling term with respect to another variable.*/
149  VDESCRFILTER_REGION_CTERM = 5, /* both region and cterm. */
150  }; // INFSUP and CTERM are incompatible
151 
152  struct var_description {
153 
154  bool is_variable; // This is a variable or a parameter.
155  bool is_disabled; // For a variable, to be solved or not
156  bool is_complex; // The variable is complex numbers
157  bool is_affine_dependent; // The variable depends in an affine way
158  // to another variable.
159  bool is_internal; // An internal variable defined on integration
160  // points, condensed out of the global system.
161  size_type n_iter; // Number of versions of the variable stored.
162  size_type n_temp_iter; // Number of additional temporary versions
163  size_type default_iter; // default iteration number.
164 
165  ptime_scheme ptsc; // For optional time integration scheme
166 
167  var_description_filter filter; // Version of an optional filter
168  // on the dofs
169  size_type filter_region; // Optional region for the filter
170  std::string filter_var; // Optional variable name for the filter
171  mesh_im const *filter_mim; // Optional integration method for the filter
172 
173  // fem or im_data description of the variable
174  mesh_fem const *mf; // Main fem of the variable.
175  ppartial_mesh_fem partial_mf; // Filter with respect to mf.
176  im_data const *imd; // im data description
177 
178  bgeot::multi_index qdims; // For data having a qdim != of the fem
179  // (dim per dof for dof data)
180  // and for constant variables.
181  gmm::uint64_type v_num;
182  std::vector<gmm::uint64_type> v_num_data;
183 
184  gmm::sub_interval I; // For a variable : indices on the whole system.
185  // For an affine dependent variable, should be the same as the
186  // original variable
187  std::vector<model_real_plain_vector> real_value;
188  std::vector<model_complex_plain_vector> complex_value;
189  std::vector<gmm::uint64_type> v_num_var_iter;
190  std::vector<gmm::uint64_type> v_num_iter;
191 
192  // For affine dependent variables
193  model_real_plain_vector affine_real_value;
194  model_complex_plain_vector affine_complex_value;
195  scalar_type alpha; // Factor for the affine dependent variables
196  std::string org_name; // Name of the original variable for affine
197  // dependent variables
198 
199  var_description(bool is_var = false, bool is_compl = false,
200  mesh_fem const *mf_ = 0, im_data const *imd_ = 0,
201  size_type n_it = 1,
202  var_description_filter filter_ = VDESCRFILTER_NO,
203  size_type filter_reg = size_type(-1),
204  const std::string &filter_var_ = std::string(""),
205  mesh_im const *filter_mim_ = 0)
206  : is_variable(is_var), is_disabled(false), is_complex(is_compl),
207  is_affine_dependent(false), is_internal(false),
208  n_iter(std::max(size_type(1), n_it)), n_temp_iter(0),
209  default_iter(0), ptsc(0),
210  filter(filter_), filter_region(filter_reg), filter_var(filter_var_),
211  filter_mim(filter_mim_), mf(mf_), imd(imd_), qdims(),
212  v_num(0), v_num_data(n_iter, act_counter()), I(0,0), alpha(1)
213  {
214  if (filter != VDESCRFILTER_NO && mf != 0)
215  partial_mf = std::make_shared<partial_mesh_fem>(*mf);
216  // v_num_data = v_num;
217  if (qdims.size() == 0) qdims.push_back(1);
218  GMM_ASSERT1(qdim(), "Attempt to create a null size variable");
219  }
220 
221  size_type qdim() const { return qdims.total_size(); }
222 
223  // add a temporary version for time integration schemes. Automatically
224  // set the default iter to it. id_num is an identifier. Do not add
225  // the version if a temporary already exist with this identifier.
226  size_type add_temporary(gmm::uint64_type id_num);
227 
228  void clear_temporaries();
229 
230  const mesh_fem &associated_mf() const {
231  GMM_ASSERT1(mf, "This variable is not linked to a fem");
232  return (filter == VDESCRFILTER_NO) ? *mf : *partial_mf;
233  }
234 
235  const mesh_fem *passociated_mf() const {
236  if (mf)
237  return (filter == VDESCRFILTER_NO || partial_mf.get() == 0)
238  ? mf : partial_mf.get();
239  return 0;
240  }
241 
242  size_type size() const { // Should control that the variable is
243  // indeed initialized by actualize_sizes() ...
244  return is_complex ? complex_value[0].size()
245  : real_value[0].size();
246  }
247  inline bool is_enabled() const { return !is_disabled; }
248 
249  void set_size();
250  }; // struct var_description
251 
252  public:
253 
254  typedef std::vector<std::string> varnamelist;
255  typedef std::vector<const mesh_im *> mimlist;
256  typedef std::vector<model_real_sparse_matrix> real_matlist;
257  typedef std::vector<model_complex_sparse_matrix> complex_matlist;
258  typedef std::vector<model_real_plain_vector> real_veclist;
259  typedef std::vector<model_complex_plain_vector> complex_veclist;
260 
261  struct term_description {
262  bool is_matrix_term; // tangent matrix term or rhs term.
263  bool is_symmetric; // Term have to be symmetrized.
264  bool is_global; // Specific global term for highly coupling bricks
265  std::string var1, var2;
266 
267  term_description(const std::string &v)
268  : is_matrix_term(false), is_symmetric(false),
269  is_global(false), var1(sup_previous_and_dot_to_varname(v)) {}
270  term_description(const std::string &v1, const std::string &v2,
271  bool issym)
272  : is_matrix_term(true), is_symmetric(issym), is_global(false),
273  var1(sup_previous_and_dot_to_varname(v1)), var2(v2) {}
274  term_description(bool ism, bool issym)
275  : is_matrix_term(ism), is_symmetric(issym), is_global(true) {}
276  };
277 
278  typedef std::vector<term_description> termlist;
279 
280  enum build_version {
281  BUILD_RHS = 1,
282  BUILD_MATRIX = 2,
283  BUILD_ALL = 3,
284  BUILD_ON_DATA_CHANGE = 4,
285  BUILD_WITH_LIN = 8, // forced calculation of linear terms
286  BUILD_RHS_WITH_LIN = 9, // = BUILD_RHS | BUILD_WITH_LIN_RHS
287  BUILD_WITH_INTERNAL = 16,
288  BUILD_RHS_WITH_INTERNAL = 17, // = BUILD_RHS | BUILD_WITH_INTERNAL
289  BUILD_MATRIX_CONDENSED = 18, // = BUILD_MATRIX | BUILD_WITH_INTERNAL
290  BUILD_ALL_CONDENSED = 19, // = BUILD_ALL | BUILD_WITH_INTERNAL
291  };
292 
293  protected:
294 
295  // rmatlist and cmatlist could had been csc_matrix vectors to reduce the
296  // amount of memory (but this would require an additional copy).
297  struct brick_description {
298  mutable bool terms_to_be_computed;
299  mutable gmm::uint64_type v_num;
300  pbrick pbr; // brick pointer
301  pdispatcher pdispatch; // Optional dispatcher
302  size_type nbrhs; // Additional rhs for dispatcher.
303  varnamelist vlist; // List of variables used by the brick.
304  varnamelist dlist; // List of data used by the brick.
305  termlist tlist; // List of terms build by the brick
306  mimlist mims; // List of integration methods.
307  size_type region; // Optional region size_type(-1) for all.
308  bool is_update_brick; // Flag for declaring special type of brick
309  // with no contributions.
310  mutable scalar_type external_load; // External load computed in assembly
311 
312  mutable model_real_plain_vector coeffs;
313  mutable scalar_type matrix_coeff = scalar_type(0);
314  // Matrices the brick has to fill in (real version)
315  mutable real_matlist rmatlist;
316  // Rhs the brick has to fill in (real version)
317  mutable std::vector<real_veclist> rveclist;
318  // additional rhs for symmetric terms (real version)
319  mutable std::vector<real_veclist> rveclist_sym;
320  // Matrices the brick has to fill in (complex version)
321  mutable complex_matlist cmatlist;
322  // Rhs the brick has to fill in (complex version)
323  mutable std::vector<complex_veclist> cveclist;
324  // additional rhs for symmetric terms (complex version)
325  mutable std::vector<complex_veclist> cveclist_sym;
326 
327  brick_description() : v_num(0) {}
328 
329  brick_description(pbrick p, const varnamelist &vl,
330  const varnamelist &dl, const termlist &tl,
331  const mimlist &mms, size_type reg)
332  : terms_to_be_computed(true), v_num(0), pbr(p), pdispatch(0), nbrhs(1),
333  vlist(vl), dlist(dl), tlist(tl), mims(mms), region(reg),
334  is_update_brick(false), external_load(0),
335  rveclist(1), rveclist_sym(1), cveclist(1),
336  cveclist_sym(1) { }
337  };
338 
339  typedef std::map<std::string, var_description> VAR_SET;
340  mutable VAR_SET variables; // Variables list of the model
341  std::vector<brick_description> bricks; // Bricks list of the model
342  dal::bit_vector valid_bricks, active_bricks;
343  std::map<std::string, pinterpolate_transformation> transformations;
344  std::map<std::string, pelementary_transformation> elem_transformations;
345  std::map<std::string, psecondary_domain> secondary_domains;
346 
347  // Structure dealing with time integration scheme
348  int time_integration; // 0 : no, 1 : time step, 2 : init
349  bool init_step;
350  scalar_type time_step; // Time step (dt) for time integration schemes
351  scalar_type init_time_step; // Time step for initialization of derivatives
352 
353  // Structure dealing with simple dof constraints
354  typedef std::map<size_type, scalar_type> real_dof_constraints_var;
355  typedef std::map<size_type, complex_type> complex_dof_constraints_var;
356  mutable std::map<std::string, real_dof_constraints_var>
357  real_dof_constraints;
358  mutable std::map<std::string, complex_dof_constraints_var>
359  complex_dof_constraints;
360  void clear_dof_constraints()
361  { real_dof_constraints.clear(); complex_dof_constraints.clear(); }
362 
363  // Structure dealing with nonlinear expressions
364  struct gen_expr {
365  std::string expr;
366  const mesh_im &mim;
367  size_type region;
368  std::string secondary_domain;
369  gen_expr(const std::string &expr_, const mesh_im &mim_,
370  size_type region_, const std::string &secdom)
371  : expr(expr_), mim(mim_), region(region_), secondary_domain(secdom) {}
372  };
373 
374  // Structure for assignment in assembly
375  struct assignement_desc {
376  std::string varname;
377  std::string expr;
378  size_type region;
379  bool before;
380  size_type order;
381  };
382 
383  std::list<assignement_desc> assignments;
384 
385  mutable std::list<gen_expr> generic_expressions;
386 
387  // Groups of variables for interpolation on different meshes
388  // generic assembly
389  std::map<std::string, std::vector<std::string> > variable_groups;
390 
391  ga_macro_dictionary macro_dict;
392 
393 
394  virtual void actualize_sizes() const;
395  bool check_name_validity(const std::string &name, bool assert=true) const;
396  void brick_init(size_type ib, build_version version,
397  size_type rhs_ind = 0) const;
398 
399  void init() { complex_version = false; act_size_to_be_done = false; }
400 
401  void resize_global_system() const;
402 
403  //to be performed after to_variables is called.
404  virtual void post_to_variables_step();
405 
406  scalar_type approx_external_load_; // Computed by assembly procedure
407  // with BUILD_RHS option.
408 
409  VAR_SET::const_iterator find_variable(const std::string &name) const;
410  const var_description &variable_description(const std::string &name) const;
411 
412  public:
413 
414  void add_generic_expression(const std::string &expr, const mesh_im &mim,
415  size_type region,
416  const std::string &secondary_domain = "") const {
417  generic_expressions.push_back(gen_expr(expr, mim, region,
418  secondary_domain));
419  }
420  void add_external_load(size_type ib, scalar_type e) const
421  { bricks[ib].external_load = e; }
422  scalar_type approx_external_load() { return approx_external_load_; }
423  // call the brick if necessary
424  void update_brick(size_type ib, build_version version) const;
425  void linear_brick_add_to_rhs(size_type ib, size_type ind_data,
426  size_type n_iter) const;
427  void update_affine_dependent_variables();
428  void brick_call(size_type ib, build_version version,
429  size_type rhs_ind = 0) const;
430  model_real_plain_vector &rhs_coeffs_of_brick(size_type ib) const
431  { return bricks[ib].coeffs; }
432  scalar_type &matrix_coeff_of_brick(size_type ib) const
433  { return bricks[ib].matrix_coeff; }
434  bool is_var_newer_than_brick(const std::string &varname,
435  size_type ib, size_type niter = size_type(-1)) const;
436  bool is_var_mf_newer_than_brick(const std::string &varname,
437  size_type ib) const;
438  bool is_mim_newer_than_brick(const mesh_im &mim,
439  size_type ib) const;
440 
441  pbrick brick_pointer(size_type ib) const {
442  GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
443  return bricks[ib].pbr;
444  }
445 
446  void variable_list(varnamelist &vl) const
447  { for (const auto &v : variables) vl.push_back(v.first); }
448 
449  void define_variable_group(const std::string &group_name,
450  const std::vector<std::string> &nl);
451  bool variable_group_exists(const std::string &group_name) const
452  { return variable_groups.count(group_name) > 0; }
453 
454  const std::vector<std::string> &
455  variable_group(const std::string &group_name) const {
456  GMM_ASSERT1(variable_group_exists(group_name),
457  "Undefined variable group " << group_name);
458  return (variable_groups.find(group_name))->second;
459  }
460 
461  void clear_assembly_assignments(void) { assignments.clear(); }
462  void add_assembly_assignments(const std::string &dataname,
463  const std::string &expr,
464  size_type rg = size_type(-1),
465  size_type order = 1,
466  bool before = false);
467 
468  /* function to be called by Dirichlet bricks */
469  void add_real_dof_constraint(const std::string &varname, size_type dof,
470  scalar_type val) const
471  { real_dof_constraints[varname][dof] = val; }
472  /* function to be called by Dirichlet bricks */
473  void add_complex_dof_constraint(const std::string &varname, size_type dof,
474  complex_type val) const
475  { complex_dof_constraints[varname][dof] = val; }
476 
477 
478  void add_temporaries(const varnamelist &vl, gmm::uint64_type id_num) const;
479 
480  const mimlist &mimlist_of_brick(size_type ib) const
481  { return bricks[ib].mims; }
482 
483  const varnamelist &varnamelist_of_brick(size_type ib) const
484  { return bricks[ib].vlist; }
485 
486  const varnamelist &datanamelist_of_brick(size_type ib) const
487  { return bricks[ib].dlist; }
488 
489  size_type region_of_brick(size_type ib) const
490  { return bricks[ib].region; }
491 
492  bool temporary_uptodate(const std::string &varname,
493  gmm::uint64_type id_num, size_type &ind) const;
494 
495  size_type n_iter_of_variable(const std::string &name) const {
496  return variables.count(name) == 0 ? size_type(0)
497  : variables[name].n_iter;
498  }
499 
500  void set_default_iter_of_variable(const std::string &varname,
501  size_type ind) const;
502  void reset_default_iter_of_variables(const varnamelist &vl) const;
503 
504  void update_from_context() const { act_size_to_be_done = true; }
505 
506  const model_real_sparse_matrix &linear_real_matrix_term
507  (size_type ib, size_type iterm);
508 
509  const model_complex_sparse_matrix &linear_complex_matrix_term
510  (size_type ib, size_type iterm);
511 
512  /** Disable a brick. */
514  GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
515  active_bricks.del(ib);
516  }
517 
518  /** Enable a brick. */
520  GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
521  active_bricks.add(ib);
522  }
523 
524  /** Disable a variable (and its attached mutlipliers). */
525  void disable_variable(const std::string &name);
526 
527  /** Enable a variable (and its attached mutlipliers). */
528  void enable_variable(const std::string &name, bool enabled=true);
529 
530  /** States if a name corresponds to a declared variable. */
531  bool variable_exists(const std::string &name) const;
532 
533  /** States if a variable is disabled (treated as data). */
534  bool is_disabled_variable(const std::string &name) const;
535 
536  /** States if a name corresponds to a declared data or disabled variable. */
537  bool is_data(const std::string &name) const;
538 
539  /** States if a name corresponds to a declared data. */
540  bool is_true_data(const std::string &name) const;
541 
542  /** States if a variable is condensed out of the global system. */
543  bool is_internal_variable(const std::string &name) const;
544 
545  bool is_affine_dependent_variable(const std::string &name) const;
546 
547  const std::string &org_variable(const std::string &name) const;
548 
549  const scalar_type &factor_of_variable(const std::string &name) const;
550 
551  void set_factor_of_variable(const std::string &name, scalar_type a);
552 
553  bool is_im_data(const std::string &name) const;
554 
555  const im_data *pim_data_of_variable(const std::string &name) const;
556 
557  const gmm::uint64_type &
558  version_number_of_data_variable(const std::string &varname,
559  size_type niter = size_type(-1)) const;
560 
561  /** Boolean which says if the model deals with real or complex unknowns
562  and data. */
563  bool is_complex() const { return complex_version; }
564 
565  /** Return true if all the model terms do not affect the coercivity of
566  the whole tangent system. */
567  bool is_coercive() const { return is_coercive_; }
568 
569  /** Return true if the model has at least one internal variable. */
570  bool has_internal_variables() const {
571  for (const auto &v : variables)
572  if (v.second.is_internal && !v.second.is_disabled) return true;
573  return false;
574  }
575 
576  /** Return true if all the model terms do not affect the coercivity of
577  the whole tangent system. */
578  bool is_symmetric() const { return is_symmetric_; }
579 
580  /** Return true if all the model terms are linear. */
581  bool is_linear() const { return is_linear_; }
582 
583  /** Total number of degrees of freedom in the model. */
584  size_type nb_dof(bool with_internal=false) const;
585 
586  /** Number of internal degrees of freedom in the model. */
587  size_type nb_internal_dof() const { return nb_dof(true)-nb_dof(); }
588 
589  /** Number of primary degrees of freedom in the model. */
590  size_type nb_primary_dof() const { return nb_dof(); }
591 
592  /** Leading dimension of the meshes used in the model. */
593  dim_type leading_dimension() const { return leading_dim; }
594 
595  /** Gives a non already existing variable name begining by `name`. */
596  std::string new_name(const std::string &name);
597 
598  const gmm::sub_interval &
599  interval_of_variable(const std::string &name) const;
600 
601  /** Gives the access to the vector value of a variable. For the real
602  version. */
603  const model_real_plain_vector &
604  real_variable(const std::string &name, size_type niter) const;
605 
606  /**The same as above, but either accessing the latest variable version,
607  or the previous, if using "Old_" prefix*/
608  const model_real_plain_vector &
609  real_variable(const std::string &name) const;
610 
611  /** Gives the access to the vector value of a variable. For the complex
612  version. */
613  const model_complex_plain_vector &
614  complex_variable(const std::string &name, size_type niter) const;
615 
616  /**The same as above, but either accessing the latest variable version,
617  or the previous, if using "Old_" prefix*/
618  const model_complex_plain_vector &
619  complex_variable(const std::string &name) const;
620 
621  /** Gives the write access to the vector value of a variable. Make a
622  change flag of the variable set. For the real version. */
623  model_real_plain_vector &
624  set_real_variable(const std::string &name, size_type niter) const;
625 
626  /**The same as above, but for either latest variable, or
627  for the previous, if prefixed with "Old_".*/
628  model_real_plain_vector &
629  set_real_variable(const std::string &name) const;
630 
631  /** Gives the write access to the vector value of a variable. Make a
632  change flag of the variable set. For the complex version. */
633  model_complex_plain_vector &
634  set_complex_variable(const std::string &name, size_type niter) const;
635 
636  /**The same as above, but either accessing the latest variable version,
637  or the previous, if using "Old_" prefix*/
638  model_complex_plain_vector &
639  set_complex_variable(const std::string &name) const;
640 
641  model_real_plain_vector &
642  set_real_constant_part(const std::string &name) const;
643 
644  model_complex_plain_vector &
645  set_complex_constant_part(const std::string &name) const;
646 
647  private:
648  template<typename VECTOR, typename T>
649  void from_variables(VECTOR &V, bool with_internal, T) const {
650  for (const auto &v : variables)
651  if (v.second.is_variable && !v.second.is_affine_dependent
652  && !v.second.is_disabled
653  && (with_internal || !v.second.is_internal))
654  gmm::copy(v.second.real_value[0], gmm::sub_vector(V, v.second.I));
655  }
656 
657  template<typename VECTOR, typename T>
658  void from_variables(VECTOR &V, bool with_internal, std::complex<T>) const {
659  for (const auto &v : variables)
660  if (v.second.is_variable && !v.second.is_affine_dependent
661  && !v.second.is_disabled
662  && (with_internal || !v.second.is_internal))
663  gmm::copy(v.second.complex_value[0], gmm::sub_vector(V, v.second.I));
664  }
665 
666  public:
667  template<typename VECTOR>
668  void from_variables(VECTOR &V, bool with_internal=false) const {
669  typedef typename gmm::linalg_traits<VECTOR>::value_type T;
670  context_check(); if (act_size_to_be_done) actualize_sizes();
671  from_variables(V, with_internal, T());
672  }
673 
674  private:
675  template<typename VECTOR, typename T>
676  void to_variables(const VECTOR &V, bool with_internal, T) {
677  for (auto &&v : variables)
678  if (v.second.is_variable && !v.second.is_affine_dependent
679  && !v.second.is_disabled
680  && (with_internal || !v.second.is_internal)) {
681  gmm::copy(gmm::sub_vector(V, v.second.I), v.second.real_value[0]);
682  v.second.v_num_data[0] = act_counter();
683  }
684  update_affine_dependent_variables();
685  this->post_to_variables_step();
686  }
687 
688  template<typename VECTOR, typename T>
689  void to_variables(const VECTOR &V, bool with_internal, std::complex<T>) {
690  for (auto &&v : variables)
691  if (v.second.is_variable && !v.second.is_affine_dependent
692  && !v.second.is_disabled
693  && (with_internal || !v.second.is_internal)) {
694  gmm::copy(gmm::sub_vector(V, v.second.I), v.second.complex_value[0]);
695  v.second.v_num_data[0] = act_counter();
696  }
697  update_affine_dependent_variables();
698  this->post_to_variables_step();
699  }
700 
701  public:
702  template<typename VECTOR>
703  void to_variables(const VECTOR &V, bool with_internal=false) {
704  typedef typename gmm::linalg_traits<VECTOR>::value_type T;
705  context_check(); if (act_size_to_be_done) actualize_sizes();
706  to_variables(V, with_internal, T());
707  }
708 
709  /** Add a fixed size variable to the model assumed to be a vector.
710  niter is the number of version of the variable stored. */
711  void add_fixed_size_variable(const std::string &name, size_type size,
712  size_type niter = 1);
713 
714  /** Add a fixed size variable to the model whith given tensor dimensions.
715  niter is the number of version of the variable stored. */
716  void add_fixed_size_variable(const std::string &name,
717  const bgeot::multi_index &sizes,
718  size_type niter = 1);
719 
720  /** Add a fixed size data to the model. niter is the number of version
721  of the data stored, for time integration schemes. */
722  void add_fixed_size_data(const std::string &name, size_type size,
723  size_type niter = 1);
724 
725  /** Add a fixed size data to the model. niter is the number of version
726  of the data stored, for time integration schemes. */
727  void add_fixed_size_data(const std::string &name,
728  const bgeot::multi_index &sizes,
729  size_type niter = 1);
730 
731  /** Resize a fixed size variable (or data) of the model. */
732  void resize_fixed_size_variable(const std::string &name, size_type size);
733 
734  /** Resize a fixed size variable (or data) of the model. */
735  void resize_fixed_size_variable(const std::string &name,
736  const bgeot::multi_index &sizes);
737 
738  /** Add a fixed size data (assumed to be a vector) to the model and
739  initialized with v. */
740  template <typename VECT>
741  void add_initialized_fixed_size_data(const std::string &name,
742  const VECT &v) {
743  this->add_fixed_size_data(name, gmm::vect_size(v));
744  if (this->is_complex())
745  gmm::copy(v, this->set_complex_variable(name));
746  else
747  gmm::copy(gmm::real_part(v), this->set_real_variable(name));
748  }
749 
750  /** Add a fixed size data (assumed to be a vector) to the model and
751  initialized with v. */
752  template <typename VECT>
753  void add_initialized_fixed_size_data(const std::string &name,
754  const VECT &v,
755  const bgeot::multi_index &sizes) {
756  this->add_fixed_size_data(name, sizes);
757  if (this->is_complex())
758  gmm::copy(v, this->set_complex_variable(name));
759  else
760  gmm::copy(gmm::real_part(v), this->set_real_variable(name));
761  }
762 
763  /** Add a fixed size data (assumed to be a matrix) to the model and
764  initialized with M. */
765  void add_initialized_matrix_data(const std::string &name,
766  const base_matrix &M);
767  void add_initialized_matrix_data(const std::string &name,
768  const base_complex_matrix &M);
769 
770  /** Add a fixed size data (assumed to be a tensor) to the model and
771  initialized with t. */
772  void add_initialized_tensor_data(const std::string &name,
773  const base_tensor &t);
774  void add_initialized_tensor_data(const std::string &name,
775  const base_complex_tensor &t);
776 
777 
778  /** Add a scalar data (i.e. of size 1) to the model initialized with e. */
779  template <typename T>
780  void add_initialized_scalar_data(const std::string &name, T e) {
781  this->add_fixed_size_data(name, 1, 1);
782  if (this->is_complex())
783  this->set_complex_variable(name)[0] = e;
784  else
785  this->set_real_variable(name)[0] = gmm::real(e);
786  }
787 
788 
789  /** Add variable defined at integration points. */
790  void add_im_variable(const std::string &name, const im_data &imd,
791  size_type niter = 1);
792  /** Add internal variable, defined at integration points and condensed. */
793  void add_internal_im_variable(const std::string &name,
794  const im_data &imd);
795  /** Add data defined at integration points. */
796  void add_im_data(const std::string &name, const im_data &imd,
797  size_type niter = 1);
798 
799  /** Add a variable being the dofs of a finite element method to the model.
800  niter is the number of version of the variable stored, for time
801  integration schemes. */
802  void add_fem_variable(const std::string &name, const mesh_fem &mf,
803  size_type niter = 1);
804 
805  /** Add a variable linked to a fem with the dof filtered with respect
806  to a mesh region. Only the dof returned by the dof_on_region
807  method of `mf` will be kept. niter is the number of version
808  of the data stored, for time integration schemes. */
809  void add_filtered_fem_variable(const std::string &name, const mesh_fem &mf,
810  size_type region, size_type niter = 1);
811 
812 
813  /** Add a "virtual" variable be an affine depedent variable with respect
814  to another variable. Mainly used for time integration scheme for
815  instance to represent time derivative of variables.
816  `alpha` is the multiplicative scalar of the dependency. */
817  void add_affine_dependent_variable(const std::string &name,
818  const std::string &org_name,
819  scalar_type alpha = scalar_type(1));
820 
821  /** Add a data being the dofs of a finite element method to the model.*/
822  void add_fem_data(const std::string &name, const mesh_fem &mf,
823  dim_type qdim = 1, size_type niter = 1);
824 
825  /** Add a data being the dofs of a finite element method to the model.*/
826  void add_fem_data(const std::string &name, const mesh_fem &mf,
827  const bgeot::multi_index &sizes, size_type niter = 1);
828 
829  /** Add an initialized fixed size data to the model, assumed to be a
830  vector field if the size of the vector is a multiple of the dof
831  number. */
832  template <typename VECT>
833  void add_initialized_fem_data(const std::string &name, const mesh_fem &mf,
834  const VECT &v) {
835  this->add_fem_data(name, mf,
836  dim_type(gmm::vect_size(v) / mf.nb_dof()), 1);
837  if (this->is_complex())
838  gmm::copy(v, this->set_complex_variable(name));
839  else
840  gmm::copy(gmm::real_part(v), this->set_real_variable(name));
841  }
842 
843  /** Add a fixed size data to the model. The data is a tensor of given
844  sizes on each dof of the finite element method. */
845  template <typename VECT>
846  void add_initialized_fem_data(const std::string &name, const mesh_fem &mf,
847  const VECT &v,
848  const bgeot::multi_index &sizes) {
849  this->add_fem_data(name, mf, sizes, 1);
850  if (this->is_complex())
851  gmm::copy(v, this->set_complex_variable(name));
852  else
853  gmm::copy(gmm::real_part(v), this->set_real_variable(name));
854  }
855 
856  /** Add a particular variable linked to a fem being a multiplier with
857  respect to a primal variable. The dof will be filtered with the
858  gmm::range_basis function applied on the terms of the model which
859  link the multiplier and the primal variable. Optimized for boundary
860  multipliers. niter is the number of version of the data stored,
861  for time integration schemes. */
862  void add_multiplier(const std::string &name, const mesh_fem &mf,
863  const std::string &primal_name,
864  size_type niter = 1);
865 
866  /** Add a particular variable linked to a fem being a multiplier with
867  respect to a primal variable and a region. The dof will be filtered
868  both with the gmm::range_basis function applied on the terms of
869  the model which link the multiplier and the primal variable and on
870  the dof on the given region. Optimized for boundary
871  multipliers. niter is the number of version of the data stored,
872  for time integration schemes. */
873  void add_multiplier(const std::string &name, const mesh_fem &mf,
874  size_type region, const std::string &primal_name,
875  size_type niter = 1);
876 
877  /** Add a particular variable linked to a fem being a multiplier with
878  respect to a primal variable. The dof will be filtered with the
879  gmm::range_basis function applied on the mass matrix between the fem
880  of the multiplier and the one of the primal variable.
881  Optimized for boundary multipliers. niter is the number of version
882  of the data stored, for time integration schemes. */
883  void add_multiplier(const std::string &name, const mesh_fem &mf,
884  const std::string &primal_name, const mesh_im &mim,
885  size_type region, size_type niter = 1);
886 
887  /** Dictonnary of user defined macros. */
888  const ga_macro_dictionary &macro_dictionary() const { return macro_dict; }
889 
890  /** Add a macro definition for the high generic assembly language.
891  This macro can be used for the definition of generic assembly bricks.
892  The name of a macro cannot coincide with a variable name. */
893  void add_macro(const std::string &name, const std::string &expr);
894 
895  /** Delete a previously defined macro definition. */
896  void del_macro(const std::string &name);
897 
898  /** Says if a macro of that name has been defined. */
899  bool macro_exists(const std::string &name) const
900  { return macro_dict.macro_exists(name); }
901 
902  /** Delete a variable or data of the model. */
903  void delete_variable(const std::string &varname);
904 
905  /** Gives the access to the mesh_fem of a variable if any. Throw an
906  exception otherwise. */
907  const mesh_fem &mesh_fem_of_variable(const std::string &name) const;
908 
909  /** Gives a pointer to the mesh_fem of a variable if any. 0 otherwise.*/
910  const mesh_fem *pmesh_fem_of_variable(const std::string &name) const;
911 
912 
913  bgeot::multi_index qdims_of_variable(const std::string &name) const;
914  size_type qdim_of_variable(const std::string &name) const;
915 
916  /** Gives the access to the tangent matrix. For the real version. */
917  const model_real_sparse_matrix &
918  real_tangent_matrix(bool internal=false) const {
919  GMM_ASSERT1(!complex_version, "This model is a complex one");
920  context_check(); if (act_size_to_be_done) actualize_sizes();
921  return internal ? internal_rTM : rTM;
922  }
923 
924  /** Gives the access to the tangent matrix. For the complex version. */
925  const model_complex_sparse_matrix &complex_tangent_matrix() const {
926  GMM_ASSERT1(complex_version, "This model is a real one");
927  context_check(); if (act_size_to_be_done) actualize_sizes();
928  return cTM;
929  }
930 
931  /** Gives access to the right hand side of the tangent linear system.
932  For the real version. An assembly of the rhs has to be done first. */
933  const model_real_plain_vector &real_rhs(bool with_internal=false) const {
934  GMM_ASSERT1(!complex_version, "This model is a complex one");
935  context_check(); if (act_size_to_be_done) actualize_sizes();
936  return (with_internal && gmm::vect_size(full_rrhs)) ? full_rrhs : rrhs;
937  }
938 
939  /** Gives write access to the right hand side of the tangent linear system.
940  Some solvers need to manipulate the model rhs directly so that for
941  example internal condensed variables can be treated properly. */
942  model_real_plain_vector &set_real_rhs(bool with_internal=false) const {
943  GMM_ASSERT1(!complex_version, "This model is a complex one");
944  context_check(); if (act_size_to_be_done) actualize_sizes();
945  return (with_internal && gmm::vect_size(full_rrhs)) ? full_rrhs : rrhs;
946  }
947 
948  /** Gives access to the partial solution for condensed internal variables.
949  A matrix assembly with condensation has to be done first. */
950  const model_real_plain_vector &internal_solution() const {
951  GMM_ASSERT1(!complex_version, "This model is a complex one");
952  context_check(); if (act_size_to_be_done) actualize_sizes();
953  return internal_sol;
954  }
955 
956  /** Gives access to the part of the right hand side of a term of
957  a particular nonlinear brick. Does not account of the eventual time
958  dispatcher. An assembly of the rhs has to be done first.
959  For the real version. */
960  const model_real_plain_vector &real_brick_term_rhs
961  (size_type ib, size_type ind_term = 0, bool sym = false,
962  size_type ind_iter = 0) const
963  {
964  GMM_ASSERT1(!complex_version, "This model is a complex one");
965  context_check(); if (act_size_to_be_done) actualize_sizes();
966  GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
967  GMM_ASSERT1(ind_term < bricks[ib].tlist.size(), "Inexistent term");
968  GMM_ASSERT1(ind_iter < bricks[ib].nbrhs, "Inexistent iter");
969  GMM_ASSERT1(!sym || bricks[ib].tlist[ind_term].is_symmetric,
970  "Term is not symmetric");
971  if (sym)
972  return bricks[ib].rveclist_sym[ind_iter][ind_term];
973  else
974  return bricks[ib].rveclist[ind_iter][ind_term];
975  }
976 
977  /** Gives access to the right hand side of the tangent linear system.
978  For the complex version. */
979  const model_complex_plain_vector &complex_rhs() const {
980  GMM_ASSERT1(complex_version, "This model is a real one");
981  context_check(); if (act_size_to_be_done) actualize_sizes();
982  return crhs;
983  }
984 
985  /** Gives write access to the right hand side of the tangent linear system.
986  Some solvers need to manipulate the model rhs directly so that for
987  example internal condensed variables can be treated properly. */
988  model_complex_plain_vector &set_complex_rhs() const {
989  GMM_ASSERT1(complex_version, "This model is a real one");
990  context_check(); if (act_size_to_be_done) actualize_sizes();
991  return crhs;
992  }
993 
994  /** Gives access to the part of the right hand side of a term of a
995  particular nonlinear brick. Does not account of the eventual time
996  dispatcher. An assembly of the rhs has to be done first.
997  For the complex version. */
998  const model_complex_plain_vector &complex_brick_term_rhs
999  (size_type ib, size_type ind_term = 0, bool sym = false,
1000  size_type ind_iter = 0) const
1001  {
1002  GMM_ASSERT1(!complex_version, "This model is a complex one");
1003  context_check(); if (act_size_to_be_done) actualize_sizes();
1004  GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
1005  GMM_ASSERT1(ind_term < bricks[ib].tlist.size(), "Inexistent term");
1006  GMM_ASSERT1(ind_iter < bricks[ib].nbrhs, "Inexistent iter");
1007  GMM_ASSERT1(!sym || bricks[ib].tlist[ind_term].is_symmetric,
1008  "Term is not symmetric");
1009  if (sym)
1010  return bricks[ib].cveclist_sym[ind_iter][ind_term];
1011  else
1012  return bricks[ib].cveclist[ind_iter][ind_term];
1013  }
1014 
1015  /** List the model variables and constant. */
1016  void listvar(std::ostream &ost) const;
1017 
1018  void listresiduals(std::ostream &ost) const;
1019 
1020  /** List the model bricks. */
1021  void listbricks(std::ostream &ost, size_type base_id = 0) const;
1022 
1023  /** Return the model brick ids. */
1024  const dal::bit_vector& get_active_bricks() const {
1025  return active_bricks;
1026  }
1027 
1028  /** Force the re-computation of a brick for the next assembly. */
1030  GMM_ASSERT1(valid_bricks[ib], "Inexistent brick");
1031  bricks[ib].terms_to_be_computed = true;
1032  }
1033 
1034  /** Add a brick to the model. varname is the list of variable used
1035  and datanames the data used. If a variable is used as a data, it
1036  should be declared in the datanames (it will depend on the value of
1037  the variable not only on the fem). Returns the brick index. */
1038  size_type add_brick(pbrick pbr, const varnamelist &varnames,
1039  const varnamelist &datanames,
1040  const termlist &terms, const mimlist &mims,
1041  size_type region);
1042 
1043  /** Delete the brick of index ib from the model. */
1044  void delete_brick(size_type ib);
1045 
1046  /** Add an integration method to a brick. */
1047  void add_mim_to_brick(size_type ib, const mesh_im &mim);
1048 
1049  /** Change the term list of a brick. Used for very special bricks only. */
1050  void change_terms_of_brick(size_type ib, const termlist &terms);
1051 
1052  /** Change the variable list of a brick. Used for very special bricks only.
1053  */
1054  void change_variables_of_brick(size_type ib, const varnamelist &vl);
1055 
1056  /** Change the data list of a brick. Used for very special bricks only.
1057  */
1058  void change_data_of_brick(size_type ib, const varnamelist &vl);
1059 
1060  /** Change the mim list of a brick. Used for very special bricks only.
1061  */
1062  void change_mims_of_brick(size_type ib, const mimlist &ml);
1063 
1064  /** Change the update flag of a brick. Used for very special bricks only.
1065  */
1066  void change_update_flag_of_brick(size_type ib, bool flag);
1067 
1068  void set_time(scalar_type t = scalar_type(0), bool to_init = true);
1069 
1070  scalar_type get_time();
1071 
1072  void set_time_step(scalar_type dt) { time_step = dt; }
1073  scalar_type get_time_step() const { return time_step; }
1074  scalar_type get_init_time_step() const { return init_time_step; }
1075  int is_time_integration() const { return time_integration; }
1076  void set_time_integration(int ti) { time_integration = ti; }
1077  bool is_init_step() const { return init_step; }
1078  void cancel_init_step() { init_step = false; }
1079  void call_init_affine_dependent_variables(int version);
1080  void shift_variables_for_time_integration();
1081  void copy_init_time_derivative();
1082  void add_time_integration_scheme(const std::string &varname,
1083  ptime_scheme ptsc);
1084  void perform_init_time_derivative(scalar_type ddt)
1085  { init_step = true; init_time_step = ddt; }
1086 
1087 
1088  /** Add a time dispacther to a brick. */
1089  void add_time_dispatcher(size_type ibrick, pdispatcher pdispatch);
1090 
1091  void set_dispatch_coeff();
1092 
1093  /** For transient problems. Initialisation of iterations. */
1094  virtual void first_iter();
1095 
1096  /** For transient problems. Prepare the next iterations. In particular
1097  shift the version of the variables.
1098  */
1099  virtual void next_iter();
1100 
1101  /** Add an interpolate transformation to the model to be used with the
1102  generic assembly.
1103  */
1104  void add_interpolate_transformation(const std::string &name,
1105  pinterpolate_transformation ptrans) {
1106  if (secondary_domain_exists(name))
1107  GMM_ASSERT1(false, "An secondary domain with the same "
1108  "name already exists");
1109  if (transformations.count(name) > 0)
1110  GMM_ASSERT1(name.compare("neighbor_element"), "neighbor_element is a "
1111  "reserved interpolate transformation name");
1112  transformations[name] = ptrans;
1113  }
1114 
1115  /** Get a pointer to the interpolate transformation `name`.
1116  */
1117  pinterpolate_transformation
1118  interpolate_transformation(const std::string &name) const {
1119  std::map<std::string, pinterpolate_transformation>::const_iterator
1120  it = transformations.find(name);
1121  GMM_ASSERT1(it != transformations.end(), "Inexistent transformation " << name);
1122  return it->second;
1123  }
1124 
1125  /** Tests if `name` corresponds to an interpolate transformation.
1126  */
1127  bool interpolate_transformation_exists(const std::string &name) const
1128  { return transformations.count(name) > 0; }
1129 
1130  /** Add an elementary transformation to the model to be used with the
1131  generic assembly.
1132  */
1133  void add_elementary_transformation(const std::string &name,
1134  pelementary_transformation ptrans) {
1135  elem_transformations[name] = ptrans;
1136  }
1137 
1138  /** Get a pointer to the elementary transformation `name`.
1139  */
1140  pelementary_transformation
1141  elementary_transformation(const std::string &name) const {
1142  std::map<std::string, pelementary_transformation>::const_iterator
1143  it = elem_transformations.find(name);
1144  GMM_ASSERT1(it != elem_transformations.end(),
1145  "Inexistent elementary transformation " << name);
1146  return it->second;
1147  }
1148 
1149  /** Tests if `name` corresponds to an elementary transformation.
1150  */
1151  bool elementary_transformation_exists(const std::string &name) const
1152  { return elem_transformations.count(name) > 0; }
1153 
1154 
1155  /** Add a secondary domain to the model to be used with the
1156  generic assembly.
1157  */
1158  void add_secondary_domain(const std::string &name,
1159  psecondary_domain ptrans) {
1160  if (interpolate_transformation_exists(name))
1161  GMM_ASSERT1(false, "An interpolate transformation with the same "
1162  "name already exists");secondary_domains[name] = ptrans;
1163  }
1164 
1165  /** Get a pointer to the interpolate transformation `name`.
1166  */
1167  psecondary_domain
1168  secondary_domain(const std::string &name) const {
1169  auto it = secondary_domains.find(name);
1170  GMM_ASSERT1(it != secondary_domains.end(),
1171  "Inexistent transformation " << name);
1172  return it->second;
1173  }
1174 
1175  /** Tests if `name` corresponds to an interpolate transformation.
1176  */
1177  bool secondary_domain_exists(const std::string &name) const
1178  { return secondary_domains.count(name) > 0; }
1179 
1180  /** Gives the name of the variable of index `ind_var` of the brick
1181  of index `ind_brick`. */
1182  const std::string &varname_of_brick(size_type ind_brick,
1183  size_type ind_var);
1184 
1185  /** Gives the name of the data of index `ind_data` of the brick
1186  of index `ind_brick`. */
1187  const std::string &dataname_of_brick(size_type ind_brick,
1188  size_type ind_data);
1189 
1190  /** Assembly of the tangent system taking into account all enabled
1191  terms in the model.
1192 
1193  version = BUILD_RHS
1194  assembles the rhs only for the primary variables, accessible with
1195  ::real_rhs() = ::real_rhs(false)
1196 
1197  version = BUILD_MATRIX
1198  assembles the tangent matrix only for the primary variables,
1199  accessible with ::real_tangent_matrix() = ::real_tangent_matrix(false)
1200 
1201  version = BUILD_ALL
1202  assembles the rhs and the tangent matrix only for primary variables
1203 
1204  version = BUILD_RHS_WITH_LIN
1205  assembles the rhs, including linear terms
1206 
1207  version = BUILD_RHS_WITH_INTERNAL
1208  assembles the rhs of both primary and internal variables, accessible
1209  with ::real_rhs(true), no condensation is performed
1210  the part of the rhs for primary variables is still accessible with
1211  ::real_rhs() = ::real_rhs(false)
1212 
1213  version = BUILD_MATRIX_CONDENSED
1214  assembles the condensed tangent system for the primary system,
1215  accessible with ::real_tangent_matrix() = ::real_tangent_matrix(false)
1216  as well as the coupling tangent matrix between internal and
1217  primary variables accessible with ::real_tangent_matrix(true)
1218 
1219  Moreover, the condensed rhs for primary variables will be computed
1220  based on whatever is currently contained in the full rhs. The
1221  condensed rhs is accessible with ::real_rhs() = ::real_rhs(false)
1222  the unmodified content of the full rhs is still accessible with
1223  ::real_rhs(true)
1224 
1225  version = BUILD_ALL_CONDENSED
1226  assembles the full rhs first and then it assembles the condensed
1227  tangent matrix and the condensed rhs
1228  */
1229  virtual void assembly(build_version version);
1230 
1231  /** Gives the assembly string corresponding to the Neumann term of
1232  the fem variable `varname` on `region`. It is deduced from the
1233  assembly string declared by the model bricks.
1234  `region` should be the index of a boundary region
1235  on the mesh where `varname` is defined. Care to call this function
1236  only after all the volumic bricks have been declared.
1237  Complains, if a brick omit to declare an assembly string.
1238  */
1239  std::string Neumann_term(const std::string &varname, size_type region);
1240 
1241  virtual void clear();
1242 
1243  explicit model(bool comp_version = false);
1244 
1245  /** check consistency of RHS and Stiffness matrix for brick with
1246  @param ind_brick - index of the brick
1247  */
1248  void check_brick_stiffness_rhs(size_type ind_brick) const;
1249 
1250 
1251  };
1252 
1253  //=========================================================================
1254  //
1255  // Time integration scheme object.
1256  //
1257  //=========================================================================
1258 
1259  /** The time integration scheme object provides the necessary methods
1260  for the model object to apply a time integration scheme to an
1261  evolutionnary problem.
1262  **/
1263  class APIDECL virtual_time_scheme {
1264 
1265  public:
1266 
1267  virtual void init_affine_dependent_variables(model &md) const = 0;
1268  virtual void init_affine_dependent_variables_precomputation(model &md)
1269  const = 0;
1270  virtual void time_derivative_to_be_initialized
1271  (std::string &name_v, std::string &name_previous_v) const = 0;
1272  virtual void shift_variables(model &md) const = 0;
1273  virtual ~virtual_time_scheme() {}
1274  };
1275 
1276  void add_theta_method_for_first_order(model &md, const std::string &varname,
1277  scalar_type theta);
1278 
1279  void add_theta_method_for_second_order(model &md, const std::string &varname,
1280  scalar_type theta);
1281 
1282  void add_Newmark_scheme(model &md, const std::string &varname,
1283  scalar_type beta, scalar_type gamma);
1284 
1285  void add_Houbolt_scheme(model &md, const std::string &varname);
1286 
1287 
1288 
1289  //=========================================================================
1290  //
1291  // Time dispatcher object.
1292  //
1293  //=========================================================================
1294 
1295  /** The time dispatcher object modify the result of a brick in order to
1296  apply a time integration scheme.
1297  **/
1298  class APIDECL virtual_dispatcher {
1299 
1300  protected:
1301 
1302  size_type nbrhs_;
1303  std::vector<std::string> param_names;
1304 
1305  public:
1306 
1307  size_type nbrhs() const { return nbrhs_; }
1308 
1309  typedef model::build_version build_version;
1310 
1311  virtual void set_dispatch_coeff(const model &, size_type) const
1312  { GMM_ASSERT1(false, "Time dispatcher with not set_dispatch_coeff !"); }
1313 
1314  virtual void next_real_iter
1315  (const model &, size_type, const model::varnamelist &,
1316  const model::varnamelist &,
1317  model::real_matlist &,
1318  std::vector<model::real_veclist> &,
1319  std::vector<model::real_veclist> &,
1320  bool) const {
1321  GMM_ASSERT1(false, "Time dispatcher with not defined first real iter !");
1322  }
1323 
1324  virtual void next_complex_iter
1325  (const model &, size_type, const model::varnamelist &,
1326  const model::varnamelist &,
1327  model::complex_matlist &,
1328  std::vector<model::complex_veclist> &,
1329  std::vector<model::complex_veclist> &,
1330  bool) const{
1331  GMM_ASSERT1(false,"Time dispatcher with not defined first comples iter");
1332  }
1333 
1334  virtual void asm_real_tangent_terms
1335  (const model &, size_type,
1336  model::real_matlist &, std::vector<model::real_veclist> &,
1337  std::vector<model::real_veclist> &,
1338  build_version) const {
1339  GMM_ASSERT1(false, "Time dispatcher with not defined real tangent "
1340  "terms !");
1341  }
1342 
1343  virtual void asm_complex_tangent_terms
1344  (const model &, size_type,
1345  model::complex_matlist &, std::vector<model::complex_veclist> &,
1346  std::vector<model::complex_veclist> &,
1347  build_version) const {
1348  GMM_ASSERT1(false, "Time dispatcher with not defined complex tangent "
1349  "terms !");
1350  }
1351 
1352  virtual_dispatcher(size_type _nbrhs) : nbrhs_(_nbrhs) {
1353  GMM_ASSERT1(_nbrhs > 0, "Time dispatcher with no rhs");
1354  }
1355  virtual ~virtual_dispatcher() {}
1356 
1357  };
1358 
1359  // ----------------------------------------------------------------------
1360  //
1361  // theta-method dispatcher
1362  //
1363  // ----------------------------------------------------------------------
1364 
1365  class APIDECL theta_method_dispatcher : public virtual_dispatcher {
1366 
1367  public:
1368 
1369  typedef model::build_version build_version;
1370 
1371  void set_dispatch_coeff(const model &md, size_type ib) const;
1372 
1373  template <typename MATLIST, typename VECTLIST>
1374  inline void next_iter(const model &md, size_type ib,
1375  const model::varnamelist &/* vl */,
1376  const model::varnamelist &/* dl */,
1377  MATLIST &/* matl */,
1378  VECTLIST &vectl, VECTLIST &vectl_sym,
1379  bool first_iter) const {
1380  if (first_iter) md.update_brick(ib, model::BUILD_RHS);
1381 
1382  // shift the rhs
1383  for (size_type i = 0; i < vectl[0].size(); ++i)
1384  gmm::copy(vectl[0][i], vectl[1][i]);
1385  for (size_type i = 0; i < vectl_sym[0].size(); ++i)
1386  gmm::copy(vectl_sym[0][i], vectl_sym[1][i]);
1387 
1388  // add the component represented by the linear matrix terms to the
1389  // supplementary rhs
1390  md.linear_brick_add_to_rhs(ib, 1, 0);
1391  }
1392 
1393  void next_real_iter
1394  (const model &md, size_type ib, const model::varnamelist &vl,
1395  const model::varnamelist &dl, model::real_matlist &matl,
1396  std::vector<model::real_veclist> &vectl,
1397  std::vector<model::real_veclist> &vectl_sym, bool first_iter) const;
1398 
1399  void next_complex_iter
1400  (const model &md, size_type ib, const model::varnamelist &vl,
1401  const model::varnamelist &dl,
1402  model::complex_matlist &matl,
1403  std::vector<model::complex_veclist> &vectl,
1404  std::vector<model::complex_veclist> &vectl_sym,
1405  bool first_iter) const;
1406 
1407  void asm_real_tangent_terms
1408  (const model &md, size_type ib, model::real_matlist &/* matl */,
1409  std::vector<model::real_veclist> &/* vectl */,
1410  std::vector<model::real_veclist> &/* vectl_sym */,
1411  build_version version) const;
1412 
1413  virtual void asm_complex_tangent_terms
1414  (const model &md, size_type ib, model::complex_matlist &/* matl */,
1415  std::vector<model::complex_veclist> &/* vectl */,
1416  std::vector<model::complex_veclist> &/* vectl_sym */,
1417  build_version version) const;
1418 
1419  theta_method_dispatcher(const std::string &THETA);
1420  };
1421 
1422  //=========================================================================
1423  //
1424  // Functions adding standard time dispatchers.
1425  //
1426  //=========================================================================
1427 
1428  /** Add a theta-method time dispatcher to a list of bricks. For instance,
1429  a matrix term $K$ will be replaced by
1430  $\theta K U^{n+1} + (1-\theta) K U^{n}$.
1431  */
1432  void APIDECL add_theta_method_dispatcher(model &md, dal::bit_vector ibricks,
1433  const std::string &THETA);
1434 
1435  /** Function which udpate the velocity $v^{n+1}$ after the computation
1436  of the displacement $u^{n+1}$ and before the next iteration. Specific
1437  for theta-method and when the velocity is included in the data
1438  of the model.
1439  */
1441  (model &md, const std::string &U, const std::string &V,
1442  const std::string &pdt, const std::string &ptheta);
1443 
1444 
1445  /** Add a midpoint time dispatcher to a list of bricks. For instance,
1446  a nonlinear term $K(U)$ will be replaced by
1447  $K((U^{n+1} + U^{n})/2)$.
1448  */
1449  void APIDECL add_midpoint_dispatcher(model &md, dal::bit_vector ibricks);
1450 
1451  /** Function which udpate the velocity $v^{n+1}$ after the computation
1452  of the displacement $u^{n+1}$ and before the next iteration. Specific
1453  for Newmark scheme and when the velocity is included in the data
1454  of the model. This version inverts the mass matrix by a conjugate
1455  gradient.
1456  */
1458  (model &md, size_type id2dt2b, const std::string &U, const std::string &V,
1459  const std::string &pdt, const std::string &ptwobeta,
1460  const std::string &pgamma);
1461 
1462  //=========================================================================
1463  //
1464  // Brick object.
1465  //
1466  //=========================================================================
1467 
1468  /** The virtual brick has to be derived to describe real model bricks.
1469  The set_flags method has to be called by the derived class.
1470  The virtual methods asm_real_tangent_terms and/or
1471  asm_complex_tangent_terms have to be defined.
1472  The brick should not store data. The data have to be stored in the
1473  model object.
1474  **/
1475  class APIDECL virtual_brick {
1476  protected:
1477  bool islinear; // The brick add a linear term or not.
1478  bool issymmetric; // The brick add a symmetric term or not.
1479  bool iscoercive; // The brick add a potentially coercive terms or not.
1480  // (in particular, not a term involving a multiplier)
1481  bool isreal; // The brick admits a real version or not.
1482  bool iscomplex; // The brick admits a complex version or not.
1483  bool isinit; // internal flag.
1484  bool compute_each_time; // The brick is linear but needs to be computed
1485  // each time it is evaluated.
1486  bool isUpdateBrick; // The brick does not contribute any terms to the
1487  // system matrix or right-hand side, but only updates state variables.
1488  std::string name; // Name of the brick.
1489 
1490  public:
1491 
1492  typedef model::build_version build_version;
1493 
1494  virtual_brick() { isinit = false; }
1495  virtual ~virtual_brick() { }
1496  void set_flags(const std::string &bname, bool islin, bool issym,
1497  bool iscoer, bool ire, bool isco, bool each_time = false) {
1498  name = bname;
1499  islinear = islin; issymmetric = issym; iscoercive = iscoer;
1500  isreal = ire; iscomplex = isco; isinit = true;
1501  compute_each_time = each_time;
1502  }
1503 
1504 # define BRICK_NOT_INIT GMM_ASSERT1(isinit, "Set brick flags !")
1505  bool is_linear() const { BRICK_NOT_INIT; return islinear; }
1506  bool is_symmetric() const { BRICK_NOT_INIT; return issymmetric; }
1507  bool is_coercive() const { BRICK_NOT_INIT; return iscoercive; }
1508  bool is_real() const { BRICK_NOT_INIT; return isreal; }
1509  bool is_complex() const { BRICK_NOT_INIT; return iscomplex; }
1510  bool is_to_be_computed_each_time() const
1511  { BRICK_NOT_INIT; return compute_each_time; }
1512  const std::string &brick_name() const { BRICK_NOT_INIT; return name; }
1513 
1514 
1515  /** Assembly of bricks real tangent terms.
1516  In case of Getfem's compilation with OpenMP option,
1517  this method is executed on multiple threads.
1518  The parallelism is provided by distributing all tangent matrices and
1519  vectors and accumulating them later into the original. Additionally,
1520  by default, all mesh_region objects, participating in the assembly,
1521  are also partitioned. In order to avoid data race conditions, this
1522  method should not modify any data simultaneously accessible from
1523  multiple threads. In case this is unavoidable, the race can be
1524  prevented by distributing this data (of type T) between the threads
1525  via getfem::omp_distribute<T> (prefered method) or
1526  protected from concurrent access with mutexes (e.g. getfem::omp_lock)
1527  or OpenMP critical section. */
1528  virtual void asm_real_tangent_terms(const model &, size_type,
1529  const model::varnamelist &,
1530  const model::varnamelist &,
1531  const model::mimlist &,
1532  model::real_matlist &,
1533  model::real_veclist &,
1534  model::real_veclist &,
1535  size_type, build_version) const
1536  { /** doesn't have to be overriden if serial pre- post- assemblies are
1537  defined */
1538  }
1539 
1540 
1541  /** Assembly of bricks complex tangent terms.
1542  In case of Getfem's compilation with OpenMP option,
1543  this method is executed on multiple threads.
1544  The parallelism is provided by distributing all tangent matrices and
1545  vectors and accumulating them later into the original. Additionally,
1546  by default, all mesh_region objects, participating in the assembly,
1547  are also partitioned. In order to avoid data race conditions, this
1548  method should not modify any data simultaneously accessible from
1549  multiple threads. In case this is unavoidable, the race can be
1550  prevented by distributing this data (of type T) between the threads
1551  via getfem::omp_distribute<T> (prefered method) or
1552  protected from concurrent access with mutexes (e.g. getfem::omp_lock)
1553  or OpenMP critical section. */
1555  const model::varnamelist &,
1556  const model::varnamelist &,
1557  const model::mimlist &,
1558  model::complex_matlist &,
1559  model::complex_veclist &,
1560  model::complex_veclist &,
1561  size_type, build_version) const
1562  { /** doesn't have to be overriden if serial pre- post- assemblies are
1563  defined*/
1564  }
1565 
1566 
1567  /** Peform any pre assembly action for real term assembly. The purpose of
1568  this method is to do any action that cannot be peformed in the main
1569  assembly routines in parallel.
1570  Possible action can be modification of the model object, cashing
1571  some data that cannot be distributed etc. */
1573  const model::varnamelist &,
1574  const model::varnamelist &,
1575  const model::mimlist &,
1576  model::real_matlist &,
1577  model::real_veclist &,
1578  model::real_veclist &,
1579  size_type, build_version) const { };
1580 
1581  /** Peform any pre assembly action for complex term assembly. The purpose
1582  of this method is to do any action that cannot be peformed in the
1583  main assembly routines in parallel.
1584  Possible action can be modification of the model object, cashing
1585  some data that cannot be distributed etc. */
1587  const model::varnamelist &,
1588  const model::varnamelist &,
1589  const model::mimlist &,
1590  model::complex_matlist &,
1591  model::complex_veclist &,
1592  model::complex_veclist &,
1593  size_type, build_version) const { };
1594 
1595  /** Peform any post assembly action for real terms. The purpose of this
1596  method is to do any action that cannot be peformed in the main
1597  assembly routines in parallel.
1598  Possible action can be modification of the model object, cashing
1599  some data that cannot be distributed etc. */
1601  const model::varnamelist &,
1602  const model::varnamelist &,
1603  const model::mimlist &,
1604  model::real_matlist &,
1605  model::real_veclist &,
1606  model::real_veclist &,
1607  size_type, build_version) const { };
1608 
1609  /** Peform any post assembly action for complex terms. The purpose of this
1610  method is to do any action that cannot be peformed in the main
1611  assembly routines in parallel.
1612  Possible action can be modification of the model object, cashing
1613  some data that cannot be distributed etc. */
1615  const model::varnamelist &,
1616  const model::varnamelist &,
1617  const model::mimlist &,
1618  model::complex_matlist &,
1619  model::complex_veclist &,
1620  model::complex_veclist &,
1621  size_type, build_version) const { };
1622 
1623 
1624  /** check consistency of stiffness matrix and rhs */
1625  void check_stiffness_matrix_and_rhs(const model &, size_type,
1626  const model::termlist& tlist,
1627  const model::varnamelist &,
1628  const model::varnamelist &,
1629  const model::mimlist &,
1630  model::real_matlist &,
1631  model::real_veclist &,
1632  model::real_veclist &, size_type rg,
1633  const scalar_type delta = 1e-8) const;
1634  /** The brick may declare an assembly string for the computation of the
1635  Neumann terms (in order to prescribe boundary conditions with
1636  Nitche's method). */
1638  (const model &, size_type, const model::varnamelist &,
1639  const model::varnamelist &) const {
1640  GMM_ASSERT1(false, "No assemby string declared, computation of Neumann "
1641  "term impossible for brick " << name);
1642  }
1643 
1644  private:
1645  /** simultaneous call to real_pre_assembly, real_assembly
1646  and real_post_assembly */
1647  void full_asm_real_tangent_terms_(const model &, size_type,
1648  const model::varnamelist &,
1649  const model::varnamelist &,
1650  const model::mimlist &,
1651  model::real_matlist &,
1652  model::real_veclist &,
1653  model::real_veclist &,
1654  size_type, build_version) const;
1655  };
1656 
1657  //=========================================================================
1658  //
1659  // Functions adding standard bricks to the model.
1660  //
1661  //=========================================================================
1662 
1663  /** Add a term given by the weak form language expression `expr` which will
1664  be assembled in region `region` and with the integration method `mim`.
1665  Only the matrix term will be taken into account, assuming that it is
1666  linear.
1667  The advantage of declaring a term linear instead of nonlinear is that
1668  it will be assembled only once and no assembly is necessary for the
1669  residual.
1670  Take care that if the expression contains some variables and if the
1671  expression is a potential or of first order (i.e. describe the weak
1672  form, not the derivative of the weak form), the expression will be
1673  derivated with respect to all variables.
1674  You can specify if the term is symmetric, coercive or not.
1675  If you are not sure, the better is to declare the term not symmetric
1676  and not coercive. But some solvers (conjugate gradient for instance)
1677  are not allowed for non-coercive problems.
1678  `brickname` is an optional name for the brick.
1679  */
1680  size_type APIDECL add_linear_term
1681  (model &md, const mesh_im &mim, const std::string &expr,
1682  size_type region = size_type(-1), bool is_sym = false,
1683  bool is_coercive = false, const std::string &brickname = "",
1684  bool return_if_nonlin = false);
1685 
1686  inline size_type APIDECL add_linear_generic_assembly_brick
1687  (model &md, const mesh_im &mim, const std::string &expr,
1688  size_type region = size_type(-1), bool is_sym = false,
1689  bool is_coercive = false, const std::string &brickname = "",
1690  bool return_if_nonlin = false) {
1691  return add_linear_term(md, mim, expr, region, is_sym,
1692  is_coercive, brickname, return_if_nonlin);
1693  }
1694 
1695  /** Add a nonlinear term given by the weak form language expression `expr`
1696  which will be assembled in region `region` and with the integration
1697  method `mim`.
1698  The expression can describe a potential or a weak form. Second order
1699  terms (i.e. containing second order test functions, Test2) are not
1700  allowed.
1701  You can specify if the term is symmetric, coercive or not.
1702  If you are not sure, the better is to declare the term not symmetric
1703  and not coercive. But some solvers (conjugate gradient for instance)
1704  are not allowed for non-coercive problems.
1705  `brickname` is an optional name for the brick.
1706  */
1708  (model &md, const mesh_im &mim, const std::string &expr,
1709  size_type region = size_type(-1), bool is_sym = false,
1710  bool is_coercive = false, const std::string &brickname = "");
1711 
1712  inline size_type APIDECL add_nonlinear_generic_assembly_brick
1713  (model &md, const mesh_im &mim, const std::string &expr,
1714  size_type region = size_type(-1), bool is_sym = false,
1715  bool is_coercive = false, const std::string &brickname = "") {
1716  return add_nonlinear_term(md, mim, expr, region,
1717  is_sym, is_coercive, brickname);
1718  }
1719 
1720 
1721  /** Add a source term given by the assembly string `expr` which will
1722  be assembled in region `region` and with the integration method `mim`.
1723  Only the residual term will be taken into account.
1724  Take care that if the expression contains some variables and if the
1725  expression is a potential, the expression will be
1726  derivated with respect to all variables.
1727  `brickname` is an optional name for the brick.
1728  */
1729  size_type APIDECL add_source_term
1730  (model &md, const mesh_im &mim, const std::string &expr,
1731  size_type region = size_type(-1),
1732  const std::string &brickname = std::string(),
1733  const std::string &directvarname = std::string(),
1734  const std::string &directdataname = std::string(),
1735  bool return_if_nonlin = false);
1736  inline size_type APIDECL add_source_term_generic_assembly_brick
1737  (model &md, const mesh_im &mim, const std::string &expr,
1738  size_type region = size_type(-1),
1739  const std::string &brickname = std::string(),
1740  const std::string &directvarname = std::string(),
1741  const std::string &directdataname = std::string(),
1742  bool return_if_nonlin = false) {
1743  return add_source_term(md, mim, expr, region, brickname,
1744  directvarname, directdataname, return_if_nonlin);
1745  }
1746 
1747  /** Adds a linear term given by a weak form language expression like
1748  ``add_linear_term`` function but for an integration on a direct
1749  product of two domains, a first specfied by ``mim`` and ``region``
1750  and a second one by ``secondary_domain`` which has to be declared
1751  first into the model.
1752  */
1754  (model &md, const mesh_im &mim, const std::string &expr,
1755  size_type region, const std::string &secondary_domain,
1756  bool is_sym = false, bool is_coercive = false,
1757  const std::string &brickname = "", bool return_if_nonlin = false);
1758 
1759  /** Adds a nonlinear term given by a weak form language expression like
1760  ``add_nonlinear_term`` function but for an integration on a direct
1761  product of two domains, a first specfied by ``mim`` and ``region``
1762  and a second one by ``secondary_domain`` which has to be declared
1763  first into the model.
1764  */
1766  (model &md, const mesh_im &mim, const std::string &expr,
1767  size_type region, const std::string &secondary_domain,
1768  bool is_sym = false, bool is_coercive = false,
1769  const std::string &brickname = "");
1770 
1771  /** Adds a source term given by a weak form language expression like
1772  ``add_source_term`` function but for an integration on a direct
1773  product of two domains, a first specfied by ``mim`` and ``region``
1774  and a second one by ``secondary_domain`` which has to be declared
1775  first into the model.
1776  */
1778  (model &md, const mesh_im &mim, const std::string &expr,
1779  size_type region, const std::string &secondary_domain,
1780  const std::string &brickname = std::string(),
1781  const std::string &directvarname = std::string(),
1782  const std::string &directdataname = std::string(),
1783  bool return_if_nonlin = false);
1784 
1785 
1786  /** Add a Laplacian term on the variable `varname` (in fact with a minus :
1787  :math:`-\text{div}(\nabla u)`). If it is a vector
1788  valued variable, the Laplacian term is componentwise. `region` is an
1789  optional mesh region on which the term is added. Return the brick index
1790  in the model.
1791  */
1793  (model &md, const mesh_im &mim, const std::string &varname,
1794  size_type region = size_type(-1));
1795 
1796 
1797  /** Add an elliptic term on the variable `varname`.
1798  The shape of the elliptic
1799  term depends both on the variable and the data. This corresponds to a
1800  term $-\text{div}(a\nabla u)$ where $a$ is the data and $u$ the variable.
1801  The data can be a scalar, a matrix or an order four tensor. The variable
1802  can be vector valued or not. If the data is a scalar or a matrix and
1803  the variable is vector valued then the term is added componentwise.
1804  An order four tensor data is allowed for vector valued variable only.
1805  The data can be constant or describbed on a fem. Of course, when
1806  the data is a tensor describe on a finite element method (a tensor
1807  field) the data can be a huge vector. The components of the
1808  matrix/tensor have to be stored with the fortran order (columnwise) in
1809  the data vector (compatibility with blas). The symmetry and coercivity
1810  of the given matrix/tensor is not verified (but assumed). `region` is an
1811  optional mesh region on which the term is added. Note that for the real
1812  version which uses the high-level generic assembly language, `dataexpr`
1813  can be any regular expression of the high-level generic assembly
1814  language (like "1", "sin(X[0])" or "Norm(u)" for instance) even
1815  depending on model variables.
1816  Return the brick index in the model.
1817  */
1819  (model &md, const mesh_im &mim, const std::string &varname,
1820  const std::string &dataexpr, size_type region = size_type(-1));
1821 
1822 
1823  /** Add a source term on the variable `varname`. The source term is
1824  represented by `dataexpr` which could be any regular expression of the
1825  high-level generic assembly language (except for the complex version
1826  where it has to be a declared data of the model). `region` is an
1827  optional mesh region on which the term is
1828  added. An additional optional data `directdataname` can be provided. The
1829  corresponding data vector will be directly added to the right hand
1830  side without assembly. Return the brick index in the model.
1831  */
1833  (model &md, const mesh_im &mim, const std::string &varname,
1834  const std::string &dataexpr, size_type region = size_type(-1),
1835  const std::string &directdataname = std::string());
1836 
1837  /** Add a source term on the variable `varname` on a boundary `region`.
1838  The source term is
1839  represented by the data `dataepxpr` which could be any regular
1840  expression of the high-level generic assembly language (except
1841  for the complex version where it has to be a declared data of
1842  the model). A scalar product with the outward normal unit vector to
1843  the boundary is performed. The main aim of this brick is to represent
1844  a Neumann condition with a vector data without performing the
1845  scalar product with the normal as a pre-processing.
1846  */
1848  (model &md, const mesh_im &mim, const std::string &varname,
1849  const std::string &dataexpr, size_type region);
1850 
1851 
1852  /** Add a (simple) Dirichlet condition on the variable `varname` and
1853  the mesh region `region`. The Dirichlet condition is prescribed by
1854  a simple post-treatment of the final linear system (tangent system
1855  for nonlinear problems) consisting of modifying the lines corresponding
1856  to the degree of freedom of the variable on `region` (0 outside the
1857  diagonal, 1 on the diagonal of the matrix and the expected value on
1858  the right hand side).
1859  The symmetry of the linear system is kept if all other bricks are
1860  symmetric.
1861  This brick is to be reserved for simple Dirichlet conditions (only dof
1862  declared on the correspodning boundary are prescribed). The application
1863  of this brick on reduced f.e.m. may be problematic. Intrinsic vectorial
1864  finite element method are not supported.
1865  `dataname` is the optional right hand side of the Dirichlet condition.
1866  It could be constant or (important) described on the same finite
1867  element method as `varname`.
1868  Returns the brick index in the model.
1869  */
1871  (model &md, const std::string &varname, size_type region,
1872  const std::string &dataname = std::string());
1873 
1874 
1875  /** Add a Dirichlet condition on the variable `varname` and the mesh
1876  region `region`. This region should be a boundary. The Dirichlet
1877  condition is prescribed with a multiplier variable `multname` which
1878  should be first declared as a multiplier
1879  variable on the mesh region in the model. `dataname` is the optional
1880  right hand side of the Dirichlet condition. It could be constant or
1881  described on a fem; scalar or vector valued, depending on the variable
1882  on which the Dirichlet condition is prescribed. Return the brick index
1883  in the model.
1884  */
1886  (model &md, const mesh_im &mim, const std::string &varname,
1887  const std::string &multname, size_type region,
1888  const std::string &dataname = std::string());
1889 
1890  /** Same function as the previous one but the multipliers variable will
1891  be declared to the brick by the function. `mf_mult` is the finite element
1892  method on which the multiplier will be build (it will be restricted to
1893  the mesh region `region` and eventually some conflicting dofs with some
1894  other multiplier variables will be suppressed).
1895  */
1897  (model &md, const mesh_im &mim, const std::string &varname,
1898  const mesh_fem &mf_mult, size_type region,
1899  const std::string &dataname = std::string());
1900 
1901  /** Same function as the previous one but the `mf_mult` parameter is
1902  replaced by `degree`. The multiplier will be described on a standard
1903  finite element method of the corresponding degree.
1904  */
1906  (model &md, const mesh_im &mim, const std::string &varname,
1907  dim_type degree, size_type region,
1908  const std::string &dataname = std::string());
1909 
1910 
1911  /** When `ind_brick` is the index of a Dirichlet brick with multiplier on
1912  the model `md`, the function return the name of the multiplier variable.
1913  Otherwise, it has an undefined behavior.
1914  */
1915  const APIDECL std::string &mult_varname_Dirichlet(model &md, size_type ind_brick);
1916 
1917  /** Add a Dirichlet condition on the variable `varname` and the mesh
1918  region `region`. This region should be a boundary. The Dirichlet
1919  condition is prescribed with penalization. The penalization coefficient
1920  is intially `penalization_coeff` and will be added to the data of
1921  the model. `dataname` is the optional
1922  right hand side of the Dirichlet condition. It could be constant or
1923  described on a fem; scalar or vector valued, depending on the variable
1924  on which the Dirichlet condition is prescribed.
1925  `mf_mult` is an optional parameter which allows to weaken the
1926  Dirichlet condition specifying a multiplier space.
1927  Returns the brick index in the model.
1928  */
1930  (model &md, const mesh_im &mim, const std::string &varname,
1931  scalar_type penalization_coeff, size_type region,
1932  const std::string &dataname = std::string(),
1933  const mesh_fem *mf_mult = 0);
1934 
1935  /** Add a Dirichlet condition on the variable `varname` and the mesh
1936  region `region`. This region should be a boundary. `Neumannterm`
1937  is the expression of the Neumann term (obtained by the Green formula)
1938  described as an expression of the high-level
1939  generic assembly language. This term can be obtained with
1940  md. Neumann_term(varname, region) once all volumic bricks have
1941  been added to the model. The Dirichlet
1942  condition is prescribed with Nitsche's method. `datag` is the optional
1943  right hand side of the Dirichlet condition. `datagamma0` is the
1944  Nitsche's method parameter. `theta` is a scalar value which can be
1945  positive or negative. `theta = 1` corresponds to the standard symmetric
1946  method which is conditionnaly coercive for `gamma0` small.
1947  `theta = -1` corresponds to the skew-symmetric method which is
1948  inconditionnaly coercive. `theta = 0` is the simplest method
1949  for which the second derivative of the Neumann term is not necessary
1950  even for nonlinear problems. Return the brick index in the model.
1951  */
1953  (model &md, const mesh_im &mim, const std::string &varname,
1954  const std::string &Neumannterm,
1955  const std::string &datagamma0, size_type region,
1956  scalar_type theta = scalar_type(0),
1957  const std::string &datag = std::string());
1958 
1959 
1960  /** Add a Dirichlet condition to the normal component of the vector
1961  (or tensor) valued variable `varname` and the mesh
1962  region `region`. This region should be a boundary. The Dirichlet
1963  condition is prescribed with a multiplier variable `multname` which
1964  should be first declared as a multiplier
1965  variable on the mesh region in the model. `dataname` is the optional
1966  right hand side of the normal Dirichlet condition.
1967  It could be constant or
1968  described on a fem; scalar or vector valued, depending on the variable
1969  on which the Dirichlet condition is prescribed (scalar if the variable
1970  is vector valued, vector if the variable is tensor valued).
1971  Returns the brick index in the model.
1972  */
1974  (model &md, const mesh_im &mim, const std::string &varname,
1975  const std::string &multname, size_type region,
1976  const std::string &dataname = std::string());
1977 
1978  /** Same function as the previous one but the multipliers variable will
1979  be declared to the brick by the function. `mf_mult` is the finite element
1980  method on which the multiplier will be build (it will be restricted to
1981  the mesh region `region` and eventually some conflicting dofs with some
1982  other multiplier variables will be suppressed).
1983  */
1985  (model &md, const mesh_im &mim, const std::string &varname,
1986  const mesh_fem &mf_mult, size_type region,
1987  const std::string &dataname = std::string());
1988 
1989  /** Same function as the previous one but the `mf_mult` parameter is
1990  replaced by `degree`. The multiplier will be described on a standard
1991  finite element method of the corresponding degree.
1992  */
1994  (model &md, const mesh_im &mim, const std::string &varname,
1995  dim_type degree, size_type region,
1996  const std::string &dataname = std::string());
1997 
1998  /** Add a Dirichlet condition to the normal component of the vector
1999  (or tensor) valued variable `varname` and the mesh
2000  region `region`. This region should be a boundary. The Dirichlet
2001  condition is prescribed with penalization. The penalization coefficient
2002  is intially `penalization_coeff` and will be added to the data of
2003  the model. `dataname` is the optional
2004  right hand side of the Dirichlet condition. It could be constant or
2005  described on a fem; scalar or vector valued, depending on the variable
2006  on which the Dirichlet condition is prescribed (scalar if the variable
2007  is vector valued, vector if the variable is tensor valued).
2008  `mf_mult` is an optional parameter which allows to weaken the
2009  Dirichlet condition specifying a multiplier space.
2010  Return the brick index in the model.
2011  */
2013  (model &md, const mesh_im &mim, const std::string &varname,
2014  scalar_type penalization_coeff, size_type region,
2015  const std::string &dataname = std::string(),
2016  const mesh_fem *mf_mult = 0);
2017 
2018 
2019 
2020  /** Add a Dirichlet condition on the normal component of the variable
2021  `varname` and the mesh
2022  region `region`. This region should be a boundary. `Neumannterm`
2023  is the expression of the Neumann term (obtained by the Green formula)
2024  described as an expression of the high-level
2025  generic assembly language. This term can be obtained with
2026  md.Neumann_term(varname, region) once all volumic bricks have
2027  been added to the model.The Dirichlet
2028  condition is prescribed with Nitsche's method. `datag` is the optional
2029  scalar right hand side of the Dirichlet condition. `datagamma0` is the
2030  Nitsche's method parameter. `theta` is a scalar value which can be
2031  positive or negative. `theta = 1` corresponds to the standard symmetric
2032  method which is conditionnaly coercive for `gamma0` small.
2033  `theta = -1` corresponds to the skew-symmetric method which is
2034  inconditionnaly coercive. `theta = 0` is the simplest method
2035  for which the second derivative of the Neumann term is not necessary
2036  even for nonlinear problems. Return the brick index in the model.
2037  */
2039  (model &md, const mesh_im &mim, const std::string &varname,
2040  const std::string &Neumannterm, const std::string &datagamma0,
2041  size_type region, scalar_type theta = scalar_type(0),
2042  const std::string &datag = std::string());
2043 
2044 
2045  /** Add some pointwise constraints on the variable `varname` thanks to
2046  a penalization. The penalization coefficient is initially
2047  `penalization_coeff` and will be added to the data of the model.
2048  The conditions are prescribed on a set of points given in the data
2049  `dataname_pt` whose dimension is the number of points times the dimension
2050  of the mesh. If the variable represents a vector field, the data
2051  `dataname_unitv` represents a vector of dimension the number of points
2052  times the dimension of the vector field which should store some
2053  unit vectors. In that case the prescribed constraint is the scalar
2054  product of the variable at the corresponding point with the corresponding
2055  unit vector.
2056  The optional data `dataname_val` is the vector of values to be prescribed
2057  at the different points.
2058  This brick is specifically designed to kill rigid displacement
2059  in a Neumann problem.
2060  */
2062  (model &md, const std::string &varname,
2063  scalar_type penalisation_coeff, const std::string &dataname_pt,
2064  const std::string &dataname_unitv = std::string(),
2065  const std::string &dataname_val = std::string());
2066 
2067 
2068  /** Add some pointwise constraints on the variable `varname` using a given
2069  multiplier `multname`.
2070  The conditions are prescribed on a set of points given in the data
2071  `dataname_pt` whose dimension is the number of points times the dimension
2072  of the mesh.
2073  The multiplier variable should be a fixed size variable of size the
2074  number of points.
2075  If the variable represents a vector field, the data
2076  `dataname_unitv` represents a vector of dimension the number of points
2077  times the dimension of the vector field which should store some
2078  unit vectors. In that case the prescribed constraint is the scalar
2079  product of the variable at the corresponding point with the corresponding
2080  unit vector.
2081  The optional data `dataname_val` is the vector of values to be prescribed
2082  at the different points.
2083  This brick is specifically designed to kill rigid displacement
2084  in a Neumann problem.
2085  */
2087  (model &md, const std::string &varname,
2088  const std::string &multname, const std::string &dataname_pt,
2089  const std::string &dataname_unitv = std::string(),
2090  const std::string &dataname_val = std::string());
2091 
2092  /** Add some pointwise constraints on the variable `varname` using
2093  multiplier. The multiplier variable is automatically added to the model.
2094  The conditions are prescribed on a set of points given in the data
2095  `dataname_pt` whose dimension is the number of points times the dimension
2096  of the mesh.
2097  If the variable represents a vector field, the data
2098  `dataname_unitv` represents a vector of dimension the number of points
2099  times the dimension of the vector field which should store some
2100  unit vectors. In that case the prescribed constraint is the scalar
2101  product of the variable at the corresponding point with the corresponding
2102  unit vector.
2103  The optional data `dataname_val` is the vector of values to be prescribed
2104  at the different points.
2105  This brick is specifically designed to kill rigid displacement
2106  in a Neumann problem.
2107  */
2109  (model &md, const std::string &varname, const std::string &dataname_pt,
2110  const std::string &dataname_unitv = std::string(),
2111  const std::string &dataname_val = std::string());
2112 
2113 
2114  /** Change the penalization coefficient of a Dirichlet condition with
2115  penalization brick. If the brick is not of this kind,
2116  this function has an undefined behavior.
2117  */
2118  void APIDECL change_penalization_coeff(model &md, size_type ind_brick,
2119  scalar_type penalisation_coeff);
2120 
2121  /** Add a generalized Dirichlet condition on the variable `varname` and
2122  the mesh region `region`. This version is for vector field.
2123  It prescribes a condition @f$ Hu = r @f$ where `H` is a matrix field.
2124  This region should be a boundary. The Dirichlet
2125  condition is prescribed with a multiplier variable `multname` which
2126  should be first declared as a multiplier
2127  variable on the mesh region in the model. `dataname` is the
2128  right hand side of the Dirichlet condition. It could be constant or
2129  described on a fem; scalar or vector valued, depending on the variable
2130  on which the Dirichlet condition is prescribed. `Hname' is the data
2131  corresponding to the matrix field `H`. It has to be a constant matrix
2132  or described on a scalar fem. Return the brick index in the model.
2133  */
2135  (model &md, const mesh_im &mim, const std::string &varname,
2136  const std::string &multname, size_type region,
2137  const std::string &dataname, const std::string &Hname);
2138 
2139  /** Same function as the preceeding one but the multipliers variable will
2140  be declared to the brick by the function. `mf_mult` is the finite element
2141  method on which the multiplier will be build (it will be restricted to
2142  the mesh region `region` and eventually some conflicting dofs with some
2143  other multiplier variables will be suppressed).
2144  */
2146  (model &md, const mesh_im &mim, const std::string &varname,
2147  const mesh_fem &mf_mult, size_type region,
2148  const std::string &dataname, const std::string &Hname);
2149 
2150  /** Same function as the preceeding one but the `mf_mult` parameter is
2151  replaced by `degree`. The multiplier will be described on a standard
2152  finite element method of the corresponding degree.
2153  */
2155  (model &md, const mesh_im &mim, const std::string &varname,
2156  dim_type degree, size_type region,
2157  const std::string &dataname, const std::string &Hname);
2158 
2159  /** Add a Dirichlet condition on the variable `varname` and the mesh
2160  region `region`. This version is for vector field.
2161  It prescribes a condition @f$ Hu = r @f$ where `H` is a matrix field.
2162  This region should be a boundary. This region should be a boundary.
2163  The Dirichlet
2164  condition is prescribed with penalization. The penalization coefficient
2165  is intially `penalization_coeff` and will be added to the data of
2166  the model. `dataname` is the
2167  right hand side of the Dirichlet condition. It could be constant or
2168  described on a fem; scalar or vector valued, depending on the variable
2169  on which the Dirichlet condition is prescribed. `Hname' is the data
2170  corresponding to the matrix field `H`. It has to be a constant matrix
2171  or described on a scalar fem. `mf_mult` is an optional parameter
2172  which allows to weaken the Dirichlet condition specifying a
2173  multiplier space. Return the brick index in the model.
2174  */
2176  (model &md, const mesh_im &mim, const std::string &varname,
2177  scalar_type penalization_coeff, size_type region,
2178  const std::string &dataname, const std::string &Hname,
2179  const mesh_fem *mf_mult = 0);
2180 
2181  /** Add a Dirichlet condition on the variable `varname` and the mesh
2182  region `region`. This region should be a boundary. This version
2183  is for vector field. It prescribes a condition
2184  @f$ Hu = r @f$ where `H` is a matrix field. `Neumannterm`
2185  is the expression of the Neumann term (obtained by the Green formula)
2186  described as an expression of the high-level
2187  generic assembly language. of the high-level
2188  generic assembly language. This term can be obtained with
2189  md.Neumann_term(varname, region) once all volumic bricks have
2190  been added to the model. The Dirichlet
2191  condition is prescribed with Nitsche's method. `datag` is the optional
2192  right hand side of the Dirichlet condition. `datagamma0` is the
2193  Nitsche's method parameter. `theta` is a scalar value which can be
2194  positive or negative. `theta = 1` corresponds to the standard symmetric
2195  method which is conditionnaly coercive for `gamma0` small.
2196  `theta = -1` corresponds to the skew-symmetric method which is
2197  inconditionnaly coercive. `theta = 0` is the simplest method
2198  for which the second derivative of the Neumann term is not necessary
2199  even for nonlinear problems. Return the brick index in the model.
2200  */
2202  (model &md, const mesh_im &mim, const std::string &varname,
2203  const std::string &Neumannterm, const std::string &datagamma0,
2204  size_type region, scalar_type theta,
2205  const std::string &datag, const std::string &dataH);
2206 
2207 
2208  /** Add a Helmoltz brick to the model. This corresponds to the scalar
2209  equation (@f$\Delta u + k^2u = 0@f$, with @f$K=k^2@f$).
2210  The weak formulation is (@f$\int k^2 u.v - \nabla u.\nabla v@f$)
2211 
2212  `dataexpr` should contain the wave number $k$. It can be real or
2213  complex.
2214  */
2215  size_type APIDECL add_Helmholtz_brick(model &md, const mesh_im &mim,
2216  const std::string &varname,
2217  const std::string &dataexpr,
2218  size_type region = size_type(-1));
2219 
2220 
2221  /** Add a Fourier-Robin brick to the model. This correspond to the weak term
2222  (@f$\int (qu).v @f$) on a boundary. It is used to represent a
2223  Fourier-Robin boundary condition.
2224 
2225  `dataexpr` is the parameter $q$ which should be a
2226  (@f$N\times N@f$) matrix term, where $N$ is the dimension of the
2227  variable `varname`. It can be an arbitrary valid expression of the
2228  high-level generic assembly language (except for the complex version
2229  for which it should be a data of the model). Note that an additional
2230  right hand side can be added with a source term brick.
2231  */
2232  size_type APIDECL add_Fourier_Robin_brick(model &md, const mesh_im &mim,
2233  const std::string &varname,
2234  const std::string &dataexpr,
2235  size_type region);
2236 
2237 
2238  // Constraint brick.
2239  model_real_sparse_matrix APIDECL &set_private_data_brick_real_matrix
2240  (model &md, size_type indbrick);
2241  model_real_plain_vector APIDECL &set_private_data_brick_real_rhs
2242  (model &md, size_type indbrick);
2243  model_complex_sparse_matrix APIDECL &set_private_data_brick_complex_matrix
2244  (model &md, size_type indbrick);
2245  model_complex_plain_vector APIDECL &set_private_data_brick_complex_rhs
2246  (model &md, size_type indbrick);
2247  size_type APIDECL add_constraint_with_penalization
2248  (model &md, const std::string &varname, scalar_type penalisation_coeff);
2249  size_type APIDECL add_constraint_with_multipliers
2250  (model &md, const std::string &varname, const std::string &multname);
2251 
2252  void set_private_data_rhs
2253  (model &md, size_type indbrick, const std::string &varname);
2254 
2255  template <typename VECT, typename T>
2256  void set_private_data_rhs(model &md, size_type ind,
2257  const VECT &L, T) {
2258  model_real_plain_vector &LL = set_private_data_brick_real_rhs(md, ind);
2259  gmm::resize(LL, gmm::vect_size(L));
2260  gmm::copy(L, LL);
2261  }
2262 
2263  template <typename VECT, typename T>
2264  void set_private_data_rhs(model &md, size_type ind, const VECT &L,
2265  std::complex<T>) {
2266  model_complex_plain_vector &LL = set_private_data_brick_complex_rhs(md, ind);
2267  gmm::resize(LL, gmm::vect_size(L));
2268  gmm::copy(L, LL);
2269  }
2270 
2271  /** For some specific bricks having an internal right hand side vector
2272  (explicit bricks: 'constraint brick' and 'explicit rhs brick'),
2273  set this rhs.
2274  */
2275  template <typename VECT>
2276  void set_private_data_rhs(model &md, size_type indbrick, const VECT &L) {
2277  typedef typename gmm::linalg_traits<VECT>::value_type T;
2278  set_private_data_rhs(md, indbrick, L, T());
2279  }
2280 
2281  template <typename MAT, typename T>
2282  void set_private_data_matrix(model &md, size_type ind,
2283  const MAT &B, T) {
2284  model_real_sparse_matrix &BB = set_private_data_brick_real_matrix(md, ind);
2285  gmm::resize(BB, gmm::mat_nrows(B), gmm::mat_ncols(B));
2286  gmm::copy(B, BB);
2287  }
2288 
2289  template <typename MAT, typename T>
2290  void set_private_data_matrix(model &md, size_type ind, const MAT &B,
2291  std::complex<T>) {
2292  model_complex_sparse_matrix &BB
2293  = set_private_data_brick_complex_matrix(md, ind);
2294  gmm::resize(BB, gmm::mat_nrows(B), gmm::mat_ncols(B));
2295  gmm::copy(B, BB);
2296  }
2297 
2298  /** For some specific bricks having an internal sparse matrix
2299  (explicit bricks: 'constraint brick' and 'explicit matrix brick'),
2300  set this matrix. @*/
2301  template <typename MAT>
2302  void set_private_data_matrix(model &md, size_type indbrick,
2303  const MAT &B) {
2304  typedef typename gmm::linalg_traits<MAT>::value_type T;
2305  set_private_data_matrix(md, indbrick, B, T());
2306  }
2307 
2308  /** Add an additional explicit penalized constraint on the variable
2309  `varname`. The constraint is $BU=L$ with `B` being a rectangular
2310  sparse matrix.
2311  Be aware that `B` should not contain a plain row, otherwise the whole
2312  tangent matrix will be plain. It is possible to change the constraint
2313  at any time with the methods set_private_matrix and set_private_rhs.
2314  The method change_penalization_coeff can also be used.
2315  */
2316  template <typename MAT, typename VECT>
2317  size_type add_constraint_with_penalization
2318  (model &md, const std::string &varname, scalar_type penalisation_coeff,
2319  const MAT &B, const VECT &L) {
2320  size_type ind
2321  = add_constraint_with_penalization(md, varname, penalisation_coeff);
2322  size_type n = gmm::mat_nrows(B), m = gmm::mat_ncols(B);
2323  set_private_data_rhs(md, ind, L);
2324  set_private_data_matrix(md, ind, B);
2325  return ind;
2326  }
2327 
2328  /** Add an additional explicit constraint on the variable `varname` thank to
2329  a multiplier `multname` peviously added to the model (should be a fixed
2330  size variable).
2331  The constraint is $BU=L$ with `B` being a rectangular sparse matrix.
2332  It is possible to change the constraint
2333  at any time with the methods set_private_matrix
2334  and set_private_rhs.
2335  */
2336  template <typename MAT, typename VECT>
2337  size_type add_constraint_with_multipliers
2338  (model &md, const std::string &varname, const std::string &multname,
2339  const MAT &B, const VECT &L) {
2340  size_type ind = add_constraint_with_multipliers(md, varname, multname);
2341  set_private_data_rhs(md, ind, L);
2342  set_private_data_matrix(md, ind, B);
2343  return ind;
2344  }
2345 
2346  template <typename MAT>
2347  size_type add_constraint_with_multipliers
2348  (model &md, const std::string &varname, const std::string &multname,
2349  const MAT &B, const std::string &Lname) {
2350  size_type ind = add_constraint_with_multipliers(md, varname, multname);
2351  set_private_data_rhs(md, ind, Lname);
2352  set_private_data_matrix(md, ind, B);
2353  return ind;
2354  }
2355 
2356  size_type APIDECL add_explicit_matrix(model &md, const std::string &varname1,
2357  const std::string &varname2,
2358  bool issymmetric, bool iscoercive);
2359  size_type APIDECL add_explicit_rhs(model &md, const std::string &varname);
2360 
2361  /** Add a brick reprenting an explicit matrix to be added to the tangent
2362  linear system relatively to the variables 'varname1' and 'varname2'.
2363  The given matrix should have as many rows as the dimension of
2364  'varname1' and as many columns as the dimension of 'varname2'.
2365  If the two variables are different and if `issymmetric' is set to true
2366  then the transpose of the matrix is also added to the tangent system
2367  (default is false). set `iscoercive` to true if the term does not
2368  affect the coercivity of the tangent system (default is false).
2369  The matrix can be changed by the command set_private_matrix.
2370  */
2371  template <typename MAT>
2372  size_type add_explicit_matrix(model &md, const std::string &varname1,
2373  const std::string &varname2, const MAT &B,
2374  bool issymmetric = false,
2375  bool iscoercive = false) {
2376  size_type ind = add_explicit_matrix(md, varname1, varname2,
2377  issymmetric, iscoercive);
2378  set_private_data_matrix(md, ind, B);
2379  return ind;
2380  }
2381 
2382  /** Add a brick representing an explicit right hand side to be added to
2383  the right hand side of the tangent
2384  linear system relatively to the variable 'varname'.
2385  The given rhs should have the same size than the dimension of
2386  'varname'. The rhs can be changed by the command set_private_rhs.
2387  */
2388  template <typename VECT>
2389  size_type add_explicit_rhs(model &md, const std::string &varname,
2390  const VECT &L) {
2391  size_type ind = add_explicit_rhs(md, varname);
2392  set_private_data_rhs(md, ind, L);
2393  return ind;
2394  }
2395 
2396 
2397  /** Linear elasticity brick ( @f$ \int \sigma(u):\varepsilon(v) @f$ ).
2398  for isotropic material. Parametrized by the Lamé coefficients
2399  lambda and mu.
2400  */
2402  (model &md, const mesh_im &mim, const std::string &varname,
2403  const std::string &dataname_lambda, const std::string &dataname_mu,
2404  size_type region = size_type(-1),
2405  const std::string &dataname_preconstraint = std::string());
2406 
2407  /** Linear elasticity brick ( @f$ \int \sigma(u):\varepsilon(v) @f$ ).
2408  for isotropic material. Parametrized by Young modulus and Poisson ratio
2409  For two-dimensional problems, corresponds to the plane strain
2410  approximation
2411  ( @f$ \lambda = E\nu/((1+\nu)(1-2\nu)), \mu = E/(2(1+\nu)) @f$ ).
2412  Corresponds to the standard model for three-dimensional problems.
2413  */
2415  (model &md, const mesh_im &mim, const std::string &varname,
2416  const std::string &data_E, const std::string &data_nu,
2417  size_type region);
2418 
2419  /**
2420  Linear elasticity brick ( @f$ \int \sigma(u):\varepsilon(v) @f$ ).
2421  for isotropic material. Parametrized by Young modulus and Poisson ratio.
2422  For two-dimensional problems, corresponds to the plane stress
2423  approximation
2424  ( @f$ \lambda^* = E\nu/(1-\nu^2), \mu = E/(2(1+\nu)) @f$ ).
2425  Corresponds to the standard model for three-dimensional problems.
2426  */
2428  (model &md, const mesh_im &mim, const std::string &varname,
2429  const std::string &data_E, const std::string &data_nu,
2430  size_type region);
2431 
2432  void APIDECL compute_isotropic_linearized_Von_Mises_or_Tresca
2433  (model &md, const std::string &varname, const std::string &dataname_lambda,
2434  const std::string &dataname_mu, const mesh_fem &mf_vm,
2435  model_real_plain_vector &VM, bool tresca);
2436 
2437  /**
2438  Compute the Von-Mises stress or the Tresca stress of a field
2439  (only valid for isotropic linearized elasticity in 3D)
2440  Parametrized by Lame coefficients.
2441  */
2442  template <class VECTVM>
2443  void compute_isotropic_linearized_Von_Mises_or_Tresca
2444  (model &md, const std::string &varname, const std::string &dataname_lambda,
2445  const std::string &dataname_mu, const mesh_fem &mf_vm,
2446  VECTVM &VM, bool tresca) {
2447  model_real_plain_vector VMM(mf_vm.nb_dof());
2448  compute_isotropic_linearized_Von_Mises_or_Tresca
2449  (md, varname, dataname_lambda, dataname_mu, mf_vm, VMM, tresca);
2450  gmm::copy(VMM, VM);
2451  }
2452 
2453  /**
2454  Compute the Von-Mises stress of a displacement field for isotropic
2455  linearized elasticity in 3D or in 2D with plane strain assumption.
2456  Parametrized by Young modulus and Poisson ratio.
2457  */
2459  (model &md, const std::string &varname, const std::string &data_E,
2460  const std::string &data_nu, const mesh_fem &mf_vm,
2461  model_real_plain_vector &VM);
2462 
2463  /**
2464  Compute the Von-Mises stress of a displacement field for isotropic
2465  linearized elasticity in 3D or in 2D with plane stress assumption.
2466  Parametrized by Young modulus and Poisson ratio.
2467  */
2469  (model &md, const std::string &varname, const std::string &data_E,
2470  const std::string &data_nu, const mesh_fem &mf_vm,
2471  model_real_plain_vector &VM);
2472 
2473 
2474  /**
2475  Mixed linear incompressibility condition brick.
2476 
2477  Update the tangent matrix with a pressure term:
2478  @f[
2479  T \longrightarrow
2480  \begin{array}{ll} T & B \\ B^t & M \end{array}
2481  @f]
2482  with @f$ B = - \int p.div u @f$ and
2483  @f$ M = \int \epsilon p.q @f$ ( @f$ \epsilon @f$ is an optional
2484  penalization coefficient).
2485 
2486  Be aware that an inf-sup condition between the finite element method
2487  describing the rpressure and the primal variable has to be satisfied.
2488 
2489  For nearly incompressible elasticity,
2490  @f[ p = -\lambda \textrm{div}~u @f]
2491  @f[ \sigma = 2 \mu \varepsilon(u) -p I @f]
2492  */
2494  (model &md, const mesh_im &mim, const std::string &varname,
2495  const std::string &multname_pressure, size_type region = size_type(-1),
2496  const std::string &dataexpr_penal_coeff = std::string());
2497 
2498  /** Mass brick ( @f$ \int \rho u.v @f$ ).
2499  Add a mass matix on a variable (eventually with a specified region).
2500  If the parameter $\rho$ is omitted it is assumed to be equal to 1.
2501  */
2502  size_type APIDECL add_mass_brick
2503  (model &md, const mesh_im &mim, const std::string &varname,
2504  const std::string &dataexpr_rho = std::string(),
2505  size_type region = size_type(-1));
2506 
2507  /** Lumped mass brick for first order.
2508  Add a lumped mass matix for first order on a variable (eventually with a specified region).
2509  If the parameter $\rho$ is omitted it is assumed to be equal to 1.
2510  */
2512  (model &md, const mesh_im &mim, const std::string &varname,
2513  const std::string &dataexpr_rho = std::string(),
2514  size_type region = size_type(-1));
2515 
2516  /** Basic d/dt brick ( @f$ \int \rho ((u^{n+1}-u^n)/dt).v @f$ ).
2517  Add the standard discretization of a first order time derivative. The
2518  parameter $rho$ is the density which could be omitted (the defaul value
2519  is 1). This brick should be used in addition to a time dispatcher for the
2520  other terms.
2521  */
2523  (model &md, const mesh_im &mim, const std::string &varname,
2524  const std::string &dataname_dt,
2525  const std::string &dataname_rho = std::string(),
2526  size_type region = size_type(-1));
2527 
2528  /** Basic d2/dt2 brick ( @f$ \int \rho ((u^{n+1}-u^n)/(\alpha dt^2) - v^n/(\alpha dt) ).w @f$ ).
2529  Add the standard discretization of a second order time derivative. The
2530  parameter $rho$ is the density which could be omitted (the defaul value
2531  is 1). This brick should be used in addition to a time dispatcher for the
2532  other terms. The time derivative $v$ of the variable $u$ is preferably
2533  computed as a post-traitement which depends on each scheme.
2534  */
2536  (model &md, const mesh_im &mim, const std::string &varnameU,
2537  const std::string &datanameV,
2538  const std::string &dataname_dt,
2539  const std::string &dataname_alpha,
2540  const std::string &dataname_rho = std::string(),
2541  size_type region = size_type(-1));
2542 
2543 
2544 } /* end of namespace getfem. */
2545 
2546 
2547 #endif /* GETFEM_MODELS_H_*/
base class for static stored objects
Deal with interdependencies of objects.
im_data provides indexing to the integration points of a mesh im object.
Describe a finite element method linked to a mesh.
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
Describe an integration method linked to a mesh.
`‘Model’' variables store the variables, the data and the description of a model.
size_type nb_internal_dof() const
Number of internal degrees of freedom in the model.
bool interpolate_transformation_exists(const std::string &name) const
Tests if name corresponds to an interpolate transformation.
void update_from_context() const
this function has to be defined and should update the object when the context is modified.
const model_complex_sparse_matrix & complex_tangent_matrix() const
Gives the access to the tangent matrix.
psecondary_domain secondary_domain(const std::string &name) const
Get a pointer to the interpolate transformation name.
const model_real_plain_vector & real_brick_term_rhs(size_type ib, size_type ind_term=0, bool sym=false, size_type ind_iter=0) const
Gives access to the part of the right hand side of a term of a particular nonlinear brick.
void add_initialized_scalar_data(const std::string &name, T e)
Add a scalar data (i.e.
bool is_symmetric() const
Return true if all the model terms do not affect the coercivity of the whole tangent system.
pelementary_transformation elementary_transformation(const std::string &name) const
Get a pointer to the elementary transformation name.
bool is_linear() const
Return true if all the model terms are linear.
model_real_plain_vector & set_real_rhs(bool with_internal=false) const
Gives write access to the right hand side of the tangent linear system.
const dal::bit_vector & get_active_bricks() const
Return the model brick ids.
void enable_brick(size_type ib)
Enable a brick.
void add_initialized_fixed_size_data(const std::string &name, const VECT &v)
Add a fixed size data (assumed to be a vector) to the model and initialized with v.
const model_real_plain_vector & real_rhs(bool with_internal=false) const
Gives access to the right hand side of the tangent linear system.
const model_real_plain_vector & internal_solution() const
Gives access to the partial solution for condensed internal variables.
void add_elementary_transformation(const std::string &name, pelementary_transformation ptrans)
Add an elementary transformation to the model to be used with the generic assembly.
void add_initialized_fem_data(const std::string &name, const mesh_fem &mf, const VECT &v)
Add an initialized fixed size data to the model, assumed to be a vector field if the size of the vect...
void add_initialized_fem_data(const std::string &name, const mesh_fem &mf, const VECT &v, const bgeot::multi_index &sizes)
Add a fixed size data to the model.
const ga_macro_dictionary & macro_dictionary() const
Dictonnary of user defined macros.
bool secondary_domain_exists(const std::string &name) const
Tests if name corresponds to an interpolate transformation.
bool macro_exists(const std::string &name) const
Says if a macro of that name has been defined.
const model_complex_plain_vector & complex_rhs() const
Gives access to the right hand side of the tangent linear system.
void disable_brick(size_type ib)
Disable a brick.
bool is_complex() const
Boolean which says if the model deals with real or complex unknowns and data.
bool has_internal_variables() const
Return true if the model has at least one internal variable.
void add_interpolate_transformation(const std::string &name, pinterpolate_transformation ptrans)
Add an interpolate transformation to the model to be used with the generic assembly.
const model_complex_plain_vector & complex_brick_term_rhs(size_type ib, size_type ind_term=0, bool sym=false, size_type ind_iter=0) const
Gives access to the part of the right hand side of a term of a particular nonlinear brick.
void add_initialized_fixed_size_data(const std::string &name, const VECT &v, const bgeot::multi_index &sizes)
Add a fixed size data (assumed to be a vector) to the model and initialized with v.
void touch_brick(size_type ib)
Force the re-computation of a brick for the next assembly.
const model_real_sparse_matrix & real_tangent_matrix(bool internal=false) const
Gives the access to the tangent matrix.
bool is_coercive() const
Return true if all the model terms do not affect the coercivity of the whole tangent system.
bool elementary_transformation_exists(const std::string &name) const
Tests if name corresponds to an elementary transformation.
void add_secondary_domain(const std::string &name, psecondary_domain ptrans)
Add a secondary domain to the model to be used with the generic assembly.
size_type nb_primary_dof() const
Number of primary degrees of freedom in the model.
model_complex_plain_vector & set_complex_rhs() const
Gives write access to the right hand side of the tangent linear system.
pinterpolate_transformation interpolate_transformation(const std::string &name) const
Get a pointer to the interpolate transformation name.
The virtual brick has to be derived to describe real model bricks.
virtual void asm_complex_tangent_terms(const model &, size_type, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::complex_matlist &, model::complex_veclist &, model::complex_veclist &, size_type, build_version) const
Assembly of bricks complex tangent terms.
virtual void complex_pre_assembly_in_serial(const model &, size_type, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::complex_matlist &, model::complex_veclist &, model::complex_veclist &, size_type, build_version) const
Peform any pre assembly action for complex term assembly.
virtual void asm_real_tangent_terms(const model &, size_type, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::real_matlist &, model::real_veclist &, model::real_veclist &, size_type, build_version) const
Assembly of bricks real tangent terms.
virtual std::string declare_volume_assembly_string(const model &, size_type, const model::varnamelist &, const model::varnamelist &) const
The brick may declare an assembly string for the computation of the Neumann terms (in order to prescr...
virtual void real_pre_assembly_in_serial(const model &, size_type, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::real_matlist &, model::real_veclist &, model::real_veclist &, size_type, build_version) const
Peform any pre assembly action for real term assembly.
virtual void complex_post_assembly_in_serial(const model &, size_type, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::complex_matlist &, model::complex_veclist &, model::complex_veclist &, size_type, build_version) const
Peform any post assembly action for complex terms.
virtual void real_post_assembly_in_serial(const model &, size_type, const model::varnamelist &, const model::varnamelist &, const model::mimlist &, model::real_matlist &, model::real_veclist &, model::real_veclist &, size_type, build_version) const
Peform any post assembly action for real terms.
The time dispatcher object modify the result of a brick in order to apply a time integration scheme.
The time integration scheme object provides the necessary methods for the model object to apply a tim...
sparse vector built upon std::vector.
Definition: gmm_vector.h:963
Miscelleanous assembly routines for common terms. Use the low-level generic assembly....
A language for generic assembly of pde boundary value problems.
Provides indexing of integration points for mesh_im.
a subclass of getfem::mesh_fem which allows to eliminate a number of dof of the original mesh_fem.
void copy(const L1 &l1, L2 &l2)
*‍/
Definition: gmm_blas.h:978
void resize(V &v, size_type n)
*‍/
Definition: gmm_blas.h:210
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
GEneric Tool for Finite Element Methods.
size_type APIDECL add_nonlinear_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), bool is_sym=false, bool is_coercive=false, const std::string &brickname="")
Add a nonlinear term given by the weak form language expression expr which will be assembled in regio...
size_type APIDECL add_pointwise_constraints_with_penalization(model &md, const std::string &varname, scalar_type penalisation_coeff, const std::string &dataname_pt, const std::string &dataname_unitv=std::string(), const std::string &dataname_val=std::string())
Add some pointwise constraints on the variable varname thanks to a penalization.
size_type APIDECL add_isotropic_linearized_elasticity_pstrain_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &data_E, const std::string &data_nu, size_type region)
Linear elasticity brick ( ).
bool is_old(const std::string &name)
Does the variable have Old_ prefix.
size_type APIDECL add_nonlinear_twodomain_term(model &md, const mesh_im &mim, const std::string &expr, size_type region, const std::string &secondary_domain, bool is_sym=false, bool is_coercive=false, const std::string &brickname="")
Adds a nonlinear term given by a weak form language expression like add_nonlinear_term function but f...
size_type APIDECL add_normal_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region)
Add a source term on the variable varname on a boundary region.
size_type APIDECL add_lumped_mass_for_first_order_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr_rho=std::string(), size_type region=size_type(-1))
Lumped mass brick for first order.
size_type APIDECL add_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string())
Add a Dirichlet condition on the variable varname and the mesh region region.
void APIDECL change_penalization_coeff(model &md, size_type ind_brick, scalar_type penalisation_coeff)
Change the penalization coefficient of a Dirichlet condition with penalization brick.
size_type APIDECL add_isotropic_linearized_elasticity_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname_lambda, const std::string &dataname_mu, size_type region=size_type(-1), const std::string &dataname_preconstraint=std::string())
Linear elasticity brick ( ).
size_type APIDECL add_pointwise_constraints_with_given_multipliers(model &md, const std::string &varname, const std::string &multname, const std::string &dataname_pt, const std::string &dataname_unitv=std::string(), const std::string &dataname_val=std::string())
Add some pointwise constraints on the variable varname using a given multiplier multname.
size_type APIDECL add_basic_d2_on_dt2_brick(model &md, const mesh_im &mim, const std::string &varnameU, const std::string &datanameV, const std::string &dataname_dt, const std::string &dataname_alpha, const std::string &dataname_rho=std::string(), size_type region=size_type(-1))
Basic d2/dt2 brick ( ).
const auto PREFIX_OLD
A prefix to refer to the previous version of a variable.
Definition: getfem_models.h:98
size_type APIDECL add_mass_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr_rho=std::string(), size_type region=size_type(-1))
Mass brick ( ).
size_type APIDECL add_Laplacian_brick(model &md, const mesh_im &mim, const std::string &varname, size_type region=size_type(-1))
Add a Laplacian term on the variable varname (in fact with a minus : :math:-\text{div}(\nabla u)).
size_type APIDECL add_source_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), const std::string &brickname=std::string(), const std::string &directvarname=std::string(), const std::string &directdataname=std::string(), bool return_if_nonlin=false)
Add a source term given by the assembly string expr which will be assembled in region region and with...
size_type APIDECL add_generic_elliptic_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1))
Add an elliptic term on the variable varname.
size_type APIDECL add_Dirichlet_condition_with_Nitsche_method(model &md, const mesh_im &mim, const std::string &varname, const std::string &Neumannterm, const std::string &datagamma0, size_type region, scalar_type theta=scalar_type(0), const std::string &datag=std::string())
Add a Dirichlet condition on the variable varname and the mesh region region.
size_type APIDECL add_Helmholtz_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1))
Add a Helmoltz brick to the model.
void APIDECL velocity_update_for_order_two_theta_method(model &md, const std::string &U, const std::string &V, const std::string &pdt, const std::string &ptheta)
Function which udpate the velocity $v^{n+1}$ after the computation of the displacement $u^{n+1}$ and ...
void APIDECL velocity_update_for_Newmark_scheme(model &md, size_type id2dt2b, const std::string &U, const std::string &V, const std::string &pdt, const std::string &ptwobeta, const std::string &pgamma)
Function which udpate the velocity $v^{n+1}$ after the computation of the displacement $u^{n+1}$ and ...
size_type APIDECL add_generalized_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname, const std::string &Hname)
Add a generalized Dirichlet condition on the variable varname and the mesh region region.
size_type APIDECL add_pointwise_constraints_with_multipliers(model &md, const std::string &varname, const std::string &dataname_pt, const std::string &dataname_unitv=std::string(), const std::string &dataname_val=std::string())
Add some pointwise constraints on the variable varname using multiplier.
size_type APIDECL add_twodomain_source_term(model &md, const mesh_im &mim, const std::string &expr, size_type region, const std::string &secondary_domain, const std::string &brickname=std::string(), const std::string &directvarname=std::string(), const std::string &directdataname=std::string(), bool return_if_nonlin=false)
Adds a source term given by a weak form language expression like add_source_term function but for an ...
void APIDECL compute_isotropic_linearized_Von_Mises_pstress(model &md, const std::string &varname, const std::string &data_E, const std::string &data_nu, const mesh_fem &mf_vm, model_real_plain_vector &VM)
Compute the Von-Mises stress of a displacement field for isotropic linearized elasticity in 3D or in ...
size_type APIDECL add_linear_incompressibility(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname_pressure, size_type region=size_type(-1), const std::string &dataexpr_penal_coeff=std::string())
Mixed linear incompressibility condition brick.
std::shared_ptr< const virtual_brick > pbrick
type of pointer on a brick
Definition: getfem_models.h:49
size_type APIDECL add_generalized_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname, const std::string &Hname, const mesh_fem *mf_mult=0)
Add a Dirichlet condition on the variable varname and the mesh region region.
size_type APIDECL add_linear_term(model &md, const mesh_im &mim, const std::string &expr, size_type region=size_type(-1), bool is_sym=false, bool is_coercive=false, const std::string &brickname="", bool return_if_nonlin=false)
Add a term given by the weak form language expression expr which will be assembled in region region a...
size_type APIDECL add_linear_twodomain_term(model &md, const mesh_im &mim, const std::string &expr, size_type region, const std::string &secondary_domain, bool is_sym=false, bool is_coercive=false, const std::string &brickname="", bool return_if_nonlin=false)
Adds a linear term given by a weak form language expression like add_linear_term function but for an ...
void APIDECL compute_isotropic_linearized_Von_Mises_pstrain(model &md, const std::string &varname, const std::string &data_E, const std::string &data_nu, const mesh_fem &mf_vm, model_real_plain_vector &VM)
Compute the Von-Mises stress of a displacement field for isotropic linearized elasticity in 3D or in ...
size_type APIDECL add_generalized_Dirichlet_condition_with_Nitsche_method(model &md, const mesh_im &mim, const std::string &varname, const std::string &Neumannterm, const std::string &datagamma0, size_type region, scalar_type theta, const std::string &datag, const std::string &dataH)
Add a Dirichlet condition on the variable varname and the mesh region region.
size_type APIDECL add_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname=std::string(), const mesh_fem *mf_mult=0)
Add a Dirichlet condition on the variable varname and the mesh region region.
void APIDECL add_midpoint_dispatcher(model &md, dal::bit_vector ibricks)
Add a midpoint time dispatcher to a list of bricks.
size_type APIDECL add_Fourier_Robin_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region)
Add a Fourier-Robin brick to the model.
void APIDECL add_theta_method_dispatcher(model &md, dal::bit_vector ibricks, const std::string &THETA)
Add a theta-method time dispatcher to a list of bricks.
size_type APIDECL add_normal_Dirichlet_condition_with_penalization(model &md, const mesh_im &mim, const std::string &varname, scalar_type penalization_coeff, size_type region, const std::string &dataname=std::string(), const mesh_fem *mf_mult=0)
Add a Dirichlet condition to the normal component of the vector (or tensor) valued variable varname a...
size_type APIDECL add_isotropic_linearized_elasticity_pstress_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &data_E, const std::string &data_nu, size_type region)
Linear elasticity brick ( ).
size_type APIDECL add_basic_d_on_dt_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataname_dt, const std::string &dataname_rho=std::string(), size_type region=size_type(-1))
Basic d/dt brick ( ).
size_type APIDECL add_source_term_brick(model &md, const mesh_im &mim, const std::string &varname, const std::string &dataexpr, size_type region=size_type(-1), const std::string &directdataname=std::string())
Add a source term on the variable varname.
size_type APIDECL add_normal_Dirichlet_condition_with_Nitsche_method(model &md, const mesh_im &mim, const std::string &varname, const std::string &Neumannterm, const std::string &datagamma0, size_type region, scalar_type theta=scalar_type(0), const std::string &datag=std::string())
Add a Dirichlet condition on the normal component of the variable varname and the mesh region region.
size_type APIDECL add_normal_Dirichlet_condition_with_multipliers(model &md, const mesh_im &mim, const std::string &varname, const std::string &multname, size_type region, const std::string &dataname=std::string())
Add a Dirichlet condition to the normal component of the vector (or tensor) valued variable varname a...
const APIDECL std::string & mult_varname_Dirichlet(model &md, size_type ind_brick)
When ind_brick is the index of a Dirichlet brick with multiplier on the model md, the function return...
size_type APIDECL add_Dirichlet_condition_with_simplification(model &md, const std::string &varname, size_type region, const std::string &dataname=std::string())
Add a (simple) Dirichlet condition on the variable varname and the mesh region region.
std::string no_old_prefix_name(const std::string &name)
Strip the variable name from prefix Old_ if it has one.