v0.16.0
Loading...
Searching...
No Matches
CellForces.hpp
Go to the documentation of this file.
1/* Copyright (c) 2025 Authors under the MIT License.
2 * See LICENSE.md for details.
3 * SPDX-License-Identifier: MIT
4 */
5
6#ifndef __CELL_FORCES_HPP__
7#define __CELL_FORCES_HPP__
8
9namespace CellEngineering {
10
17
18/**
19 * Common data structure used to pass data between operators
20 */
21struct CommonData {
22
23 MatrixDouble forceAtGaussPts;
26
27 boost::shared_ptr<VectorDouble> dispX;
28 boost::shared_ptr<VectorDouble> dispY;
29
31 : dispX(boost::shared_ptr<VectorDouble>(new VectorDouble())),
32 dispY(boost::shared_ptr<VectorDouble>(new VectorDouble())) {}
33};
34
35/**
36 * Face element used to run operators
37 */
43
44/**
45 * Operator to get measured displacements in X-direction on the face
46 */
48 OpGetDispX(CommonData &common_data)
49 : MoFEM::OpCalculateScalarFieldValues("DISP_X", common_data.dispX) {}
50};
51
52/**
53 * Operator to get measured displacements in Y-direction on the face
54 */
56 OpGetDispY(CommonData &common_data)
57 : MoFEM::OpCalculateScalarFieldValues("DISP_Y", common_data.dispY) {}
58};
59
60/**
61 * \brief Calculate and assemble D matrix
62 */
65
66 Mat A;
67 const double epsRho;
68
69 OpCellPotentialD(Mat a, const double rho)
71 "RHO", "RHO", UserDataOperator::OPROWCOL),
72 A(a), epsRho(rho) {
73 sYmm = false;
74 }
75
76 MatrixDouble C;
77
78 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
79 EntityType col_type,
80 DataForcesAndSourcesCore::EntData &row_data,
81 DataForcesAndSourcesCore::EntData &col_data) {
82
84
85 int nb_row = row_data.getIndices().size();
86 int nb_col = col_data.getIndices().size();
87
88 if (nb_row == 0)
90 if (nb_col == 0)
92
93 const VectorInt &row_indices = row_data.getIndices();
94 const VectorInt &col_indices = col_data.getIndices();
95
96 const int nb_gauss_pts = row_data.getN().size1();
97
98 C.resize(nb_row, nb_col, false);
99 C.clear();
100 for (int gg = 0; gg != nb_gauss_pts; gg++) {
101 // get integration weights
102 const double val = getGaussPts()(2, gg) * getArea() * epsRho;
103 for (int rr = 0; rr != nb_row; rr++) {
104 const double diff_nr_x = row_data.getDiffN()(gg, 2 * rr + 0);
105 const double diff_nr_y = row_data.getDiffN()(gg, 2 * rr + 1);
106 for (int cc = 0; cc != nb_col; cc++) {
107 const double diff_nc_x = col_data.getDiffN()(gg, 2 * cc + 0);
108 const double diff_nc_y = col_data.getDiffN()(gg, 2 * cc + 1);
109 C(rr, cc) += val * (diff_nr_x * diff_nc_x + diff_nr_y * diff_nc_y);
110 }
111 }
112 }
113
114 CHKERR MatSetValues(A, nb_row, &*row_indices.begin(), nb_col,
115 &*col_indices.begin(), &*C.data().begin(), ADD_VALUES);
116
118 }
119};
120
121/**
122 * \brief Calculate and assemble B matrix
123
124 \f[
125 \mathbf{B} = \int_{S_0}
126 \mathbf{N}^\textrm{T}_\textrm{u} \frac{\partial \mathbf{N}_\rho}{\partial
127 \mathbf{x}} \textrm{d}S \f]
128
129 */
132
133 Mat A;
134
135 OpCellPotentialB(Mat a, const string field_name)
138 A(a) {
139 sYmm = false;
140 }
141
142 MatrixDouble C;
143
144 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
145 EntityType col_type,
146 DataForcesAndSourcesCore::EntData &row_data,
147 DataForcesAndSourcesCore::EntData &col_data) {
148
150
151 int nb_row = row_data.getIndices().size();
152 int nb_col = col_data.getIndices().size();
153
154 if (nb_row == 0)
156 if (nb_col == 0)
158
159 const VectorInt &row_indices = row_data.getIndices();
160 const VectorInt &col_indices = col_data.getIndices();
161
162 const int nb_gauss_pts = row_data.getN().size1();
163
164 C.resize(nb_row, nb_col, false);
165 C.clear();
166 for (int gg = 0; gg != nb_gauss_pts; gg++) {
167 // get integration weights
168 const double val = getGaussPts()(2, gg) * getArea();
169 for (int rr = 0; rr != nb_row; rr++) {
170 const double diff_nr_x = row_data.getDiffN()(gg, 2 * rr + 0);
171 const double diff_nr_y = row_data.getDiffN()(gg, 2 * rr + 1);
172 for (int cc = 0; cc != nb_col / 3; cc++) {
173 const double nc = col_data.getN(gg)[cc];
174 C(rr, 3 * cc + 0) -= val * diff_nr_x * nc;
175 C(rr, 3 * cc + 1) -= val * diff_nr_y * nc;
176 }
177 }
178 }
179
180 CHKERR MatSetValues(A, nb_row, &*row_indices.begin(), nb_col,
181 &*col_indices.begin(), &*C.data().begin(), ADD_VALUES);
182
184 }
185};
186
187/**
188 * \brief Calculate and assemble S matrix
189
190 */
193
194 Mat A;
195 const double epsU;
196
197 OpCellS(Mat a, const double eps_u)
199 "UPSILON", "U", UserDataOperator::OPROWCOL),
200 A(a), epsU(eps_u) {
201 sYmm = false;
202 }
203
204 MatrixDouble C;
205
206 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
207 EntityType col_type,
208 DataForcesAndSourcesCore::EntData &row_data,
209 DataForcesAndSourcesCore::EntData &col_data) {
210
212
213 int nb_row = row_data.getIndices().size();
214 int nb_col = col_data.getIndices().size();
215
216 if (nb_row == 0)
218 if (nb_col == 0)
220
221 const VectorInt &row_indices = row_data.getIndices();
222 const VectorInt &col_indices = col_data.getIndices();
223
224 const int nb_gauss_pts = row_data.getN().size1();
225
226 C.resize(nb_row, nb_col, false);
227 C.clear();
228 for (int gg = 0; gg != nb_gauss_pts; gg++) {
229 // get integration weights
230 const double val = getGaussPts()(2, gg) * getArea() * pow(epsU, -1);
231 for (int rr = 0; rr != nb_row / 3; rr++) {
232 const double nr = row_data.getN(gg)[rr];
233 for (int cc = 0; cc != nb_col / 3; cc++) {
234 const double nc = col_data.getN(gg)[cc];
235 const double c = val * nr * nc;
236 C(3 * rr + 0, 3 * cc + 0) += c;
237 C(3 * rr + 1, 3 * cc + 1) += c;
238 }
239 }
240 }
241
242 CHKERR MatSetValues(A, nb_row, &*row_indices.begin(), nb_col,
243 &*col_indices.begin(), &*C.data().begin(), ADD_VALUES);
244
246 }
247};
248
249/**
250 * \brief Calculate and assemble g vector
251
252 \f[
253 \mathbf{g} = \int_{S_1} \mathbf{N}^\textrm{T}_\textrm{u} \overline{\mathbf{u}}
254 \textrm{d}S, \f]
255
256 */
259
260 Vec F;
261 const double epsU;
263
264 OpCell_g(Vec f, const double eps_u, CommonData &common_data)
266 "UPSILON", UserDataOperator::OPROW),
267 F(f), epsU(eps_u), commonData(common_data) {}
268
269 VectorDouble nF;
270
271 MoFEMErrorCode doWork(int side, EntityType type,
272 DataForcesAndSourcesCore::EntData &data) {
273
275
276 int nb_row = data.getIndices().size();
277 if (nb_row == 0)
279
280 const VectorDouble &disp_x = *commonData.dispX;
281 const VectorDouble &disp_y = *commonData.dispY;
282
283 const int nb_gauss_pts = data.getN().size1();
284
285 nF.resize(nb_row, false);
286 nF.clear();
287 for (int gg = 0; gg != nb_gauss_pts; gg++) {
288 const double val = getGaussPts()(2, gg) * getArea() * pow(epsU, -1);
289 for (int rr = 0; rr != nb_row / 3; rr++) {
290 const double nr = val * data.getN(gg)[rr];
291 nF[3 * rr + 0] += nr * disp_x[gg];
292 nF[3 * rr + 1] += nr * disp_y[gg];
293 }
294 }
295 // assemble local face vector
296 CHKERR VecSetValues(F, nb_row, &data.getIndices()[0], &nF[0], ADD_VALUES);
297
299 }
300};
301
302/**
303 * \brief Calculate and assemble Z matrix
304 */
307
308 Mat A;
309 const double epsRho;
310 const double epsL;
311
312 OpCellCurlD(Mat a, const double eps_rho, const double eps_l)
314 "RHO", "RHO", UserDataOperator::OPROWCOL),
315 A(a), epsRho(eps_rho), epsL(eps_l) {
316 sYmm = false;
317 }
318
319 MatrixDouble C;
320
321 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
322 EntityType col_type,
323 DataForcesAndSourcesCore::EntData &row_data,
324 DataForcesAndSourcesCore::EntData &col_data) {
325
327
328 int nb_row = row_data.getIndices().size();
329 int nb_col = col_data.getIndices().size();
330
331 if (nb_row == 0)
333 if (nb_col == 0)
335
336 const VectorInt &row_indices = row_data.getIndices();
337 const VectorInt &col_indices = col_data.getIndices();
338
339 const int nb_gauss_pts = row_data.getN().size1();
340
341 auto t_diff_base_row = row_data.getFTensor2DiffN<3, 2>();
342 auto t_base_row = row_data.getFTensor1N<3>();
343
344 FTensor::Index<'i', 3> i;
345 FTensor::Index<'j', 2> j;
348
349 C.resize(nb_row, nb_col, false);
350 C.clear();
351 for (int gg = 0; gg != nb_gauss_pts; gg++) {
352 // get integration weights
353 const double val = getGaussPts()(2, gg) * getArea();
354 for (int rr = 0; rr != nb_row; rr++) {
355 const double curl_row = t_diff_base_row(1, 0) - t_diff_base_row(0, 1);
356 auto t_diff_base_col = col_data.getFTensor2DiffN<3, 2>(gg, 0);
357 auto t_base_col = col_data.getFTensor1N<3>(gg, 0);
358 for (int cc = 0; cc != nb_col; cc++) {
359 const double curl_col = t_diff_base_col(1, 0) - t_diff_base_col(0, 1);
360 const double diag = val * epsRho * t_base_row(i) * t_base_col(i);
361 const double curl =
362 epsL > 0 ? val * pow(epsL, -1) * curl_row * curl_col : 0;
363 C(rr, cc) += diag + curl;
364 ++t_diff_base_col;
365 ++t_base_col;
366 }
367 ++t_diff_base_row;
368 ++t_base_row;
369 }
370 }
371
372 CHKERR MatSetValues(A, nb_row, &*row_indices.begin(), nb_col,
373 &*col_indices.begin(), &*C.data().begin(), ADD_VALUES);
374
376 }
377};
378
379/**
380 * \brief Calculate and assemble Z matrix
381 */
384
385 Mat A;
386
387 OpCellCurlB(Mat a, const string field_name)
390 A(a) {
391 sYmm = false;
392 }
393
394 MatrixDouble C;
395
396 MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type,
397 EntityType col_type,
398 DataForcesAndSourcesCore::EntData &row_data,
399 DataForcesAndSourcesCore::EntData &col_data) {
400
402
403 int nb_row = row_data.getIndices().size();
404 int nb_col = col_data.getIndices().size();
405
406 if (nb_row == 0)
408 if (nb_col == 0)
410
411 const VectorInt &row_indices = row_data.getIndices();
412 const VectorInt &col_indices = col_data.getIndices();
413
414 const int nb_gauss_pts = row_data.getN().size1();
415
416 auto t_base_row = row_data.getFTensor1N<3>();
417
418 C.resize(nb_row, nb_col, false);
419 C.clear();
420 for (int gg = 0; gg != nb_gauss_pts; gg++) {
421 // get integration weights
422 const double val = getGaussPts()(2, gg) * getArea();
423 for (int rr = 0; rr != nb_row; rr++) {
424 // This is scalar field, diff yield tensor1
425 auto t_base_col = col_data.getFTensor0N(gg, 0);
426 for (int cc = 0; cc != nb_col / 3; cc++) {
427 C(rr, 3 * cc + 0) -= val * t_base_row(0) * t_base_col;
428 C(rr, 3 * cc + 1) -= val * t_base_row(1) * t_base_col;
429 ++t_base_col;
430 }
431 ++t_base_row;
432 }
433 }
434
435 CHKERR MatSetValues(A, nb_row, &*row_indices.begin(), nb_col,
436 &*col_indices.begin(), &*C.data().begin(), ADD_VALUES);
437
439 }
440};
441
442/**
443 * \brief Post-process tractions
444 *
445 * \todo Should be done with Prisms, no need to have three kinds of elements,
446 * tets for solid, prisms for constrains and triangles to do post-processing. We
447 * can do post-pocessing with prisms.
448 *
449 */
452
454
459
460 /**
461 * Real work is done here, i.e. assemble tractions
462 */
463 MoFEMErrorCode doWork(int side, EntityType type,
464 DataForcesAndSourcesCore::EntData &data) {
465 //
466 //
468
469 if (data.getFieldData().empty())
471
472 const int nb_gauss_pts = data.getN().size1();
473 const int nb_dofs = data.getFieldData().size();
474
475 VectorDouble *vec;
476 MatrixDouble *mat;
477 MatrixDouble *grad;
478
479 if (rowFieldName == "RHO") {
483 }
484
485 if (type == MBVERTEX) {
486 mat->resize(nb_gauss_pts, 2, false);
487 mat->clear();
488 vec->resize(nb_gauss_pts, false);
489 vec->clear();
490 grad->resize(0, 0, false);
491 }
492
493 // calculate forces at integration points
494 for (unsigned int gg = 0; gg < nb_gauss_pts; gg++) {
495 for (int rr = 0; rr != nb_dofs; rr++) {
496 const double diff_base_x = data.getDiffN()(gg, 2 * rr + 0);
497 const double diff_base_y = data.getDiffN()(gg, 2 * rr + 1);
498 const double val = data.getFieldData()[rr];
499 (*mat)(gg, 0) += diff_base_x * val;
500 (*mat)(gg, 1) += diff_base_y * val;
501 const double base = data.getN()(gg, rr);
502 (*vec)[gg] += base * val;
503 }
504 }
505
507 }
508};
509
510/**
511 * \brief Post-process tractions
512 *
513 * \todo Should be done with Prisms, no need to have three kinds of elements,
514 * tets for solid, prisms for constrains and triangles to do post-processing. We
515 * can do post-pocessing with prisms.
516 *
517 */
520
522
527
528 /**
529 * Real work is done here, i.e. assemble tractions
530 */
531 MoFEMErrorCode doWork(int side, EntityType type,
532 DataForcesAndSourcesCore::EntData &data) {
533 //
534 //
536
537 if (data.getFieldData().empty())
539
540 const int nb_gauss_pts = data.getN().size1();
541 const int nb_dofs = data.getFieldData().size();
542
543 VectorDouble *vec;
544 MatrixDouble *mat;
545 MatrixDouble *grad;
546
547 if (rowFieldName == "RHO") {
551 }
552
553 if (type == MBEDGE && side == 0) {
554 mat->resize(nb_gauss_pts, 2, false);
555 mat->clear();
556 grad->resize(nb_gauss_pts, 4, false);
557 grad->clear();
558 vec->resize(0, false);
559 }
560
561 // calculate forces at integration points
562 auto t_base = data.getFTensor1N<3>();
563 auto t_diff_base_fun = data.getFTensor2DiffN<3, 2>();
564
565 for (unsigned int gg = 0; gg < nb_gauss_pts; gg++) {
566 auto t_data = data.getFTensor0FieldData();
567 for (int rr = 0; rr != nb_dofs; rr++) {
568 const double base_x = t_base(0);
569 const double base_y = t_base(1);
570 (*mat)(gg, 0) += base_x * t_data;
571 (*mat)(gg, 1) += base_y * t_data;
572 for (int i = 0; i != 2; i++) {
573 for (int j = 0; j != 2; j++) {
574 (*grad)(gg, 2 * i + j) += t_diff_base_fun(i, j) * t_data;
575 }
576 }
577 ++t_data;
578 ++t_base;
579 ++t_diff_base_fun;
580 }
581 }
582
584 }
585};
586
587/**
588 * \brief Shave results on mesh tags for post-processing
589 */
592
594 moab::Interface &postProcMesh;
595 std::vector<EntityHandle> &mapGaussPts;
597
598 /**
599 * Constructor
600 */
601 PostProcTraction(MoFEM::Interface &m_field, moab::Interface &post_proc_mesh,
602 std::vector<EntityHandle> &map_gauss_pts,
603 CommonData &common_data)
606 mField(m_field), postProcMesh(post_proc_mesh),
607 mapGaussPts(map_gauss_pts), commonData(common_data) {}
608
609 /**
610 * \brief Here real work is done
611 */
612 MoFEMErrorCode doWork(int side, EntityType type,
613 DataForcesAndSourcesCore::EntData &data) {
615
616 if (type != MBVERTEX)
618
619 double def_val[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
620 Tag th_force, th_force_potential, th_grad_force;
621 CHKERR postProcMesh.tag_get_handle("FORCE", 3, MB_TYPE_DOUBLE, th_force,
622 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
623
625 CHKERR postProcMesh.tag_get_handle("FORCE_POTENTIAL", 1, MB_TYPE_DOUBLE,
626 th_force_potential,
627 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
628 }
629 if (commonData.gradForceAtGaussPtrs.size1() > 0) {
630 CHKERR postProcMesh.tag_get_handle("FORCE_GRADIENT", 9, MB_TYPE_DOUBLE,
631 th_grad_force,
632 MB_TAG_CREAT | MB_TAG_SPARSE, def_val);
633 }
634
635 int nb_gauss_pts = data.getN().size1();
636 if (mapGaussPts.size() != (unsigned int)nb_gauss_pts) {
637 SETERRQ(PETSC_COMM_SELF, MOFEM_DATA_INCONSISTENCY, "data inconsistency");
638 }
639
640 for (int gg = 0; gg < nb_gauss_pts; gg++) {
641 const double force[] = {commonData.forceAtGaussPts(gg, 0),
642 commonData.forceAtGaussPts(gg, 1), 0};
643 CHKERR postProcMesh.tag_set_data(th_force, &mapGaussPts[gg], 1, force);
645 CHKERR postProcMesh.tag_set_data(
646 th_force_potential, &mapGaussPts[gg], 1,
648 }
649 if (commonData.gradForceAtGaussPtrs.size1() > 0) {
650 const double grad_force[] = {commonData.gradForceAtGaussPtrs(gg, 0),
652 0,
655 0,
656 0,
657 0,
658 0};
659 CHKERR postProcMesh.tag_set_data(th_grad_force, &mapGaussPts[gg], 1,
660 grad_force);
661
662 }
663 }
664
666 }
667};
668
669} // namespace CellEngineering
670
671#endif // __CELL_FORCES_HPP__
ForcesAndSourcesCore::UserDataOperator UserDataOperator
std::string type
constexpr double a
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int order
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
FTensor::Index< 'j', 3 > j
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
constexpr auto field_name
MatrixDouble gradForceAtGaussPtrs
boost::shared_ptr< VectorDouble > dispY
VectorDouble forcePotentialAtGaussPoints
boost::shared_ptr< VectorDouble > dispX
FaceElement(MoFEM::Interface &m_field)
int getRuleThroughThickness(int order)
int getRuleTrianglesOnly(int order)
FatPrism(MoFEM::Interface &m_field)
Calculate and assemble Z matrix.
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, DataForcesAndSourcesCore::EntData &row_data, DataForcesAndSourcesCore::EntData &col_data)
OpCellCurlB(Mat a, const string field_name)
Calculate and assemble Z matrix.
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, DataForcesAndSourcesCore::EntData &row_data, DataForcesAndSourcesCore::EntData &col_data)
OpCellCurlD(Mat a, const double eps_rho, const double eps_l)
Calculate and assemble B matrix.
OpCellPotentialB(Mat a, const string field_name)
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, DataForcesAndSourcesCore::EntData &row_data, DataForcesAndSourcesCore::EntData &col_data)
Calculate and assemble D matrix.
OpCellPotentialD(Mat a, const double rho)
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, DataForcesAndSourcesCore::EntData &row_data, DataForcesAndSourcesCore::EntData &col_data)
Calculate and assemble S matrix.
MoFEMErrorCode doWork(int row_side, int col_side, EntityType row_type, EntityType col_type, DataForcesAndSourcesCore::EntData &row_data, DataForcesAndSourcesCore::EntData &col_data)
OpCellS(Mat a, const double eps_u)
Calculate and assemble g vector.
MoFEMErrorCode doWork(int side, EntityType type, DataForcesAndSourcesCore::EntData &data)
OpCell_g(Vec f, const double eps_u, CommonData &common_data)
OpGetDispX(CommonData &common_data)
OpGetDispY(CommonData &common_data)
Post-process tractions.
OpVirtualCurlRho(std::string field_name, CommonData &common_data)
MoFEMErrorCode doWork(int side, EntityType type, DataForcesAndSourcesCore::EntData &data)
OpVirtualPotentialRho(std::string field_name, CommonData &common_data)
MoFEMErrorCode doWork(int side, EntityType type, DataForcesAndSourcesCore::EntData &data)
Shave results on mesh tags for post-processing.
PostProcTraction(MoFEM::Interface &m_field, moab::Interface &post_proc_mesh, std::vector< EntityHandle > &map_gauss_pts, CommonData &common_data)
MoFEMErrorCode doWork(int side, EntityType type, DataForcesAndSourcesCore::EntData &data)
Here real work is done.
std::vector< EntityHandle > & mapGaussPts
bool sYmm
If true assume that matrix is symmetric structure.
Deprecated interface functions.
@ OPROW
operator doWork function is executed on FE rows
@ OPROWCOL
operator doWork is executed on FE rows &columns
MatrixDouble & getGaussPts()
matrix of integration (Gauss) points for Volume Element
Specialization for double precision scalar field values calculation.
double rho
Definition plastic.cpp:145