Hermes2D  3.0
weakforms_neutronics.h
1 #ifndef __H2D_NEUTRONICS_WEAK_FORMS_H
2 #define __H2D_NEUTRONICS_WEAK_FORMS_H
3 
4 #include "weakforms_h1.h"
5 #include "../forms.h"
6 #include "../function/filter.h"
7 
8 namespace Hermes
9 {
10  namespace Hermes2D
11  {
12  namespace WeakFormsNeutronics
13  {
14  namespace Monoenergetic
15  {
16  namespace Diffusion
17  {
18  /*
19  Simple monoenergetic neutron diffusion, with the following weak formulation within each
20  homogeneous region:
21 
22  \int_{region} D \nabla\phi \cdot \nabla\psi d\bfx + \int_{region} \Sigma_a \phi\psi d\bfx
23  = \int_{region} Q_{ext}\psi d\bfx
24 
25  where
26 
27  D ... diffusion coefficient,
28  \Sigma_a ... absorption cross-section,
29  Q_{ext} ... external neutron sources
30 
31  are region-wise constant physical parameters of the problem. Each region has one entry in vector
32  'regions', which is the marker used for all elements it is composed of (usually specified in the
33  mesh file). A corresponding entry in the *_map arguments is the value of the particular physical
34  parameter for that marker.
35 
36  Dirichlet and/or zero Neumann BC are assumed - nonzero Neumann or Newton boundary conditions can
37  be enabled by creating a descendant and adding surface forms to it.
38  */
39  template<typename Scalar>
40  class HERMES_API DefaultWeakFormFixedSource : public WeakForm < Scalar >
41  {
42  public:
43  DefaultWeakFormFixedSource(std::vector<std::string> regions,
44  std::vector<double> D_map,
45  std::vector<double> Sigma_a_map,
46  std::vector<double> Q_map);
47  };
48  }
49  }
50 
51  namespace Multigroup
52  {
53  namespace MaterialProperties
54  {
55  namespace Definitions
56  {
57  typedef double rank0;
58  typedef std::vector<double> rank1;
59  typedef std::vector<std::vector<double > > rank2;
60  typedef std::vector<std::vector<std::vector<double > > > rank3;
61 
62  typedef std::map<std::string, rank0> MaterialPropertyMap0;
63  typedef std::map<std::string, rank1> MaterialPropertyMap1;
64  typedef std::map<std::string, rank2> MaterialPropertyMap2;
65  typedef std::map<std::string, rank3> MaterialPropertyMap3;
66 
67  typedef std::vector<bool > bool1;
68  typedef std::vector<std::vector<bool > > bool2;
69  }
70 
71  namespace Messages
72  {
73  static const char* E_INF_VALUE =
74  "Attempt to set an infinite material property.";
75  static const char* W_NEG_VALUE =
76  "Entered material data lead to some negative properties.";
77  static const char* W_MG_EXTENSION =
78  "Attempted to create a multigroup material-property map in a container for singlegroup maps.";
79  static const char* W_SA_LT_SF =
80  "Possible unphysical situation detected: Sigma_a < Sigma_f.";
81  static const char* E_MR_EXTENSION =
82  "Cannot create a multiregion material-property map: no regions specified.";
83  static const char* E_INSUFFICIENT_DATA =
84  "Not all required material properties have been set.";
85  static const char* W_NO_FISSION =
86  "Not all required fission properties have been set or could be determined automatically."
87  "Assuming a non-fissioning system.";
88  static const char* W_NO_SCATTERING =
89  "Not all required scattering properties have been set or could be determined automatically."
90  "Assuming a purely absorbing system.";
91  static const char* E_INVALID_COMBINATION =
92  "Invalid combination of entered material properties.";
93  static const char* E_NONMATCHING_PROPERTIES =
94  "All properties must be defined for a single given number of materials.";
95  static const char* E_INVALID_SIZE =
96  "Material property defined for an unexpected number of groups.";
97  static const char* E_INVALID_GROUP_INDEX =
98  "Attempted to access an out-of-range group.";
99  static const char* E_INVALID_MARKER =
100  "Material data undefined for the given element marker.";
101  static const char* E_SG_SIGMA_R =
102  "Group-reduction cross-section (Sigma_r) is not defined for one-group (i.e. monoenergetic) problems."
103  "Set Sigma_a instead.";
104  }
105 
106  namespace ValidationFunctors
107  {
108  using namespace Definitions;
109  using namespace Messages;
110 
111  struct ensure_trivial {
112  void operator() (MaterialPropertyMap1::value_type x) {
113  MaterialPropertyMap1::mapped_type::iterator it;
114  for (it = x.second.begin(); it != x.second.end(); ++it)
115  if (fabs(*it) > 1e-14)
116  throw Hermes::Exceptions::Exception(E_INVALID_COMBINATION);
117  }
118  };
119 
120  struct ensure_size {
121  ensure_size(unsigned int nrows, unsigned int ncols = 0)
122  : nrows(nrows), ncols(ncols) {};
123 
124  void operator() (MaterialPropertyMap1::value_type x) {
125  if (x.second.size() != nrows)
126  throw Hermes::Exceptions::Exception(E_INVALID_SIZE);
127  }
128 
129  void operator() (MaterialPropertyMap2::value_type x) {
130  if (x.second.size() != nrows)
131  throw Hermes::Exceptions::Exception(E_INVALID_SIZE);
132 
133  MaterialPropertyMap2::mapped_type::iterator it;
134  for (it = x.second.begin(); it != x.second.end(); ++it)
135  if (it->size() != ncols)
136  throw Hermes::Exceptions::Exception(E_INVALID_SIZE);
137  }
138 
139  private:
140  unsigned int nrows, ncols;
141  };
142  }
143 
144  namespace Common
145  {
146  using namespace Definitions;
147  using namespace Messages;
148 
149  class HERMES_API NDArrayMapOp
150  {
151  //
152  // NOTE: Could be perhaps combined with the classes material_property_map and MultiArray below
153  // and moved to hermes_common as a general way of handling maps with multidimensional mapped types.
154  //
155 
156  template <typename NDArrayType>
157  static rank0 divide(rank0 x, rank0 y) {
158  if (x == 0 && y == 0)
159  return 0.0;
160  else if (y == 0)
161  {
162  throw Hermes::Exceptions::Exception(E_INF_VALUE);
163  return -1.0;
164  }
165  else
166  return x / y;
167  }
168 
169  template <typename NDArrayType>
170  static rank0 multiply(rank0 x, rank0 y) {
171  return x*y;
172  }
173 
174  template <typename NDArrayType>
175  static rank0 add(rank0 x, rank0 y) {
176  return x + y;
177  }
178 
179  template <typename NDArrayType>
180  static rank0 subtract(rank0 x, rank0 y) {
181  rank0 ret = x - y;
182  return ret;
183  }
184 
185  public:
186 
187 #define for_each_element_in_dimension \
188  typedef typename NDArrayType::value_type dim_type; \
189  typename NDArrayType::const_iterator dim_iterator_x = x.begin(); \
190  typename NDArrayType::const_iterator dim_iterator_y = y.begin(); \
191  for (; dim_iterator_x != x.end(); ++dim_iterator_x, ++dim_iterator_y)
192 
193  template <typename NDArrayType>
194  static NDArrayType divide(const NDArrayType& x, const NDArrayType& y)
195  {
196  NDArrayType res; res.reserve(x.size());
197 
198  for_each_element_in_dimension
199  res.push_back(divide<dim_type>(*dim_iterator_x, *dim_iterator_y));
200 
201  return res;
202  }
203 
204  template <typename NDArrayType>
205  static NDArrayType multiply(const NDArrayType& x, const NDArrayType& y)
206  {
207  NDArrayType res; res.reserve(x.size());
208 
209  for_each_element_in_dimension
210  res.push_back(multiply<dim_type>(*dim_iterator_x, *dim_iterator_y));
211 
212  return res;
213  }
214 
215  template <typename NDArrayType>
216  static NDArrayType add(const NDArrayType& x, const NDArrayType& y)
217  {
218  NDArrayType res; res.reserve(x.size());
219 
220  for_each_element_in_dimension
221  res.push_back(add<dim_type>(*dim_iterator_x, *dim_iterator_y));
222 
223  return res;
224  }
225 
226  template <typename NDArrayType>
227  static NDArrayType subtract(const NDArrayType& x, const NDArrayType& y)
228  {
229  NDArrayType res; res.reserve(x.size());
230 
231  for_each_element_in_dimension
232  res.push_back(subtract<dim_type>(*dim_iterator_x, *dim_iterator_y));
233 
234  return res;
235  }
236 
237 #undef for_each_element_in_dimension
238 
239 #define for_each_element_in_map \
240  typename std::map<std::string, T>::iterator iterator_ret = ret.begin(); \
241  typename std::map<std::string, T>::const_iterator iterator_x = x.begin(); \
242  typename std::map<std::string, T>::const_iterator iterator_y = y.begin(); \
243  for (; iterator_x != x.end(); ++iterator_x, ++iterator_y, ++iterator_ret)
244 
245  template <typename T>
246  static std::map<std::string, T> divide(const std::map<std::string, T>& x,
247  const std::map<std::string, T>& y)
248  {
249  std::map<std::string, T> ret = x;
250 
251  for_each_element_in_map
252  iterator_ret->second = divide<T>(iterator_x->second, iterator_y->second);
253 
254  return ret;
255  }
256 
257  template <typename T>
258  static std::map<std::string, T> multiply(const std::map<std::string, T>& x,
259  const std::map<std::string, T>& y)
260  {
261  std::map<std::string, T> ret = x;
262 
263  for_each_element_in_map
264  iterator_ret->second = multiply<T>(iterator_x->second, iterator_y->second);
265 
266  return ret;
267  }
268 
269  template <typename T>
270  static std::map<std::string, T> add(const std::map<std::string, T>& x,
271  const std::map<std::string, T>& y)
272  {
273  std::map<std::string, T> ret = x;
274 
275  for_each_element_in_map
276  iterator_ret->second = add<T>(iterator_x->second, iterator_y->second);
277 
278  return ret;
279  }
280 
281  template <typename T>
282  static std::map<std::string, T> subtract(const std::map<std::string, T>& x,
283  const std::map<std::string, T>& y)
284  {
285  std::map<std::string, T> ret = x;
286 
287  for_each_element_in_map
288  iterator_ret->second = subtract<T>(iterator_x->second, iterator_y->second);
289 
290  return ret;
291  }
292 
293 #undef for_each_element_in_map
294  };
295 
296  class HERMES_API MaterialPropertyMaps : public Hermes::Mixins::Loggable
297  {
298  protected:
299 
300  MaterialPropertyMap1 Sigma_f;
301  MaterialPropertyMap1 nu;
302  MaterialPropertyMap1 chi;
303 
304  MaterialPropertyMap1 Sigma_a;
305  MaterialPropertyMap1 nuSigma_f;
306 
307  std::set<std::string> materials_list;
308  unsigned int G;
309 
310  bool1 fission_multigroup_structure;
311 
312  void extend_to_multigroup(const MaterialPropertyMap0& mrsg_map, MaterialPropertyMap1 *mrmg_map);
313 
314  void extend_to_multiregion(const rank1& srmg_array, MaterialPropertyMap1 *mrmg_map);
315 
316  void extend_to_multiregion_multigroup(const rank0& srsg_value, MaterialPropertyMap1 *mrmg_map);
317 
318  void fill_with(double c, MaterialPropertyMap1 *mrmg_map);
319 
320  MaterialPropertyMaps(unsigned int G, std::set<std::string> mat_list = std::set<std::string>())
321  : materials_list(mat_list), G(G) { };
322 
323  virtual void validate();
324 
325  public:
326 
327  void set_nu(const MaterialPropertyMap1& nu) {
328  this->nu = nu;
329  }
330 
331  void set_nu(const MaterialPropertyMap0& nu) {
332  extend_to_multigroup(nu, &this->nu);
333  }
334 
335  void set_nu(const rank1& nu) {
336  extend_to_multiregion(nu, &this->nu);
337  }
338 
339  void set_nu(const rank0& nu) {
340  extend_to_multiregion_multigroup(nu, &this->nu);
341  }
342 
343  void set_chi(const MaterialPropertyMap1& chi) {
344  this->chi = chi;
345  }
346 
347  void set_chi(const rank1& chi) {
348  extend_to_multiregion(chi, &this->chi);
349  }
350 
351  void set_fission_multigroup_structure(const bool1& chi_nnz) {
352  this->fission_multigroup_structure = chi_nnz;
353  }
354 
355  void set_Sigma_a(const MaterialPropertyMap1& Sa) {
356  this->Sigma_a = Sa;
357  }
358 
359  void set_Sigma_f(const MaterialPropertyMap1& Sf) {
360  this->Sigma_f = Sf;
361  }
362 
363  void set_nuSigma_f(const MaterialPropertyMap1 nSf) {
364  this->nuSigma_f = nSf;
365  }
366 
367  const MaterialPropertyMap1& get_Sigma_f() const {
368  return this->Sigma_f;
369  }
370  const MaterialPropertyMap1& get_nu() const {
371  return this->nu;
372  }
373  const MaterialPropertyMap1& get_chi() const {
374  return this->chi;
375  }
376  const bool1& get_fission_multigroup_structure() const {
377  return this->fission_multigroup_structure;
378  }
379 
380  const rank1& get_Sigma_f(std::string material) const;
381  const rank1& get_nu(std::string material) const;
382  const rank1& get_chi(std::string material) const;
383 
384  unsigned int get_G() const { return G; }
385 
386  friend std::ostream & operator<< (std::ostream& os, const MaterialPropertyMaps& matprop);
387  };
388  }
389 
390  namespace Diffusion
391  {
392  using namespace Definitions;
393  using namespace Messages;
394 
396  {
397  protected:
398 
399  MaterialPropertyMap1 D;
400  MaterialPropertyMap1 Sigma_r;
401  MaterialPropertyMap2 Sigma_s;
402  MaterialPropertyMap1 src;
403 
404  MaterialPropertyMap1 Sigma_t;
405 
406  bool2 scattering_multigroup_structure;
407 
408  public:
409 
410  MaterialPropertyMaps(unsigned int G, std::set<std::string> mat_list = std::set<std::string>())
411  : Common::MaterialPropertyMaps(G, mat_list) { };
412 
413  MaterialPropertyMap1 extract_map2_diagonals(const MaterialPropertyMap2& map2);
414 
415  MaterialPropertyMap1 sum_map2_columns(const MaterialPropertyMap2& map2);
416 
417  MaterialPropertyMap2 create_map2_by_diagonals(const MaterialPropertyMap1& diags);
418 
419  void fill_with(double c, MaterialPropertyMap2 *mrmg_map);
420 
421  // We always need to supply chi, nu, Sigma_f, Sigma_r, Sigma_s and D to our neutronics weak forms.
422  // These parameters are often defined in terms of the other ones, or not specified at all and assumed
423  // to be zero for a particular simplified situation. This method, together with its complement in the
424  // parent class, uses the most typical definitions to build the six-parameter set from the given input.
425  // It also checks whether the user did not enter nonsensical values. However, values entered by the
426  // user may sometimes not satisfy the common relations, as some empirical corrections may have been
427  // already included in them.
428  virtual void validate();
429 
430  void set_src(const MaterialPropertyMap1& src) {
431  this->src = src;
432  }
433 
434  void set_src(const MaterialPropertyMap0& src) {
435  extend_to_multigroup(src, &this->src);
436  }
437 
438  void set_src(const rank1& src) {
439  extend_to_multiregion(src, &this->src);
440  }
441 
442  void set_src(const double& src) {
443  extend_to_multiregion_multigroup(src, &this->src);
444  }
445 
446  void set_D(const MaterialPropertyMap1& D) {
447  this->D = D;
448  }
449 
450  void set_Sigma_r(const MaterialPropertyMap1& Sr) {
451  this->Sigma_r = Sr;
452  }
453 
454  void set_Sigma_t(const MaterialPropertyMap1& St) {
455  this->Sigma_t = St;
456  }
457 
458  void set_Sigma_s(const MaterialPropertyMap2& Ss) {
459  this->Sigma_s = Ss;
460  }
461 
462  void set_scattering_multigroup_structure(const bool2& Ss_nnz) {
463  this->scattering_multigroup_structure = Ss_nnz;
464  }
465 
466  const MaterialPropertyMap2& get_Sigma_s() const {
467  return this->Sigma_s;
468  }
469  const MaterialPropertyMap1& get_Sigma_r() const {
470  return this->Sigma_r;
471  }
472  const MaterialPropertyMap1& get_D() const {
473  return this->D;
474  }
475  const MaterialPropertyMap1& get_src() const {
476  return this->src;
477  }
478  const bool2& get_scattering_multigroup_structure() const {
479  return this->scattering_multigroup_structure;
480  }
481 
482  const rank2& get_Sigma_s(std::string material) const;
483  const rank1& get_Sigma_r(std::string material) const;
484  const rank1& get_D(std::string material) const;
485  const rank1& get_src(std::string material) const;
486 
487  friend HERMES_API std::ostream & operator<< (std::ostream& os, const MaterialPropertyMaps& matprop);
488  };
489  }
490 
491  template <typename NDArrayType>
493  {
494  private:
495  std::map<std::string, NDArrayType> m_map;
496  public:
497  material_property_map(const std::string& key, const NDArrayType& val) {
498  m_map[key] = val;
499  }
500 
501  material_property_map<NDArrayType>& operator()(const std::string& key, const NDArrayType& val) {
502  m_map[key] = val;
503  return *this;
504  }
505 
506  operator std::map<std::string, NDArrayType>() {
507  return m_map;
508  }
509  };
510 
511  template <typename NDArrayType>
513  {
514  private:
515  std::vector<NDArrayType> m_data;
516  public:
517  MultiArray(const NDArrayType& val) {
518  m_data.push_back(val);
519  }
520 
521  MultiArray<NDArrayType>& operator()(const NDArrayType& val) {
522  m_data.push_back(val);
523  return *this;
524  }
525 
526  operator std::vector<NDArrayType>() {
527  return m_data;
528  }
529  };
530 
531  namespace Definitions
532  {
533  typedef MultiArray<rank0> row;
534  typedef MultiArray<rank1> mat;
535  typedef MultiArray<bool> bool_row;
536  typedef MultiArray< std::vector<bool> > bool_mat;
537  }
538  }
539 
540  namespace ElementaryForms
541  {
542  namespace Diffusion
543  {
544  using namespace MaterialProperties::Diffusion;
545 
546  class HERMES_API GenericForm
547  {
548  protected:
549  const MaterialPropertyMaps& matprop;
550  GeomType geom_type;
551 
552  GenericForm(const MaterialPropertyMaps& matprop,
553  GeomType geom_type = HERMES_PLANAR)
554  : matprop(matprop), geom_type(geom_type)
555  {};
556 
557  GenericForm(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
558  GeomType geom_type = HERMES_PLANAR)
559  : matprop(matprop), geom_type(geom_type), mesh(mesh)
560  {};
561 
562  MeshSharedPtr mesh;
563  };
564 
565  struct HERMES_API VacuumBoundaryCondition
566  {
567  // TODO: General albedo boundary condition.
568  template<typename Scalar>
569  class HERMES_API Jacobian : public MatrixFormSurf < Scalar >
570  {
571  public:
572  Jacobian(unsigned int g, GeomType geom_type = HERMES_PLANAR)
573  : MatrixFormSurf<Scalar>(g, g),
574  g(g), geom_type(geom_type)
575  {};
576 
577  Jacobian(unsigned int g, std::string area, GeomType geom_type = HERMES_PLANAR)
578  : MatrixFormSurf<Scalar>(g, g),
579  g(g), geom_type(geom_type)
580  {
581  this->set_area(area);
582  };
583 
584  template<typename Real, typename ScalarTestFns>
585  ScalarTestFns matrix_form(int n, double *wt, Func<ScalarTestFns> *u_ext[], Func<Real> *u,
586  Func<Real> *v, GeomSurf<Real> *e, Func<ScalarTestFns> **ext) const;
587 
588  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *u,
589  Func<double> *v, GeomSurf<double> *e, Func<Scalar> **ext) const {
590  return matrix_form<double, Scalar>(n, wt, u_ext, u, v, e, ext);
591  }
592 
593  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *u,
594  Func<Hermes::Ord> *v, GeomSurf<Hermes::Ord> *e, Func<Ord> **ext) const {
595  return matrix_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, u, v, e, ext);
596  }
597 
598  // This is to make the form usable in rk_time_step_newton().
599  virtual MatrixFormSurf<Scalar>* clone() const {
600  return new Jacobian(*this);
601  }
602 
603  private:
604  unsigned int g;
605  GeomType geom_type;
606  };
607 
608  template<typename Scalar>
609  class HERMES_API Residual : public VectorFormSurf < Scalar >
610  {
611  public:
612  Residual(unsigned int g, GeomType geom_type = HERMES_PLANAR)
614  g(g), geom_type(geom_type)
615  {};
616 
617  Residual(unsigned int g, std::string area, GeomType geom_type = HERMES_PLANAR)
619  g(g), geom_type(geom_type)
620  {
621  this->set_area(area);
622  };
623 
624  template<typename Real, typename ScalarTestFns>
625  ScalarTestFns vector_form(int n, double *wt, Func<ScalarTestFns> *u_ext[],
626  Func<Real> *v, GeomSurf<Real> *e, Func<ScalarTestFns> **ext) const;
627 
628  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[],
629  Func<double> *v, GeomSurf<double> *e, Func<Scalar> **ext) const {
630  return vector_form<double, Scalar>(n, wt, u_ext, v, e, ext);
631  }
632 
633  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[],
634  Func<Hermes::Ord> *v, GeomSurf<Hermes::Ord> *e, Func<Ord> **ext) const {
635  return vector_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, v, e, ext);
636  }
637 
638  // This is to make the form usable in rk_time_step_newton().
639  virtual VectorFormSurf<Scalar>* clone() const {
640  return new Residual(*this);
641  }
642 
643  private:
644  unsigned int g;
645  GeomType geom_type;
646  };
647  };
648 
649  struct HERMES_API DiffusionReaction
650  {
651  template<typename Scalar>
652  class Jacobian : public MatrixFormVol<Scalar>, protected GenericForm
653  {
654  public:
655  Jacobian(unsigned int g,
656  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
657  : MatrixFormVol<Scalar>(g, g),
658  GenericForm(matprop, geom_type),
659  g(g)
660  {};
661 
662  Jacobian(unsigned int g, std::string area,
663  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
664  : MatrixFormVol<Scalar>(g, g),
665  GenericForm(matprop, geom_type),
666  g(g)
667  {
668  this->set_area(area);
669  };
670 
671  Jacobian(unsigned int g,
672  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
673  : MatrixFormVol<Scalar>(g, g),
674  GenericForm(matprop, mesh, geom_type),
675  g(g)
676  {};
677 
678  Jacobian(unsigned int g, std::string area,
679  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
680  : MatrixFormVol<Scalar>(g, g),
681  GenericForm(matprop, mesh, geom_type),
682  g(g)
683  {
684  this->set_area(area);
685  };
686 
687  template<typename Real, typename ScalarTestFns>
688  ScalarTestFns matrix_form(int n, double *wt, Func<ScalarTestFns> *u_ext[], Func<Real> *u,
689  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
690 
691  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *u,
692  Func<double> *v, GeomVol<double> *e, Func<Scalar> **ext) const {
693  return matrix_form<double, Scalar>(n, wt, u_ext, u, v, e, ext);
694  }
695 
696  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *u,
698  return matrix_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, u, v, e, ext);
699  }
700 
701  // This is to make the form usable in rk_time_step_newton().
702  virtual MatrixFormVol<Scalar>* clone() const {
703  return new Jacobian(*this);
704  }
705 
706  private:
707 
708  unsigned int g;
709  };
710 
711  template<typename Scalar>
712  class Residual : public VectorFormVol<Scalar>, protected GenericForm
713  {
714  public:
715 
716  Residual(unsigned int g,
717  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
719  GenericForm(matprop, geom_type),
720  g(g)
721  {};
722 
723  Residual(unsigned int g, std::string area,
724  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
726  GenericForm(matprop, geom_type),
727  g(g)
728  {
729  this->set_area(area);
730  };
731 
732  Residual(unsigned int g,
733  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
735  GenericForm(matprop, mesh, geom_type),
736  g(g)
737  {};
738 
739  Residual(unsigned int g, std::string area,
740  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
742  GenericForm(matprop, mesh, geom_type),
743  g(g)
744  {
745  this->set_area(area);
746  };
747 
748  template<typename Real, typename ScalarTestFns>
749  ScalarTestFns vector_form(int n, double *wt, Func<ScalarTestFns> *u_ext[],
750  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
751 
752  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *v,
753  GeomVol<double> *e, Func<Scalar> **ext) const {
754  return vector_form<double, Scalar>(n, wt, u_ext, v, e, ext);
755  }
756 
757  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *v,
758  GeomVol<Hermes::Ord> *e, Func<Ord> **ext) const {
759  return vector_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, v, e, ext);
760  }
761 
762  // This is to make the form usable in rk_time_step_newton().
763  virtual VectorFormVol<Scalar>* clone() const {
764  return new Residual(*this);
765  }
766 
767  private:
768 
769  unsigned int g;
770  };
771  };
772 
773  struct HERMES_API FissionYield
774  {
775  template<typename Scalar>
776  class HERMES_API Jacobian : public MatrixFormVol<Scalar>, protected GenericForm
777  {
778  public:
779 
780  Jacobian(unsigned int gto, unsigned int gfrom,
781  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
782  : MatrixFormVol<Scalar>(gto, gfrom),
783  GenericForm(matprop, geom_type),
784  gto(gto), gfrom(gfrom)
785  {};
786 
787  Jacobian(unsigned int gto, unsigned int gfrom, std::string area,
788  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
789  : MatrixFormVol<Scalar>(gto, gfrom),
790  GenericForm(matprop, geom_type),
791  gto(gto), gfrom(gfrom)
792  {
793  this->set_area(area);
794  };
795 
796  Jacobian(unsigned int gto, unsigned int gfrom,
797  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
798  : MatrixFormVol<Scalar>(gto, gfrom),
799  GenericForm(matprop, mesh, geom_type),
800  gto(gto), gfrom(gfrom)
801  {};
802 
803  Jacobian(unsigned int gto, unsigned int gfrom, std::string area,
804  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
805  : MatrixFormVol<Scalar>(gto, gfrom),
806  GenericForm(matprop, mesh, geom_type),
807  gto(gto), gfrom(gfrom)
808  {
809  this->set_area(area);
810  };
811 
812  template<typename Real, typename ScalarTestFns>
813  ScalarTestFns matrix_form(int n, double *wt, Func<ScalarTestFns> *u_ext[], Func<Real> *u,
814  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
815 
816  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *u,
817  Func<double> *v, GeomVol<double> *e, Func<Scalar> **ext) const {
818  return -1.0 * matrix_form<double, Scalar>(n, wt, u_ext, u, v, e, ext);
819  }
820 
821  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *u,
823  return matrix_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, u, v, e, ext);
824  }
825 
826  // This is to make the form usable in rk_time_step_newton().
827  virtual MatrixFormVol<Scalar>* clone() const {
828  return new Jacobian(*this);
829  }
830 
831  private:
832 
833  unsigned int gto, gfrom;
834  };
835 
836  template<typename Scalar>
837  class HERMES_API OuterIterationForm : public VectorFormVol<Scalar>, protected GenericForm
838  {
839  public:
840 
841  OuterIterationForm(unsigned int g,
842  const MaterialPropertyMaps& matprop,
843  std::vector<MeshFunctionSharedPtr<Scalar> >& iterates,
844  double keff = 1.0,
845  GeomType geom_type = HERMES_PLANAR)
847  GenericForm(matprop, geom_type),
848  g(g), keff(keff)
849  {
850  //this->wf->set_ext(iterates);
851  if (g >= iterates.size())
852  throw Hermes::Exceptions::Exception(E_INVALID_GROUP_INDEX);
853  }
854 
855  OuterIterationForm(unsigned int g, std::string area,
856  const MaterialPropertyMaps& matprop,
857  std::vector<MeshFunctionSharedPtr<Scalar> >& iterates,
858  double keff = 1.0,
859  GeomType geom_type = HERMES_PLANAR)
861  GenericForm(matprop, geom_type),
862  g(g), keff(keff)
863  {
864  this->set_area(area);
865  //this->wf->set_ext(iterates);
866  if (g >= iterates.size())
867  throw Hermes::Exceptions::Exception(E_INVALID_GROUP_INDEX);
868  }
869 
870  OuterIterationForm(unsigned int g,
871  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
872  std::vector<MeshFunctionSharedPtr<Scalar> >& iterates,
873  double keff = 1.0,
874  GeomType geom_type = HERMES_PLANAR)
876  GenericForm(matprop, mesh, geom_type),
877  g(g), keff(keff)
878  {
879  //this->wf->set_ext(iterates);
880  if (g >= iterates.size())
881  throw Hermes::Exceptions::Exception(E_INVALID_GROUP_INDEX);
882  }
883 
884  OuterIterationForm(unsigned int g, std::string area,
885  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
886  std::vector<MeshFunctionSharedPtr<Scalar> >& iterates,
887  double keff = 1.0,
888  GeomType geom_type = HERMES_PLANAR)
890  GenericForm(matprop, mesh, geom_type),
891  g(g), keff(keff)
892  {
893  this->set_area(area);
894  //this->wf->set_ext(iterates);
895  if (g >= iterates.size())
896  throw Hermes::Exceptions::Exception(E_INVALID_GROUP_INDEX);
897  }
898 
899  template<typename Real, typename ScalarTestFns>
900  ScalarTestFns vector_form(int n, double *wt, Func<ScalarTestFns> *u_ext[],
901  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
902 
903  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *v,
904  GeomVol<double> *e, Func<Scalar> **ext) const {
905  return -1.0 * vector_form<double, Scalar>(n, wt, u_ext, v, e, ext);
906  }
907 
908  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *v,
909  GeomVol<Hermes::Ord> *e, Func<Ord> **ext) const {
910  return vector_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, v, e, ext);
911  }
912 
913  // This is to make the form usable in rk_time_step_newton().
914  virtual VectorFormVol<Scalar>* clone() const {
915  return new OuterIterationForm(*this);
916  }
917 
918  void update_keff(double new_keff) { keff = new_keff; }
919 
920  private:
921 
922  unsigned int g;
923  double keff;
924  };
925 
926  template<typename Scalar>
927  class HERMES_API Residual : public VectorFormVol<Scalar>, protected GenericForm
928  {
929  public:
930  Residual(unsigned int gto, unsigned int gfrom,
931  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
932  : VectorFormVol<Scalar>(gto),
933  GenericForm(matprop, geom_type),
934  gto(gto), gfrom(gfrom)
935  {};
936 
937  Residual(unsigned int gto, unsigned int gfrom, std::string area,
938  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
939  : VectorFormVol<Scalar>(gto),
940  GenericForm(matprop, geom_type),
941  gto(gto), gfrom(gfrom)
942  {
943  this->set_area(area);
944  };
945 
946  Residual(unsigned int gto, unsigned int gfrom,
947  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
948  : VectorFormVol<Scalar>(gto),
949  GenericForm(matprop, mesh, geom_type),
950  gto(gto), gfrom(gfrom)
951  {};
952 
953  Residual(unsigned int gto, unsigned int gfrom, std::string area,
954  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
955  : VectorFormVol<Scalar>(gto),
956  GenericForm(matprop, mesh, geom_type),
957  gto(gto), gfrom(gfrom)
958  {
959  this->set_area(area);
960  };
961 
962  template<typename Real, typename ScalarTestFns>
963  ScalarTestFns vector_form(int n, double *wt, Func<ScalarTestFns> *u_ext[],
964  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
965 
966  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *v,
967  GeomVol<double> *e, Func<Scalar> **ext) const {
968  return -1.0 * vector_form<double, Scalar>(n, wt, u_ext, v, e, ext);
969  }
970 
971  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *v,
972  GeomVol<Hermes::Ord> *e, Func<Ord> **ext) const {
973  return vector_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, v, e, ext);
974  }
975 
976  // This is to make the form usable in rk_time_step_newton().
977  virtual VectorFormVol<Scalar>* clone() const {
978  return new Residual(*this);
979  }
980 
981  private:
982 
983  unsigned int gto, gfrom;
984  };
985  };
986 
987  struct HERMES_API Scattering
988  {
989  template<typename Scalar>
990  class Jacobian : public MatrixFormVol<Scalar>, protected GenericForm
991  {
992  public:
993 
994  Jacobian(unsigned int gto, unsigned int gfrom,
995  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
996  : MatrixFormVol<Scalar>(gto, gfrom),
997  GenericForm(matprop, geom_type),
998  gto(gto), gfrom(gfrom)
999  {};
1000 
1001  Jacobian(unsigned int gto, unsigned int gfrom, std::string area,
1002  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
1003  : MatrixFormVol<Scalar>(gto, gfrom, area),
1004  GenericForm(matprop, geom_type),
1005  gto(gto), gfrom(gfrom)
1006  {};
1007 
1008  Jacobian(unsigned int gto, unsigned int gfrom,
1009  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
1010  : MatrixFormVol<Scalar>(gto, gfrom),
1011  GenericForm(matprop, mesh, geom_type),
1012  gto(gto), gfrom(gfrom)
1013  {};
1014 
1015  Jacobian(unsigned int gto, unsigned int gfrom, std::string area,
1016  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
1017  : MatrixFormVol<Scalar>(gto, gfrom, area),
1018  GenericForm(matprop, mesh, geom_type),
1019  gto(gto), gfrom(gfrom)
1020  {};
1021 
1022  template<typename Real, typename ScalarTestFns>
1023  ScalarTestFns matrix_form(int n, double *wt, Func<ScalarTestFns> *u_ext[], Func<Real> *u,
1024  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
1025 
1026  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *u,
1027  Func<double> *v, GeomVol<double> *e, Func<Scalar> **ext) const {
1028  return -1.0 * matrix_form<double, Scalar>(n, wt, u_ext, u, v, e, ext);
1029  }
1030 
1031  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *u,
1033  return matrix_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, u, v, e, ext);
1034  }
1035 
1036  // This is to make the form usable in rk_time_step_newton().
1037  virtual MatrixFormVol<Scalar>* clone() const {
1038  return new Jacobian(*this);
1039  }
1040 
1041  private:
1042 
1043  unsigned int gto, gfrom;
1044  };
1045 
1046  template<typename Scalar>
1047  class Residual : public VectorFormVol<Scalar>, protected GenericForm
1048  {
1049  public:
1050  Residual(unsigned int gto, unsigned int gfrom,
1051  const MaterialPropertyMaps& matprop,
1052  GeomType geom_type = HERMES_PLANAR)
1053  : VectorFormVol<Scalar>(gto),
1054  GenericForm(matprop, geom_type),
1055  gto(gto), gfrom(gfrom)
1056  {};
1057 
1058  Residual(unsigned int gto, unsigned int gfrom, std::string area,
1059  const MaterialPropertyMaps& matprop,
1060  GeomType geom_type = HERMES_PLANAR)
1061  : VectorFormVol<Scalar>(gto, area),
1062  GenericForm(matprop, geom_type),
1063  gto(gto), gfrom(gfrom)
1064  {};
1065 
1066  Residual(unsigned int gto, unsigned int gfrom,
1067  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1068  GeomType geom_type = HERMES_PLANAR)
1069  : VectorFormVol<Scalar>(gto),
1070  GenericForm(matprop, mesh, geom_type),
1071  gto(gto), gfrom(gfrom)
1072  {};
1073 
1074  Residual(unsigned int gto, unsigned int gfrom, std::string area,
1075  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1076  GeomType geom_type = HERMES_PLANAR)
1077  : VectorFormVol<Scalar>(gto, area),
1078  GenericForm(matprop, mesh, geom_type),
1079  gto(gto), gfrom(gfrom)
1080  {};
1081 
1082  template<typename Real, typename ScalarTestFns>
1083  ScalarTestFns vector_form(int n, double *wt, Func<ScalarTestFns> *u_ext[],
1084  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
1085 
1086  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *v,
1087  GeomVol<double> *e, Func<Scalar> **ext) const {
1088  return -1.0 * vector_form<double, Scalar>(n, wt, u_ext, v, e, ext);
1089  }
1090 
1091  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *v,
1092  GeomVol<Hermes::Ord> *e, Func<Ord> **ext) const {
1093  return vector_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, v, e, ext);
1094  }
1095 
1096  // This is to make the form usable in rk_time_step_newton().
1097  virtual VectorFormVol<Scalar>* clone() const {
1098  return new Residual(*this);
1099  }
1100 
1101  private:
1102 
1103  unsigned int gto, gfrom;
1104  };
1105  };
1106 
1107  struct HERMES_API ExternalSources
1108  {
1109  template<typename Scalar>
1110  class LinearForm : public VectorFormVol<Scalar>, protected GenericForm
1111  {
1112  public:
1113 
1114  LinearForm(unsigned int g,
1115  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
1116  : VectorFormVol<Scalar>(g),
1117  GenericForm(matprop, geom_type),
1118  g(g)
1119  {};
1120 
1121  LinearForm(unsigned int g, std::string area,
1122  const MaterialPropertyMaps& matprop, GeomType geom_type = HERMES_PLANAR)
1123  : VectorFormVol<Scalar>(g, area),
1124  GenericForm(matprop, geom_type),
1125  g(g)
1126  {};
1127 
1128  LinearForm(unsigned int g,
1129  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
1130  : VectorFormVol<Scalar>(g),
1131  GenericForm(matprop, mesh, geom_type),
1132  g(g)
1133  {};
1134 
1135  LinearForm(unsigned int g, std::string area,
1136  const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type = HERMES_PLANAR)
1137  : VectorFormVol<Scalar>(g, area),
1138  GenericForm(matprop, mesh, geom_type),
1139  g(g)
1140  {};
1141 
1142  template<typename Real, typename ScalarTestFns>
1143  ScalarTestFns vector_form(int n, double *wt, Func<ScalarTestFns> *u_ext[],
1144  Func<Real> *v, GeomVol<Real> *e, Func<ScalarTestFns> **ext) const;
1145 
1146  virtual Scalar value(int n, double *wt, Func<Scalar> *u_ext[], Func<double> *v,
1147  GeomVol<double> *e, Func<Scalar> **ext) const {
1148  return -1.0 * vector_form<double, Scalar>(n, wt, u_ext, v, e, ext);
1149  }
1150 
1151  virtual Hermes::Ord ord(int n, double *wt, Func<Hermes::Ord> *u_ext[], Func<Hermes::Ord> *v,
1152  GeomVol<Hermes::Ord> *e, Func<Ord> **ext) const {
1153  return vector_form<Hermes::Ord, Hermes::Ord>(n, wt, u_ext, v, e, ext);
1154  }
1155 
1156  // This is to make the form usable in rk_time_step_newton().
1157  virtual VectorFormVol<Scalar>* clone() const {
1158  return new LinearForm(*this);
1159  }
1160 
1161  private:
1162 
1163  unsigned int g;
1164  };
1165  };
1166  }
1167  }
1168 
1169  namespace CompleteWeakForms
1170  {
1171  namespace Diffusion
1172  {
1173  using namespace MaterialProperties;
1174  using namespace ElementaryForms::Diffusion;
1175 
1176  template<typename Scalar>
1177  class HERMES_API DefaultWeakFormFixedSource : public WeakForm < Scalar >
1178  {
1179  protected:
1180  void lhs_init(unsigned int G, const MaterialPropertyMaps& matprop, MeshSharedPtr mesh, GeomType geom_type);
1181 
1182  public:
1183  DefaultWeakFormFixedSource(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1184  GeomType geom_type = HERMES_PLANAR);
1185 
1186  DefaultWeakFormFixedSource(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1187  Hermes2DFunction<Scalar>*f_src,
1188  std::string src_area = HERMES_ANY,
1189  GeomType geom_type = HERMES_PLANAR);
1190 
1191  DefaultWeakFormFixedSource(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1192  Hermes2DFunction<Scalar>*f_src,
1193  std::vector<std::string> src_areas,
1194  GeomType geom_type = HERMES_PLANAR);
1195 
1196  DefaultWeakFormFixedSource(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1197  const std::vector<Hermes2DFunction<Scalar>*>& f_src,
1198  std::string src_area = HERMES_ANY,
1199  GeomType geom_type = HERMES_PLANAR);
1200 
1201  DefaultWeakFormFixedSource(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1202  const std::vector<Hermes2DFunction<Scalar>*>& f_src,
1203  std::vector<std::string> src_areas,
1204  GeomType geom_type = HERMES_PLANAR);
1205  };
1206 
1207  template<typename Scalar>
1208  class HERMES_API DefaultWeakFormSourceIteration : public WeakForm < Scalar >
1209  {
1210  protected:
1211  std::vector<FissionYield::OuterIterationForm<Scalar>*> keff_iteration_forms;
1212 
1213  public:
1214  DefaultWeakFormSourceIteration(const MaterialPropertyMaps& matprop, MeshSharedPtr mesh,
1215  std::vector<MeshFunctionSharedPtr<Scalar> >& iterates,
1216  double initial_keff_guess,
1217  GeomType geom_type = HERMES_PLANAR);
1218 
1219  void update_keff(double new_keff);
1222  double get_keff() { return 0.0; };
1223  };
1224  }
1225  }
1226 
1227  namespace SupportClasses
1228  {
1229  using MaterialProperties::Common::MaterialPropertyMaps;
1230  using namespace MaterialProperties::Definitions;
1231 
1232  class HERMES_API SourceFilter : public SimpleFilter < double >
1233  {
1234  public:
1235  SourceFilter(std::vector<MeshFunctionSharedPtr<double> > solutions, const MaterialPropertyMaps* matprop,
1236  const std::string& source_area)
1237  : SimpleFilter<double>(solutions, std::vector<int>()), matprop(matprop), source_area(source_area)
1238  {
1239  nu = matprop->get_nu().at(source_area);
1240  Sigma_f = matprop->get_Sigma_f().at(source_area);
1241  }
1242  private:
1243  rank1 nu;
1244  rank1 Sigma_f;
1245  const MaterialPropertyMaps* matprop;
1246  const std::string& source_area;
1247 
1248  void filter_fn(int n, const std::vector<const double*>& values, double* result);
1249 
1250  MeshFunction<double>* clone() const { return new SourceFilter(this->solutions, matprop, source_area); }
1251  };
1252  }
1253  }
1254  }
1255  }
1256 }
1257 #endif
Geometry - volumetric - for order calculation.
Definition: forms.h:90
Definition: adapt.h:24
Abstract, base class for vector Surface form - i.e. VectorForm, where the integration is with respect...
Definition: weakform.h:48
Abstract, base class for matrix Surface form - i.e. MatrixForm, where the integration is with respect...
Definition: weakform.h:47
Represents the weak formulation of a PDE problem.
Definition: global.h:86
Calculated function values (from the class Function) on an element for assembling.
Definition: forms.h:214
::xsd::cxx::tree::string< char, simple_type > string
C++ type corresponding to the string XML Schema built-in type.
Geometry - surface - for order calculation.
Definition: forms.h:111
Abstract, base class for matrix Volumetric form - i.e. MatrixForm, where the integration is with resp...
Definition: weakform.h:45
GeomType
Geometrical type of weak forms.
Definition: global.h:148
Abstract, base class for vector Volumetric form - i.e. VectorForm, where the integration is with resp...
Definition: weakform.h:46