openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
mechanics.cc
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
27 #include "mechanics.h"
28 #include "mechanic_integrators.h"
29 #include "petsc_utils.h"
30 #include "constitutive_model.h"
31 #include "constitutive_model_library.h"
32 #include "SF_init.h"
33 
34 namespace opencarp {
35 
36 
40 PetscErrorCode equilibrium_solver_internal_forces_petsc_helperfunction(SNES snes, Vec du, Vec resid, void * solver_pointer)
41 {
42  Mechanics * mech = reinterpret_cast<Mechanics *>(user_globals::physics_reg[mech_phys]);
43  equilibrium_solver * solver = reinterpret_cast<equilibrium_solver *>(solver_pointer);
44  SF::petsc_vector<int, double> * position = reinterpret_cast<SF::petsc_vector<int, double> *>(solver->position);
45 
46  PetscErrorCode ierr;
47  //change nodal coords based on du
48  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
49  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
50  ierr = VecAXPY(position->data, 1.0, du); CHKERRQ(ierr);
51  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
52  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
53 
54  const SF::vector<mesh_int_t> & alg_nod = get_mesh(elasticity_msh).pl.algebraic_nodes();
57 
58  solver->update_node_coords();
59  solver->f_internal->set(0.0); // set f_internal to 0 before calculating new force
60  solver->calc_internal_forces(mech->mtype, mech->logger);
61 
63 
64  solver->f_external->set(0.0);
65 
66  for (int nmbc_idx = 0; nmbc_idx < param_globals::num_mech_nbcs; nmbc_idx++) {
67  solver->apply_external_forces(mech->mtype, mech->logger, mech->surfmesh, solver->nmbcs[nmbc_idx]);
68  }
69  SF::petsc_vector<int, double> * f_internal = reinterpret_cast<SF::petsc_vector<int, double> *>(solver->f_internal);
70  SF::petsc_vector<int, double> * residuum = reinterpret_cast<SF::petsc_vector<int, double> *>(solver->residuum);
71  SF::petsc_vector<int, double> * f_external = reinterpret_cast<SF::petsc_vector<int, double> *>(solver->f_external);
72  residuum->set(0.0);
73  residuum->add_scaled(*f_internal, 1.0);
74  residuum->add_scaled(*f_external, -1.0);
75  ierr = VecAssemblyBegin(resid); CHKERRQ(ierr);
76  ierr = VecAssemblyEnd(resid); CHKERRQ(ierr);
77  ierr = VecCopy(residuum->data, resid); CHKERRQ(ierr);
78  ierr = VecAssemblyBegin(resid); CHKERRQ(ierr);
79  ierr = VecAssemblyEnd(resid); CHKERRQ(ierr);
80 
81  // reset nodal coords to the ones before this iteration
82  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
83  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
84  ierr = VecAXPY(position->data, -1.0, du); CHKERRQ(ierr);
85  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
86  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
87  ierr = VecAssemblyBegin(resid); CHKERRQ(ierr);
88  ierr = VecAssemblyEnd(resid); CHKERRQ(ierr);
89  solver->update_node_coords();
90 #ifdef DEBUG_INT
91  PetscScalar resid_norm;
92  VecNorm(resid, NORM_2, &resid_norm);
93  printf("\n Residuum on rank %d: %e", PetscGlobalRank, resid_norm);
94  ierr = VecAssemblyBegin(resid); CHKERRQ(ierr);
95  ierr = VecAssemblyEnd(resid); CHKERRQ(ierr);
96 #endif
97  return ierr;
98 }
99 
103 PetscErrorCode equilibrium_solver_jacobian_petsc_helperfunction(SNES snes, Vec du, Mat jacobian, Mat preconditioner_mat, void * solver_pointer)
104 {
105  PetscErrorCode ierr;
106  Mechanics * mech = reinterpret_cast<Mechanics *>(user_globals::physics_reg[mech_phys]);
107  equilibrium_solver * solver = reinterpret_cast<equilibrium_solver *>(solver_pointer);
108  SF::petsc_vector<int, double> * position = reinterpret_cast<SF::petsc_vector<int, double> *>(solver->position);
109  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
110  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
111  ierr = VecAXPY(position->data, 1.0, du); CHKERRQ(ierr);
112  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
113  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
114  solver->K_eq->zero();
115  solver->update_node_coords();
116  solver->rebuild_stiffness(mech->mtype, mech->logger);
117  SF::petsc_matrix<mesh_int_t, mesh_real_t> * K_eq = reinterpret_cast<SF::petsc_matrix<mesh_int_t, mesh_real_t> *>(solver->K_eq);
118  ierr = MatAssemblyBegin(preconditioner_mat, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
119  ierr = MatAssemblyEnd(preconditioner_mat, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
120  ierr = MatCopy(K_eq->data, preconditioner_mat, DIFFERENT_NONZERO_PATTERN); CHKERRQ(ierr);
121  ierr = MatAssemblyBegin(preconditioner_mat, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
122  ierr = MatAssemblyEnd(preconditioner_mat, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
123 
124  // set position again to where it was before calculating the jacobian
125  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
126  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
127  ierr = VecAXPY(position->data, -1.0, du); CHKERRQ(ierr);
128  ierr = VecAssemblyBegin(du); CHKERRQ(ierr);
129  ierr = VecAssemblyEnd(du); CHKERRQ(ierr);
130 
131  solver->update_node_coords();
132 
133 
134  if(jacobian != preconditioner_mat)
135  {
136  ierr = MatAssemblyBegin(jacobian, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
137  ierr = MatAssemblyEnd(jacobian, MAT_FINAL_ASSEMBLY); CHKERRQ(ierr);
138  }
139  return ierr;
140 }
141 
146 {
147  double t1, t2;
148  get_time(t1);
149 
150  set_dir(OUTPUT);
151 
152  // open logger
153  logger = f_open("mechanics.log", param_globals::experiment != 4 ? "w" : "r");
154 
155  setup_mappings();
156 
157  double global_time = user_globals::tm_manager->time;
158  timer_idx = user_globals::tm_manager->add_eq_timer(global_time, param_globals::tend, 0,
159  param_globals::dt, 0, "elec::ref_dt", "TS");
160 
161  // generate the surface mesh
163  mesh.xyz_Euler = mesh.xyz;
165  // give surfmesh the same nodes, numberings etc
166  surfmesh.g_numpts = mesh.g_numpts;
167  surfmesh.l_numpts = mesh.l_numpts;
168  surfmesh.xyz = mesh.xyz;
170  surfmesh.nbr = mesh.nbr;
171  surfmesh.pl = mesh.pl;
172  // register the mechanics material model
173  register_material_model();
174  // set up the linear equation systems.
175  log_msg(logger,0,0, "\n Setting up Mechanical Solvers \n");
176  setup_solvers();
177 
178  // prepare the mechanics output. we skip it if we do post-processing
179  if(param_globals::experiment != EXP_POSTPROCESS)
180  setup_output();
181 
182  this->initialize_time += timing(t2, t1);
183 }
184 
188 void Mechanics::setup_mappings() //currently mostly copied from electrics setup_mapping
189 {
190  bool mech_mesh_exits = mesh_is_registered(elasticity_msh);
191  assert(mech_mesh_exits);
192  const int dpn = 3;
193 
194  // It may be that another physic (e.g. electrics) has already computed the mappings,
195  // thus we first test their existence
196  if(get_scattering(elasticity_msh, ALG_TO_NODAL, dpn) == NULL) {
197  log_msg(logger, 0, 0, "%s: Setting up mechanics algebraic-to-nodal scattering.", __func__);
199  }
201  log_msg(logger, 0, 0, "%s: Setting up mechanics PETSc to canonical permutation.", __func__);
203  }
204 }
205 
210 {
211  double t1, t2;
212  get_time(t1);
213  sf_mesh & mesh = get_mesh(elasticity_msh);
214 // checkpointing(); // not yet implemented
215 
216  if(&eq_solver)
217  {
218  size_t nelem = mesh.g_numelem;
219  surfmesh.xyz_Euler = mesh.xyz_Euler; //updates nodal coordinates of surface mesh
221 
222  const SF::vector<mesh_int_t>& alg_nod_surf = surfmesh.pl.algebraic_nodes();
223  const SF::vector<mesh_int_t>& alg_dsp_surf = surfmesh.pl.algebraic_layout();
225  const SF::vector<mesh_int_t>& alg_nod_vol = mesh.pl.algebraic_nodes();
226  const SF::vector<mesh_int_t>& alg_dsp_vol = mesh.pl.algebraic_layout();
227  const SF::vector<mesh_int_t>& ref_nbr_vol = mesh.get_numbering(SF::NBR_REF);
228  for (int nmbc_idx = 0; nmbc_idx < param_globals::num_mech_nbcs; nmbc_idx++) {
230  }
231  eq_solver.solve();
232  // update nodal coordinates with calculated du
238  }
239  this->compute_time += timing(t2, t1);
240 }
241 
243 {
244  double t1, t2;
245  get_time(t1);
247  this->output_time += timing(t2, t1);
248 }
249 
254 {
255  // TODO
256  // close logger
257  f_close(logger);
258 }
259 
260 void Mechanics::setup_output()
261 {
262  set_dir(OUTPUT);
263  output_manager.register_output(eq_solver.displacement, elasticity_msh, 3, param_globals::ufile, "mm");
264  output_manager.register_output(eq_solver.position, elasticity_msh, 3, param_globals::dynptfile, "mm");
265  output_manager.register_output(eq_solver.f_internal, elasticity_msh, 3, param_globals::Ffile, "kN");
266  output_manager.register_output(eq_solver.residuum, elasticity_msh, 3, param_globals::Residfile, "kN");
267 }
268 
269 void Mechanics::dump_matrices()
270 {
271  std::string bsname = param_globals::dump_basename;
272  std::string fn;
273  // TODO
274  set_dir(OUTPUT);
275 }
276 
277 
280 double Mechanics::timer_val(const int timer_id)
281 {
282  double val = 0.0;
283  // TODO
284  return val;
285 }
286 
290 std::string Mechanics::timer_unit(const int timer_id)
291 {
292  std::string s_unit;
293  // TODO
294 
295  return s_unit;
296 }
297 
301 void Mechanics::setup_solvers()
302 {
303  set_dir(OUTPUT);
304  eq_solver.init();
306 }
307 
311 void Mechanics::checkpointing()
312 {
313  // TODO
314  const timer_manager & tm = *user_globals::tm_manager;
315 }
316 
320 void Mechanics::register_material_model()
321 {
322  mtype.regions.resize(param_globals::num_mech_mat_regions);
323  RegionSpecs* reg = mtype.regions.data();
324  for (std::size_t mreg = 0; mreg < param_globals::num_mech_mat_regions; mreg++) {
325  mechMaterial* mMat = new mechMaterial();
326  mMat->material_type = MechMat;
327  mMat->set_constitutive_model(param_globals::mech_mat_region[mreg].constitutive_model);
328  reg[mreg].material = mMat;
329  }
330 }
331 
336 {
338  log_msg(logger, 0, 0,"Equilibrium solver initialized.");
339 
341 
342  sf_mesh & mechanics_mesh = get_mesh(elasticity_msh);
343  mechanics_mesh.xyz_Euler = mechanics_mesh.xyz;
344  sf_vec::ltype alg_type = sf_vec::algebraic;
345  sf_vec::ltype ele_type = sf_vec::elemwise;
346  sf_vec::ltype nodal_type = sf_vec::nodal;
347  sf_vec::ltype ip_type = sf_vec::ipwise;
348  const int dpn = 3; //dof per node
349 
351  SF::init_vector(&position, mechanics_mesh, dpn, alg_type);
352  SF::init_vector(&reference_pos, mechanics_mesh, dpn, alg_type);
353  SF::init_vector(&displacement, mechanics_mesh, dpn, alg_type);
356  SF::init_vector(&f_internal, mechanics_mesh, dpn, alg_type);
357  SF::init_vector(&f_external, mechanics_mesh, dpn, alg_type);
358  SF::init_vector(&residuum, mechanics_mesh, dpn, alg_type);
359  SF::init_vector(&dirichlet_bcs, mechanics_mesh, dpn, alg_type);
360  SF::init_vector(&dirichlet_bcs_1, mechanics_mesh, dpn, alg_type);
361 
363 
364  int max_row_entries = max_nodal_edgecount(mechanics_mesh);
365 
368  K_eq->init(mechanics_mesh, dpn, dpn, max_row_entries);
369 
370  displacement->set(0.0);
371 
373  const SF::vector<mesh_int_t>& alg_nod = mechanics_mesh.pl.algebraic_nodes();
374  const SF::vector<mesh_int_t>& alg_dsp = mechanics_mesh.pl.algebraic_layout();
375  const SF::vector<mesh_int_t> & nbr = mechanics_mesh.get_numbering(SF::NBR_REF);
376  std::size_t loc_node;
377 
378  double * pos = position->ptr();
379  double * ref_pos = reference_pos->ptr();
381  for(std::size_t i = 0; i < alg_nod.size(); i++){
382  loc_node = alg_nod[i];
383  for(std::size_t k = 0; k < dpn; k++){
384  pos[3 * i + k] = mechanics_mesh.xyz_Euler[loc_node * 3 + k];
385  ref_pos[3 * i + k] = mechanics_mesh.xyz[loc_node * 3 + k];
386  }
387  }
388  position->release_ptr(pos);
389  reference_pos->release_ptr(ref_pos);
390 
392  std::size_t num_mnbcs = param_globals::num_mech_nbcs;
393  std::size_t num_mdbcs = param_globals::num_mech_dbcs;
394 
395 
396  for(std::size_t dbc_idx = 0; dbc_idx < num_mdbcs; dbc_idx++)
397  {
400  }
401 
402 
403  for(std::size_t nbc_idx = 0; nbc_idx < num_mnbcs; nbc_idx++)
404  {
407  }
408 
409  dirichlet_bcs->set(1); //set all positions of dirichlet_boundary_conditions to 1 as default.
410  dirichlet_bcs_1->set(0);
411 
412  double * dbc_ptr = dirichlet_bcs->ptr();
413  double * dbc1_ptr = dirichlet_bcs_1->ptr();
414 
415  for(size_t dbc_idx = 0; dbc_idx < num_mdbcs; dbc_idx++)
416  {
417  switch (dmbcs[dbc_idx].dbc_type) {
418  case mech_bcs::dbc_t::all:
419  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
420  std::size_t gidx = nbr[alg_nod[lidx]];
421  bool found = FALSE;
422  std::size_t vtx = 0;
423  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
424  {
425  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
426  vtx++;
427  }
428  if (found) {
429  for(size_t k = 0; k < dpn; k++)
430  {
431  dbc_ptr[3 * lidx + k] = 0;
432  dbc1_ptr[3 * lidx + k] = 1;
433  }
434  }
435  }
436  break;
437  case mech_bcs::dbc_t::x:
438  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
439  std::size_t gidx = nbr[alg_nod[lidx]];
440  bool found = FALSE;
441  std::size_t vtx = 0;
442  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
443  {
444  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
445  vtx++;
446  }
447  if (found)
448  {
449  dbc_ptr[3 * lidx] = 0;
450  dbc1_ptr[3 * lidx] = 1;
451  }
452  }
453  break;
454  case mech_bcs::dbc_t::y:
455  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
456  std::size_t gidx = nbr[alg_nod[lidx]];
457  bool found = FALSE;
458  std::size_t vtx = 0;
459  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
460  {
461  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
462  vtx++;
463  }
464  if (found)
465  {
466  dbc_ptr[3 * lidx + 1] = 0;
467  dbc1_ptr[3 * lidx + 1] = 1;
468  }
469  }
470  break;
471  case mech_bcs::dbc_t::z:
472  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
473  std::size_t gidx = nbr[alg_nod[lidx]];
474  bool found = FALSE;
475  std::size_t vtx = 0;
476  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
477  {
478  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
479  vtx++;
480  }
481  if (found)
482  {
483  dbc_ptr[3 * lidx + 2] = 0;
484  dbc1_ptr[3 * lidx + 2] = 1;
485  }
486  }
487  break;
488  case mech_bcs::dbc_t::xy:
489  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
490  std::size_t gidx = nbr[alg_nod[lidx]];
491  bool found = FALSE;
492  std::size_t vtx = 0;
493  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
494  {
495  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
496  vtx++;
497  }
498  if (found)
499  {
500  dbc_ptr[3 * lidx] = 0;
501  dbc_ptr[3 * lidx + 1] = 0;
502  dbc1_ptr[3 * lidx] = 1;
503  dbc1_ptr[3 * lidx + 1] = 1;
504  }
505  }
506  break;
507  case mech_bcs::dbc_t::xz:
508  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
509  std::size_t gidx = nbr[alg_nod[lidx]];
510  bool found = FALSE;
511  std::size_t vtx = 0;
512  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
513  {
514  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
515  vtx++;
516  }
517  if (found)
518  {
519  dbc_ptr[3 * lidx] = 0;
520  dbc_ptr[3 * lidx + 2] = 0;
521  dbc1_ptr[3 * lidx] = 1;
522  dbc1_ptr[3 * lidx + 2] = 1;
523  }
524  }
525  break;
526  case mech_bcs::dbc_t::yz:
527  for (std::size_t lidx = 0; lidx < alg_nod.size(); lidx++) {
528  std::size_t gidx = nbr[alg_nod[lidx]];
529  bool found = FALSE;
530  std::size_t vtx = 0;
531  while (!found && (vtx < dmbcs[dbc_idx].vertices.size()))
532  {
533  found = (gidx == dmbcs[dbc_idx].vertices[vtx]);
534  vtx++;
535  }
536  if (found)
537  {
538  dbc_ptr[3 * lidx + 1] = 0;
539  dbc_ptr[3 * lidx + 2] = 0;
540  dbc1_ptr[3 * lidx + 1] = 1;
541  dbc1_ptr[3 * lidx + 2] = 1;
542  }
543  }
544  break;
545 
546  default:
547  log_msg(logger, 0, 0, "No direction type defined. Default option to fix displacement in all directions at given nodes");
548  break;
549  }
550  }
551 
552  dirichlet_bcs->release_ptr(dbc_ptr);
553  dirichlet_bcs_1->release_ptr(dbc1_ptr);
554 
555  setup_nonlinear_solver(logger);
556 }
557 
562 {
563  double t0, t1, dur;
564  get_time(t0);
565 
566  rebuild_stiffness(mtype, logger);
567 }
568 
573 {
574  double t0, t1, dur;
575  int log_flag = param_globals::output_level > 1 ? ECHO : 0;
576 
577  sf_mesh & mesh = get_mesh(elasticity_msh);
578 
579  get_time(t0);
580 
581  mech_stiffness_integrator m_stfn_integ(mtype);
582  K_eq->zero();
583 
584  SF::assemble_matrix(*K_eq, mesh, m_stfn_integ);
586 
589 
590  dur = timing(t1, t0);
591 }
592 
597 {
598  double to, t1;
599  mech_internal_forces_integrator int_force_int(mt);
600 
601  // get mesh reference
602  sf_mesh & mesh = get_mesh(elasticity_msh);
603  SF::assemble_vector(*f_internal, mesh, int_force_int);
605 }
606 
611 {
612  const SF::vector<mesh_int_t>& alg_nod = surfmesh.pl.algebraic_nodes();
613  const SF::vector<mesh_int_t>& alg_dsp = surfmesh.pl.algebraic_layout();
614  const SF::vector<mesh_int_t>& ref_nbr = surfmesh.get_numbering(SF::NBR_REF);
615 
618  {
619  log_msg(logger, 0, 0, "Applying external forces based on Neumann boundary conditions using a constant pressure for all elements");
620  double time = tm.time + param_globals::dt; //Test
621  double pressure = nmbcs.scaling[1] * time / param_globals::tend; //calculate pressure as function of the time
622  f_external->set(0.0); // then set f_external to zero before each new calculation
624  mesh_real_t area;
625  SF::elem_t type;
626  bool bc0, bc1, bc2, bc3;
627  SF::Point normal;
628  SF::dmat<double> shape;
631  double w[EP_MAX_IPOINTS];
632  double F[9];
633  double iF[9];
634  double detF;
635  SF::dmat<double> gshape;
636  SF::vector<mesh_int_t> nbc_idx_test;
637  double forces[SF_MAX_ELEM_NODES*3];
638  double * f_ext = f_external->ptr();
639  for(size_t eidx = 0; eidx < surfmesh.l_numelem; eidx++) //go through local elements
640  {
641  view.set_elem(eidx);
642  type = view.type();
643  shape.set_size(4, view.num_nodes());
644  SF::Point fib = {1, 0, 0}; // just to satisfy get_transformed_pts
645  int nint;
646  int int_order;
647  switch (type) {
648  case SF::Tri:
649  bc0 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(0)]) != std::end(nmbcs.vertices);
650  bc1 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(1)]) != std::end(nmbcs.vertices);
651  bc2 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(2)]) != std::end(nmbcs.vertices);
652  if(bc0 && bc1 && bc2) //check if all three nodes of the triangle surface element are part of the boundary condition vertices
653  {
654  int_order = 1; //hard-coded for linear elements
655  view.integration_points(int_order, ipts, w, nint);
656  SF::get_transformed_pts(view, lpts, fib);
657  for(std::size_t iidx =0; iidx < nint; iidx++)
658  {
659  SF::reference_shape(type, ipts[iidx], shape);
660 // Calculate area of surface element
661  area = mag(cross(view.coord_upd(2) - view.coord_upd(0), view.coord_upd(1) - view.coord_upd(0)));
662 // Calculate normal of surface element
663  normal = normalize(cross(view.coord_upd(1) - view.coord_upd(0), view.coord_upd(2) - view.coord_upd(0)));
664  for(std::size_t a = 0; a < view.num_nodes(); a++)
665  {
666  std::size_t walker = 0;
667  bool alg_nod_dx_found = FALSE;
668  while(walker < alg_nod.size() && !alg_nod_dx_found)
669  {
670  alg_nod_dx_found = (alg_nod[walker] == view.node(a));
671  walker++;
672  }
673  double sa = shape[0][a];
674  if(alg_nod_dx_found)
675  {
676  f_ext[3 * (walker - 1)] += sa * w[iidx] * area * pressure * normal.x;
677  f_ext[3 * (walker - 1) + 1] += sa * w[iidx] * area * pressure * normal.y;
678  f_ext[3 * (walker - 1) + 2] += sa * w[iidx] * area * pressure * normal.z;
679  }
680  }
681  }
682  }
683 
684  break;
685  case SF::Quad:
686  // TODO, current implementation only works for rectangular quadriliterals
687  bc0 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(0)]) != std::end(nmbcs.vertices);
688  bc1 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(1)]) != std::end(nmbcs.vertices);
689  bc2 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(2)]) != std::end(nmbcs.vertices);
690  bc3 = std::find(std::begin(nmbcs.vertices), std::end(nmbcs.vertices), ref_nbr[view.node(3)]) != std::end(nmbcs.vertices);
691  if(bc0 && bc1 && bc2 && bc3) //check if all four nodes of the rectangle surface element are part of the boundary condition vertices
692  {
693  int_order = 2; //hard-coded for linear elements
694  view.integration_points(int_order, ipts, w, nint);
695  SF::get_transformed_pts(view, lpts, fib);
696  for(std::size_t iidx =0; iidx < nint; iidx++)
697  {
698  SF::reference_shape(type, ipts[iidx], shape);
699 // Calculate area of surface element and scale with 0.25 for Gauss integration
700  area = 0.125 * (mag(cross(view.coord_upd(2) - view.coord_upd(0), view.coord_upd(1) - view.coord_upd(0))) + mag(cross(view.coord_upd(2) - view.coord_upd(0), view.coord_upd(3) - view.coord_upd(0))));
701 // Calculate normal of surface element
702  normal = normalize(cross(view.coord_upd(1) - view.coord_upd(0), view.coord_upd(2) - view.coord_upd(0)));
703  for(std::size_t a = 0; a < view.num_nodes(); a++)
704  {
705  std::size_t walker = 0;
706  bool alg_nod_dx_found = FALSE;
707  while(walker < alg_nod.size() && !alg_nod_dx_found)
708  {
709  alg_nod_dx_found = (alg_nod[walker] == view.node(a));
710  walker++;
711  }
712  double sa = shape[0][a];
713  if(alg_nod_dx_found)
714  {
715  f_ext[3 * (walker - 1)] += sa * w[iidx] * area * pressure * normal.x;
716  f_ext[3 * (walker - 1) + 1] += sa * w[iidx] * area * pressure * normal.y;
717  f_ext[3 * (walker - 1) + 2] += sa * w[iidx] * area * pressure * normal.z;
718  }
719  }
720  }
721  }
722  break;
723  default:
724  break;
725  }
726  }
727  f_external->release_ptr(f_ext);
728  }
729  else
730  {
731  sf_vec * f_buff;
732  f_buff->init(*f_external);
733  f_buff->set(nmbcs.vertices, nmbcs.scaling);
734  }
736 }
737 
738 
740 {
741  double t0,t1;
742  get_time(t0);
743  du->set(0.0);
744  (* nonlin_solver)(* du, * residuum);
745 }
746 
750 void equilibrium_solver::setup_nonlinear_solver(FILE_SPEC logger)
751 {
752  tol = param_globals::cg_tol_eq;
753  max_it = param_globals::cg_maxit_eq;
754  std::string solver_file;
755  solver_file = param_globals::eq_options_file;
756 
757  equilibrium_solver* eq_solve = this;
758 
759  bool has_nullspace = true;
760  nonlin_solver->setup_solver(*residuum, *K_eq, tol, max_it, param_globals::cg_norm_eq, "equilibrium PDE", has_nullspace, logger, solver_file.c_str(), "", equilibrium_solver_internal_forces_petsc_helperfunction, equilibrium_solver_jacobian_petsc_helperfunction, (void *) this);
761 }
762 
766 void mech_bcs::setup(int idx)
767 {
768  if(definition == Neumann)
769  {
770  const mech_nbcs & cur_mnbc = param_globals::mech_nbc[idx];
771  nbc_type = (cur_mnbc.nbc_type == 0) ? mech_bcs::pressure : mech_bcs::force;
772  direction.x = cur_mnbc.direction[0];
773  direction.y = cur_mnbc.direction[1];
774  direction.z = cur_mnbc.direction[2];
775  // get a logger from the physics
777 
778  // these are the criteria for choosing how we extract the nodes for the Nbcs
779  bool vertex_file_given = strlen(cur_mnbc.vtx_file) > 0;
780  bool tag_index_given = cur_mnbc.geomID > -1;
781  // the mesh we need for computing the local vertex indices.
782  const sf_mesh & mesh = get_mesh(elasticity_msh);
783 
784  if(vertex_file_given && tag_index_given)
785  log_msg(0,3,0, "%s warning: More than one region definitions set in Neumann boundary conditions %d", __func__, idx);
786 
787  if(vertex_file_given) {
788  input_filename = cur_mnbc.vtx_file;
789 
790  log_msg(logger, 0, 0, "Neumann bcs region %d: Selecting vertices from file %s", idx, input_filename.c_str());
791 
792  set_dir(INPUT);
793 
794  // we read the indices. they are being localized w.r.t. the provided numbering. In our
795  // case this is always the reference numbering.
796  if(cur_mnbc.vtx_fcn)
797  {
798  if(nbc_type == 0)
799  {
800  log_msg(logger, 0, 0, "Trying to read a vertex file with scaled Neumann boundary conditions but specified pressure type! Aborting!");
801  EXIT(1);
802  }
803  read_indices_with_data(vertices, scaling, input_filename, mesh, SF::NBR_REF, true, 1, PETSC_COMM_WORLD);
804  }
805  else
806  {
807  read_indices(vertices, input_filename, mesh, SF::NBR_REF, true, PETSC_COMM_WORLD);
808  scaling.assign(vertices.size(), cur_mnbc.strength);
809  }
810  int gnum_idx = get_global(vertices.size(), MPI_SUM);
811  if(gnum_idx == 0) {
812  log_msg(0, 5, 0, "Neumann bcs region %d: Specified vertices are not in domain! Aborting!", idx);
813  EXIT(1);
814  }
815  }
816  else if(tag_index_given) {
817 
818  int tag = cur_mnbc.geomID;
819  log_msg(logger, 0, 0, "Neumann bc region %d: Selecting vertices from tag %d", idx, tag);
820 
821  indices_from_region_tag(vertices, mesh, tag);
822  // we restrict the indices to the algebraic subset
823  SF::restrict_to_set(vertices, mesh.pl.algebraic_nodes());
824  }
825  else {
826  log_msg(logger, 0, 0, "Neumann bc region %d: Selecting vertices from shape.", idx);
827 
828  geom_shape shape;
829  shape.type = geom_shape::shape_t(cur_mnbc.geom_type);
830  shape.p0 = cur_mnbc.p0;
831  shape.p1 = cur_mnbc.p1;
832  shape.radius = cur_mnbc.radius;
833 
834  bool nodal = true;
835  indices_from_geom_shape(vertices, mesh, shape, nodal);
836  // we restrict the indices to the algebraic subset
837  SF::restrict_to_set(vertices, mesh.pl.algebraic_nodes());
838 
839  int gsize = vertices.size();
840  if(get_global(gsize, MPI_SUM) == 0) {
841  log_msg(0,5,0, "error: Empty Neumann bc region [%d] def! Aborting!", idx);
842  EXIT(1);
843  }
844  scaling.assign(gsize, cur_mnbc.strength); //read in the strength
845  }
846  if(cur_mnbc.dump_vtx_file) {
848  mesh.pl.globalize(glob_idx);
849 
850  SF::vector<mesh_int_t> srt_idx;
851  SF::sort_parallel(mesh.comm, glob_idx, srt_idx);
852 
853  size_t num_vtx = get_global(srt_idx.size(), MPI_SUM);
854  int rank = get_rank();
855 
856  FILE_SPEC f = NULL;
857  int err = 0;
858 
859  if(rank == 0) {
860  char dump_name[1024];
861  sprintf(dump_name, "NBCs_%d.vtx", idx);
862 
863  f = f_open(dump_name, "w");
864  if(!f) err++;
865  else {
866  fprintf(f->fd, "%zd\nextra\n", num_vtx);
867  }
868  }
869 
870  if(!get_global(err, MPI_SUM)) {
871  print_vector(mesh.comm, srt_idx, 1, f ? f->fd : NULL);
872  } else {
873  log_msg(0, 4, 0, "error: Neumann bc region [%d] cannot be dumped!");
874  }
875 
876  // only root really does that
877  f_close(f);
878  }
879  }
880 
881  if(definition == Dirichlet)
882  {
883  const mech_dbcs & cur_mdbc = param_globals::mech_dbc[idx];
884 
885  // assigning dbc_type
886  switch (cur_mdbc.dbc_type) {
887  case 0:
888  dbc_type = all;
889  break;
890  case 1:
891  dbc_type = x;
892  break;
893  case 2:
894  dbc_type = y;
895  break;
896  case 3:
897  dbc_type = z;
898  break;
899  case 4:
900  dbc_type = xy;
901  break;
902  case 5:
903  dbc_type = xz;
904  break;
905  case 6:
906  dbc_type = yz;
907  break;
908  default:
909  dbc_type = all;
910  break;
911  }
912 
913  // get a logger from the physics
915 
916  // these are the criteria for choosing how we extract the Dbc nodes
917  bool vertex_file_given = strlen(cur_mdbc.vtx_file) > 0;
918  bool tag_index_given = cur_mdbc.geomID > -1;
919  // the mesh we need for computing the local vertex indices.
920  const sf_mesh & mesh = get_mesh(elasticity_msh);
921 
922  if(vertex_file_given && tag_index_given)
923  log_msg(0,3,0, "%s warning: More than one region definitions set in Dirichlet boundary conditions %d", __func__, idx);
924 
925  if(vertex_file_given) {
926  input_filename = cur_mdbc.vtx_file;
927 
928  log_msg(logger, 0, 0, "Dirichlet bcs region %d: Selecting vertices from file %s", idx, input_filename.c_str());
929 
930  set_dir(INPUT);
931 
932  // we read the indices. they are being localized w.r.t. the provided numbering. In our
933  // case this is always the reference numbering.
934  if(cur_mdbc.vtx_fcn)
935  read_indices_with_data(vertices, scaling, input_filename, mesh, SF::NBR_REF, true, 1, PETSC_COMM_WORLD);
936  else
937  read_indices(vertices, input_filename, mesh, SF::NBR_REF, true, PETSC_COMM_WORLD);
938 
939  int gnum_idx = get_global(vertices.size(), MPI_SUM);
940  if(gnum_idx == 0) {
941  log_msg(0, 5, 0, "Dirichlet bcs region %d: Specified vertices are not in domain! Aborting!", idx);
942  EXIT(1);
943  }
944  }
945  else if(tag_index_given) {
946 
947  int tag = cur_mdbc.geomID;
948  log_msg(logger, 0, 0, "Dirichlet bc region %d: Selecting vertices from tag %d", idx, tag);
949 
950  indices_from_region_tag(vertices, mesh, tag);
951  // we restrict the indices to the algebraic subset
952  SF::restrict_to_set(vertices, mesh.pl.algebraic_nodes());
953  }
954  else {
955  log_msg(logger, 0, 0, "Dirichlet bc region %d: Selecting vertices from shape.", idx);
956 
957  geom_shape shape;
958  shape.type = geom_shape::shape_t(cur_mdbc.geom_type);
959  shape.p0 = cur_mdbc.p0;
960  shape.p1 = cur_mdbc.p1;
961  shape.radius = cur_mdbc.radius;
962 
963  bool nodal = true;
964  indices_from_geom_shape(vertices, mesh, shape, nodal);
965  // we restrict the indices to the algebraic subset
966  SF::restrict_to_set(vertices, mesh.pl.algebraic_nodes());
967 
968  int gsize = vertices.size();
969  if(get_global(gsize, MPI_SUM) == 0) {
970  log_msg(0,5,0, "error: Empty Dirichlet bc region [%d] def! Aborting!", idx);
971  EXIT(1);
972  }
973  }
974  if(cur_mdbc.dump_vtx_file) {
976  mesh.pl.globalize(glob_idx);
977 
978  SF::vector<mesh_int_t> srt_idx;
979  SF::sort_parallel(mesh.comm, glob_idx, srt_idx);
980 
981  size_t num_vtx = get_global(srt_idx.size(), MPI_SUM);
982  int rank = get_rank();
983 
984  FILE_SPEC f = NULL;
985  int err = 0;
986 
987  if(rank == 0) {
988  char dump_name[1024];
989  sprintf(dump_name, "DBCs_%d.vtx", idx);
990 
991  f = f_open(dump_name, "w");
992  if(!f) err++;
993  else {
994  fprintf(f->fd, "%zd\nextra\n", num_vtx);
995  }
996  }
997 
998  if(!get_global(err, MPI_SUM)) {
999  print_vector(mesh.comm, srt_idx, 1, f ? f->fd : NULL);
1000  } else {
1001  log_msg(0, 4, 0, "error: Dirichlet bc region [%d] cannot be dumped!");
1002  }
1003 
1004  // only root really does that
1005  f_close(f);
1006  }
1007  }
1008  }
1009 } // namespace opencarp
1010 
double mesh_real_t
Definition: SF_container.h:48
#define SF_MAX_ELEM_NODES
max #nodes defining an element
Definition: SF_fem_utils.h:40
#define ECHO
Definition: basics.h:308
virtual void finish_assembly()=0
virtual void zero()=0
virtual void init(T iNRows, T iNCols, T ilrows, T ilcols, T loc_offset, T mxent)
virtual S * ptr()=0
virtual void release_ptr(S *&p)=0
virtual void set(const vector< T > &idx, const vector< S > &vals, const bool additive=false)=0
virtual void add_scaled(const abstract_vector< T, S > &vec, S k)=0
virtual void init(const meshdata< mesh_int_t, mesh_real_t > &imesh, int idpn, ltype inp_layout)=0
void set_size(const short irows, const short icols)
set the matrix dimensions
Definition: dense_mat.hpp:73
Comfort class. Provides getter functions to access the mesh member variables more comfortably.
Definition: SF_fem_utils.h:705
const T & node(short nidx) const
Access the connectivity information.
Definition: SF_fem_utils.h:795
void integration_points(const short order, Point *ip, double *w, int &nint) const
Definition: SF_fem_utils.h:937
void set_elem(size_t eidx)
Set the view to a new element.
Definition: SF_fem_utils.h:733
elem_t type() const
Getter function for the element type.
Definition: SF_fem_utils.h:773
Point coord_upd(short nidx) const
Access updated vertex coordinates.
Definition: SF_fem_utils.h:854
T num_nodes() const
Getter function for the number of nodes.
Definition: SF_fem_utils.h:763
overlapping_layout< T > pl
nodal parallel layout
Definition: SF_container.h:419
size_t g_numpts
global number of points
Definition: SF_container.h:389
size_t l_numelem
local number of elements
Definition: SF_container.h:388
std::map< SF_nbr, vector< T > > nbr
container for different numberings
Definition: SF_container.h:415
vector< S > xyz_Euler
node coordinates in Euler formulation
Definition: SF_container.h:417
vector< S > xyz
node coordinates in Lagrange formulation
Definition: SF_container.h:416
size_t l_numpts
local number of points
Definition: SF_container.h:390
size_t g_numelem
global number of elements
Definition: SF_container.h:387
MPI_Comm comm
the parallel mesh is defined on a MPI world
Definition: SF_container.h:393
vector< T > & get_numbering(SF_nbr nbr_type)
Get the vector defining a certain numbering.
Definition: SF_container.h:454
size_t size() const
The current size of the vector.
Definition: SF_vector.h:104
void assign(InputIterator s, InputIterator e)
Assign a memory range.
Definition: SF_vector.h:161
int timer_idx
the timer index received from the timer manager
Definition: physics_types.h:66
FILE_SPEC logger
The logger of the physic, each physic should have one.
Definition: physics_types.h:64
void destroy()
Currently we only need to close the file logger.
Definition: mechanics.cc:253
std::string timer_unit(const int timer_id)
figure out units of a signal linked to a given timer
Definition: mechanics.cc:290
double timer_val(const int timer_id)
figure out current value of a signal linked to a given timer
Definition: mechanics.cc:280
equilibrium_solver eq_solver
Definition: mechanics.h:149
MaterialType mtype
Definition: mechanics.h:148
void initialize()
Initialize the Mechanics.
Definition: mechanics.cc:145
igb_output_manager output_manager
class handling the igb output
Definition: mechanics.h:153
void compute_step()
Main function for every compute step.
Definition: mechanics.cc:209
void calc_internal_forces(MaterialType mtype, FILE_SPEC logger)
Calculation of the internal forces based on the deformation.
Definition: mechanics.cc:596
void rebuild_stiffness(MaterialType mtype, FILE_SPEC logger)
rebuild stiffness matrix
Definition: mechanics.cc:572
sf_vec * dirichlet_bcs_1
Dirichlet boundary conditions but with 1 = dbc exists.
Definition: mechanics.h:83
sf_vec * position
position x
Definition: mechanics.h:71
sf_vec * du
incremental displacement du
Definition: mechanics.h:74
sf_mat * K_eq
stiffness matrix for static equilibrium solver K
Definition: mechanics.h:84
int max_it
maximum number of iterations
Definition: mechanics.h:93
double tol
CG stopping tolerance.
Definition: mechanics.h:92
sf_vec * residuum
residuum r
Definition: mechanics.h:79
sf_vec * displacement
absolute displacement u
Definition: mechanics.h:73
void apply_external_forces(MaterialType mtype, FILE_SPEC logger, sf_mesh surfmesh, mech_bcs nmbcs)
Applying external forces from Neumann boundary conditions.
Definition: mechanics.cc:610
sf_vec * f_internal
internal forces f_int
Definition: mechanics.h:76
sf_vec * dirichlet_bcs
Dirichlet boundary conditions, 0 = dbc exists.
Definition: mechanics.h:82
SF::vector< mesh_int_t > dbc_idx
Indices for Dirichlet boundary conditions.
Definition: mechanics.h:80
sf_nl_sol * nonlin_solver
the nonlinear solver
Definition: mechanics.h:89
void rebuild_matrices(MaterialType mtype, FILE_SPEC logger)
rebuild the matrices
Definition: mechanics.cc:561
SF::vector< mesh_int_t > nbc_idx
Indices for Neumann boundary conditions.
Definition: mechanics.h:81
sf_vec * initial_guess
needed for initial guess for nonlinear solver
Definition: mechanics.h:75
mech_bcs nmbcs[10]
Neumann boundary conditions.
Definition: mechanics.h:87
mech_bcs dmbcs[10]
Dirichlet boundary condtions.
Definition: mechanics.h:86
void init()
Initialize equlibirum solver.
Definition: mechanics.cc:335
sf_vec * reference_pos
reference position X
Definition: mechanics.h:72
sf_vec * f_external
external forces f_ext
Definition: mechanics.h:77
class to store shape definitions
Definition: basics.h:381
void write_data()
write registered data to disk
Definition: sim_utils.cc:1442
void register_output(sf_vec *inp_data, const mesh_t inp_meshid, const int dpn, const char *name, const char *units, const SF::vector< mesh_int_t > *idx=NULL, bool elem_data=false)
Register a data vector for output.
Definition: sim_utils.cc:1409
void setup(int idx)
Setup of both Neumann and Dirichlet mechanics boundary conditions.
Definition: mechanics.cc:766
SF::Point direction
direction in which the bc is applied
Definition: mechanics.h:56
dbc_t dbc_type
fixed coordinates
Definition: mechanics.h:55
SF::vector< mesh_int_t > vertices
list of nodes that bc is active on
Definition: mechanics.h:57
std::string input_filename
filename with list of nodes
Definition: mechanics.h:59
SF::vector< SF_real > scaling
scaling for Neumann bcs
Definition: mechanics.h:58
nbc_t nbc_type
pressure given for elements, force given for nodes
Definition: mechanics.h:54
def_t definition
type of boundary condition
Definition: mechanics.h:53
Used to integrate the internal nodel forces per element.
centralize time managment and output triggering
Definition: timer_utils.h:73
int add_eq_timer(double istart, double iend, int ntrig, double iintv, double idur, const char *iname, const char *poolname=nullptr)
Add a equidistant step timer to the array of timers.
Definition: timer_utils.cc:78
double time
current time
Definition: timer_utils.h:76
#define EP_MAX_LPOINTS
maximum supported number of points in a local element
#define EP_MAX_IPOINTS
maximum supported number of integration points
Tissue level mechanics, main Mechanics physics class.
void get_transformed_pts(const element_view< T, S > &view, Point *loc_pts, Point &trsf_fibre)
void init_solver(SF::abstract_linear_solver< T, S > **sol)
Definition: SF_init.h:243
void compute_surface_mesh(const meshdata< T, S > &mesh, const SF_nbr numbering, const hashmap::unordered_set< T > &tags, meshdata< T, S > &surfmesh)
Compute the surface of a given mesh.
void print_vector(MPI_Comm comm, const vector< T > &vec, const short dpn, FILE *fd)
void assemble_vector(abstract_vector< T, S > &vec, meshdata< mesh_int_t, mesh_real_t > &domain, vector_integrator< mesh_int_t, mesh_real_t > &integrator)
Generalized vector assembly.
void sort_parallel(MPI_Comm comm, const vector< T > &idx, vector< T > &out_idx)
Sort index values parallel ascending across the ranks.
void assemble_matrix(abstract_matrix< T, S > &mat, meshdata< mesh_int_t, mesh_real_t > &domain, matrix_integrator< mesh_int_t, mesh_real_t > &integrator)
Generalized matrix assembly.
int max_nodal_edgecount(const meshdata< T, S > &mesh)
Compute the maximum number of node-to-node edges for a mesh.
Definition: SF_container.h:599
void restrict_to_set(vector< T > &v, const hashmap::unordered_set< T > &set)
void init_vector(SF::abstract_vector< T, S > **vec)
Definition: SF_init.h:122
void init_matrix(SF::abstract_matrix< T, S > **mat)
Definition: SF_init.h:222
elem_t
element type enum
Definition: SF_container.h:54
@ Tri
Definition: SF_container.h:61
@ Quad
Definition: SF_container.h:60
void reference_shape(const elem_t type, const Point ip, dmat< double > &rshape)
Compute shape function and its derivatives on a reference element.
Definition: SF_fem_utils.h:383
@ NBR_PETSC
PETSc numbering of nodes.
Definition: SF_container.h:192
@ NBR_ELEM_REF
The element numbering of the reference mesh (the one stored on HD).
Definition: SF_container.h:193
@ NBR_REF
The nodal numbering of the reference mesh (the one stored on HD).
Definition: SF_container.h:190
timer_manager * tm_manager
a manager for the various physics timers
Definition: main.cc:52
std::map< physic_t, Basic_physic * > physics_reg
the physics
Definition: main.cc:50
PetscErrorCode equilibrium_solver_internal_forces_petsc_helperfunction(SNES snes, Vec du, Vec resid, void *solver_pointer)
Helpferfunction necessary for the petsc snes solver to solve the nonlinear problem.
Definition: mechanics.cc:40
vec3< V > normalize(vec3< V > a)
Definition: vect.h:198
SF::scattering * get_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
Get a scattering from the global scatter registry.
sf_mesh & get_mesh(const mesh_t gt)
Get a mesh by specifying the gridID.
Definition: sf_interface.cc:33
SF::scattering * register_scattering(const int from, const int to, const SF::SF_nbr nbr, const int dpn)
Register a scattering between to grids, or between algebraic and nodal representation of data on the ...
Definition: sf_interface.cc:65
SF::scattering * get_permutation(const int mesh_id, const int perm_id, const int dpn)
Get the PETSC to canonical permutation scattering for a given mesh and number of dpn.
int set_dir(IO_t dest)
Definition: sim_utils.cc:452
vec3< V > cross(const vec3< V > &a, const vec3< V > &b)
Definition: vect.h:144
int get_rank(MPI_Comm comm=PETSC_COMM_WORLD)
Definition: basics.h:276
T get_global(T in, MPI_Op OP, MPI_Comm comm=PETSC_COMM_WORLD)
Do a global reduction on a variable.
Definition: basics.h:233
FILE_SPEC f_open(const char *fname, const char *mode)
Open a FILE_SPEC.
Definition: basics.cc:135
SF::scattering * register_permutation(const int mesh_id, const int perm_id, const int dpn)
Register a permutation between two orderings for a mesh.
V mag(const vec3< V > &vect)
Definition: vect.h:131
PetscErrorCode equilibrium_solver_jacobian_petsc_helperfunction(SNES snes, Vec du, Mat jacobian, Mat preconditioner_mat, void *solver_pointer)
Helpferfunction necessary for the petsc snes solver to compute the jacobian.
Definition: mechanics.cc:103
@ OUTPUT
Definition: sim_utils.h:52
void indices_from_region_tag(SF::vector< mesh_int_t > &idx, const sf_mesh &mesh, const int tag)
Populate vertex data with the vertices of a given tag region.
Definition: fem_utils.cc:155
void indices_from_geom_shape(SF::vector< mesh_int_t > &idx, const sf_mesh &mesh, const geom_shape shape, const bool nodal)
Populate vertex data with the vertices inside a defined box shape.
Definition: fem_utils.cc:169
void log_msg(FILE_SPEC out, int level, unsigned char flag, const char *fmt,...)
Definition: basics.cc:72
@ elasticity_msh
Definition: sf_interface.h:64
void get_time(double &tm)
Definition: basics.h:436
bool mesh_is_registered(const mesh_t gt)
check wheter a SF mesh is set
Definition: sf_interface.cc:59
Basic_physic * get_physics(physic_t p, bool error_if_missing)
Convinience function to get a physics.
Definition: sim_utils.cc:824
void read_indices_with_data(SF::vector< T > &idx, SF::vector< S > &dat, const std::string filename, const hashmap::unordered_map< mesh_int_t, mesh_int_t > &dd_map, const int dpn, MPI_Comm comm)
like read_indices, but with associated data for each index
Definition: fem_utils.h:269
V timing(V &t2, const V &t1)
Definition: basics.h:448
void read_indices(SF::vector< T > &idx, const std::string filename, const hashmap::unordered_map< mesh_int_t, mesh_int_t > &dd_map, MPI_Comm comm)
Read indices from a file.
Definition: fem_utils.h:120
void f_close(FILE_SPEC &f)
Close a FILE_SPEC.
Definition: basics.cc:162
@ MechMat
Definition: fem_types.h:42
#define PETSC_TO_CANONICAL
Permute algebraic data from PETSC to canonical ordering.
Definition: sf_interface.h:76
#define ALG_TO_NODAL
Scatter algebraic to nodal.
Definition: sf_interface.h:74
#define EXP_POSTPROCESS
Definition: sim_utils.h:160
Point and vector struct.
Definition: SF_container.h:66
double y
Definition: SF_container.h:68
double z
Definition: SF_container.h:69
double x
Definition: SF_container.h:67
virtual void setup_solver(abstract_vector< T, S > &residuum, abstract_matrix< T, S > &mat, double tol, int max_it, short norm, const char *name, bool has_nullspace, void *logger, const char *solver_opts_file, const char *default_opts, PetscErrorCode function(SNES, Vec, Vec, void *), PetscErrorCode jacobian(SNES, Vec, Mat, Mat, void *), void *solver_pointer=NULL)=0
description of materal properties in a mesh
Definition: fem_types.h:155
SF::vector< RegionSpecs > regions
array with region params
Definition: fem_types.h:160
File descriptor struct.
Definition: basics.h:133