25 : m_solverId(solver->m_solverId), m_noInternalCells(solver->grid().noInternalCells()) {
31 m_noSegments = m_solver->
m_geometry->geometryContext().getNoSegments();
41 m_kFactor = Context::getSolverProperty<MFloat>(
"kFactor", m_solverId, AT_, &m_kFactor);
51 mAlloc(m_subCellLayerDepth, m_noSegments,
"m_subCellLayerDepth", 0, AT_);
52 for(
MInt i = 0; i < m_noSegments; i++) {
53 m_subCellLayerDepth[i] = Context::getSolverProperty<MInt>(
"subCellLayerDepth", m_solverId, AT_, i);
58 mAlloc(m_noBndryCellsPerSegment, m_noSegments,
"m_noBndryCellsPerSegment", 0, AT_);
72 m_multiBC = Context::getSolverProperty<MBool>(
"multiBC", m_solverId, AT_, &m_multiBC);
73 if(!m_multiBC)
mTerm(1, AT_,
"m_multiBC is set to false, bc functions are not adapted to this input.");
87 m_bndryNormalMethod =
"read";
88 m_bndryNormalMethod = Context::getSolverProperty<MString>(
"bndryNormalMethod", m_solverId, AT_, &m_bndryNormalMethod);
89 if(m_bndryNormalMethod !=
"read")
90 mTerm(1, AT_,
"m_bndryNormalMethod is not \"read\", bc functions are not adapted to this input.");
93 createBoundaryCells();
100 findCellsRequireSubCellIntegration();
102 calculateCutPoints();
104 for(
MInt i = 0; i < (
MInt)m_bndryCndSegIds.size(); i++) {
105 if(m_solver->m_testRun) {
106 writeOutSTLBoundaries(i,
"preSimulation");
108 calcAvgFaceNormal(i);
136 for(
MInt i = 0; i < (
MInt)(m_bndryCndSegIds.size()); i++) {
137 MInt seg_id = m_bndryCndSegIds[i];
138 MInt bc_id = m_bndryCndIds[i];
140 ostringstream ostrSegId;
142 MString strSegId = ostrSegId.str();
151 name =
"segFixationDirs_";
152 name.append(strSegId);
154 for(
MInt d = 0; d < nDim; d++) {
155 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
157 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
158 for(
MInt d = 0; d < nDim; d++) {
159 m_bndryCells[j].m_directionOfAction[d] = dir[d];
165 name =
"segFixationDirs_";
166 name.append(strSegId);
168 for(
MInt d = 0; d < nDim; d++) {
169 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
171 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
172 for(
MInt d = 0; d < nDim; d++) {
173 m_bndryCells[j].m_directionOfAction[d] = dir[d];
179 name =
"segFixationDirs_";
180 name.append(strSegId);
182 for(
MInt d = 0; d < nDim; d++) {
183 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
185 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
186 for(
MInt d = 0; d < nDim; d++) {
187 m_bndryCells[j].m_directionOfAction[d] = dir[d];
196 name =
"segLoadDirs_";
197 name.append(strSegId);
199 for(
MInt d = 0; d < nDim; d++) {
200 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
202 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
203 for(
MInt d = 0; d < nDim; d++) {
204 m_bndryCells[j].m_directionOfAction[d] = dir[d];
207 name =
"segLoadValue_";
208 name.append(strSegId);
210 for(
MInt d = 0; d < nDim; d++) {
211 load[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
213 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
214 for(
MInt d = 0; d < nDim; d++) {
215 m_bndryCells[j].m_load[d] = load[d];
221 name =
"segLoadDirs_";
222 name.append(strSegId);
224 for(
MInt d = 0; d < nDim; d++) {
225 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
227 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
228 for(
MInt d = 0; d < nDim; d++) {
229 m_bndryCells[j].m_directionOfAction[d] = dir[d];
232 name =
"segLoadValue_";
233 name.append(strSegId);
235 for(
MInt d = 0; d < nDim; d++) {
236 load[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
238 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
239 for(
MInt d = 0; d < nDim; d++) {
240 m_bndryCells[j].m_load[d] = load[d];
246 name =
"segLoadDirs_";
247 name.append(strSegId);
249 for(
MInt d = 0; d < nDim; d++) {
250 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
252 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
253 for(
MInt d = 0; d < nDim; d++) {
254 m_bndryCells[j].m_directionOfAction[d] = dir[d];
257 name =
"segLoadValue_";
258 name.append(strSegId);
260 for(
MInt d = 0; d < nDim; d++) {
261 load[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
263 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
264 for(
MInt d = 0; d < nDim; d++) {
265 m_bndryCells[j].m_load[d] = load[d];
271 name =
"segLoadDirs_";
272 name.append(strSegId);
274 for(
MInt d = 0; d < nDim; d++) {
275 dir[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
277 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
278 for(
MInt d = 0; d < nDim; d++) {
279 m_bndryCells[j].m_directionOfAction[d] = dir[d];
282 name =
"segLoadValue_";
283 name.append(strSegId);
285 for(
MInt d = 0; d < nDim; d++) {
286 load[d] = Context::getSolverProperty<MFloat>(name, m_solverId, AT_, d);
288 for(
MInt j = m_bndryCndOffsets[i]; j < m_bndryCndOffsets[i + 1]; j++) {
289 for(
MInt d = 0; d < nDim; d++) {
290 m_bndryCells[j].m_load[d] = load[d];
296 mTerm(1, AT_,
"Unknown boundary condition id!");
325 MInt noMultiCells = 0;
327 MInt bndryCellsIt = 0, bndryCellsIt2 = 0;
329 m_log <<
" + Creating boundary cells..." << endl;
330 m_log <<
" - Multiple BC usage: " << m_multiBC << endl;
332 for(
MInt i = 0; i < m_solver->m_cells.size(); i++) {
333 if(!m_solver->c_isLeafCell(i))
continue;
335 std::vector<MInt> nodeList;
336 getStlNodeList(i, nodeList);
338 const MInt noNodes = (
MInt)nodeList.size();
340 m_solver->a_isBndryCell(i) =
true;
343 m_bndryCells.emplace_back();
345 bndryCellsIt = m_bndryCells.size() - 1;
346 m_bndryCells[bndryCellsIt].m_cellId = i;
350 for(
MInt j = 0; j < noNodes; j++) {
351 MBool already_in =
false;
352 MInt segId = m_solver->m_geometry->elements[nodeList[j]].m_segmentId;
353 MInt bndId = m_solver->m_geometry->elements[nodeList[j]].m_bndCndId;
354 for(
MInt k = 0; k < (
MInt)(m_bndryCells[bndryCellsIt].m_segmentId.size()); k++) {
355 if(m_bndryCells[bndryCellsIt].m_segmentId[k] == segId) {
361 m_bndryCells[bndryCellsIt].m_segmentId.push_back(segId);
362 m_bndryCells[bndryCellsIt].m_bndryCndId.push_back(bndId);
366 if(m_bndryCells[bndryCellsIt].m_segmentId.size() > 1) {
373 bndryCellsIt2 = bndryCellsIt;
374 for(
MInt j = 1; j < (
MInt)(m_bndryCells[bndryCellsIt].m_segmentId.size()); j++) {
376 MInt bndId = m_bndryCells[bndryCellsIt].m_bndryCndId[j];
377 MInt segId = m_bndryCells[bndryCellsIt].m_segmentId[j];
380 m_bndryCells.emplace_back();
381 m_bndryCells[bndryCellsIt2].m_cellId = i;
383 m_bndryCells[bndryCellsIt2].m_segmentId.push_back(segId);
384 m_bndryCells[bndryCellsIt2].m_bndryCndId.push_back(bndId);
390 m_log <<
" - noBndCells: " << m_bndryCells.size() << endl;
391 m_log <<
" - noMultiCells: " << noMultiCells << endl << endl;
409 const MInt tmpCellSize = m_bndryCells.size();
411 m_log <<
" + Sorting boundary cells..." << endl;
412 m_log <<
" - no. boundary cells: " << tmpCellSize << endl;
415 stable_sort(m_bndryCells.begin(), m_bndryCells.end(),
416 [](
auto a,
auto b) { return a.m_segmentId[0] < b.m_segmentId[0]; });
418 MInt tmpSegmentId = -1;
419 MInt tmpBndryCndId = -1;
422 m_mapBndryCndSegId2Index.resize(m_noSegments, -1);
424 for(
MInt i = 0; i < tmpCellSize; i++) {
425 if(tmpSegmentId != m_bndryCells[i].m_segmentId[0]) {
428 tmpSegmentId = m_bndryCells[i].m_segmentId[0];
429 tmpBndryCndId = m_bndryCells[i].m_bndryCndId[0];
431 m_bndryCndIds.push_back(tmpBndryCndId);
432 m_bndryCndOffsets.push_back(counter);
433 m_bndryCndSegIds.push_back(tmpSegmentId);
434 m_mapBndryCndSegId2Index[tmpSegmentId] = m_bndryCndSegIds.size() - 1;
436 m_noBndryCellsPerSegment[tmpSegmentId]++;
437 m_solver->a_isBndryCell(m_bndryCells[counter].m_cellId) =
true;
438 m_solver->a_bndId(m_bndryCells[counter].m_cellId) = counter;
443 m_bndryCndOffsets.push_back(counter);
445 for(
MInt i = 0; i < (
MInt)(m_bndryCndSegIds.size()); i++) {
446 MInt seg_id = m_bndryCndSegIds[i];
448 m_log <<
" - BC " << m_bndryCndIds[i] << endl;
449 m_log <<
" * index: " << i << endl;
450 m_log <<
" * segment id: " << seg_id << endl;
451 m_log <<
" * no cells: " << m_noBndryCellsPerSegment[seg_id] << endl;
452 m_log <<
" * offsets: " << m_bndryCndOffsets[i] <<
" - " << m_bndryCndOffsets[i + 1] - 1 << endl;
467 m_log <<
" + Setting the boundary condition handler..." << endl << endl;
470 bndryCndHandlerSystemMatrix =
new BndryCndHandler[m_bndryCndIds.size()];
471 bndryCndHandlerForce =
new BndryCndHandler[m_bndryCndIds.size()];
474 for(
MInt i = 0; i < (
MInt)(m_bndryCndIds.size()); i++) {
475 switch(m_bndryCndIds[i]) {
536 stringstream errorMessage;
537 errorMessage <<
" FcBndryCnd::setBndryCndHandler : Unknown boundary condition " << m_bndryCndIds[i]
538 <<
" exiting program.";
539 mTerm(1, AT_, errorMessage.str());
557 MInt segId = m_bndryCndSegIds[index];
558 cout <<
"bc8010(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
559 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
562 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
563 const MInt cellId = m_bndryCells[i].m_cellId;
564 const MFloat halfLength = m_solver->c_cellLengthAtCell(cellId) * F1B2;
566 const MInt noNodes = m_solver->a_noNodes(cellId);
568 MFloatScratchSpace penalty(nDim * m_solver->a_noNodes(cellId), nDim * m_solver->a_noNodes(cellId), AT_,
"penalty");
570 for(
MInt node = 0; node < noNodes; node++) {
572 m_solver->getCoordinatesOfNode(node, cellId, nodalCoord);
574 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
575 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
577 for(
MInt d = F0; d < nDim; d++) {
579 for(
MInt dim = 0; dim < nDim; dim++) {
580 const MFloat normal = m_bndryCells[i].m_faceNormals[t][dim];
581 const MFloat diff = (nodalCoord[dim] - m_bndryCells[i].m_cutFaces[t][d * nDim + dim]);
582 dist += normal * normal * diff * diff;
584 const MFloat eps = halfLength * 1e-3;
585 if(
dist < (eps * eps)) {
586 for(
MInt dim = 0; dim < nDim; dim++) {
587 const MInt pos = node * nDim + dim;
588 if(m_bndryCells[i].m_directionOfAction[dim] > F0) {
589 penalty(pos, pos) = m_kFactor;
596 m_solver->computeAssembledBndryMatrix(penalty, cellId);
613 MInt segId = m_bndryCndSegIds[index];
614 cout <<
"bc8011(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
615 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
618 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
619 const MInt cellId = m_bndryCells[i].m_cellId;
620 const MFloat halfLength = m_solver->c_cellLengthAtCell(cellId) * F1B2;
621 std::vector<MInt> nodeList;
622 getStlNodeList(cellId, nodeList);
624 MInt noNodes = m_solver->a_noNodes(cellId);
626 nodeOnSurface.
fill(0);
630 for(
MInt node = 0; node < noNodes; node++) {
632 m_solver->getCoordinatesOfNode(node, cellId, nodalCoord);
637 for(
MInt dim = 0; dim < nDim; dim++) {
638 d[dim] = nodalCoord[dim] - m_bndryCells[i].m_avgFaceNormal[dim] * halfLength;
639 e[dim] = nodalCoord[dim] + m_bndryCells[i].m_avgFaceNormal[dim] * halfLength;
640 radius += (d[dim] - nodalCoord[dim]) * (d[dim] - nodalCoord[dim]);
642 radius = sqrt(radius);
644 MBool hasCut =
false;
645 for(
MInt n = 0; n < (signed)nodeList.size(); n++) {
646 if(m_solver->m_geometry->elements[nodeList[n]].m_segmentId != segId)
continue;
649 MFloat**
const v = m_solver->m_geometry->elements[nodeList[n]].m_vertices;
650 hasCut = m_solver->m_geometry->getLineTriangleIntersectionSimpleDistance(d, e, v[0], v[1], v[2], &distance);
651 if(
approx(distance, radius, eps)) {
657 nodeOnSurface(node) = 1;
664 MFloatScratchSpace penalty(nDim * m_solver->a_noNodes(cellId), nDim * m_solver->a_noNodes(cellId), AT_,
"penalty");
667 for(
MInt j = 0; j < (m_solver->a_pRfnmnt(cellId) + 2); j++) {
668 for(
MInt k = 0; k < (m_solver->a_pRfnmnt(cellId) + 2); k++) {
669 MInt loop = (nDim == 3) ? (m_solver->a_pRfnmnt(cellId) + 2) : 1;
670 for(
MInt l = 0; l < loop; l++) {
671 MInt nodePos[nDim] = {0};
674 if(nDim == 3) nodePos[2] = l;
676 MBool wrongSide =
false;
677 for(
MInt d = 0; d < nDim; d++) {
678 z[d] = m_solver->m_gaussPoints[m_solver->a_pRfnmnt(cellId)][nodePos[d]];
679 if(!
approx(m_bndryCells[i].m_avgFaceNormal[d], F0, 1e-6)) {
685 if(wrongSide)
continue;
690 m_solver->getDisplacementInterpolationMatrix(cellId, z, L_coef);
693 for(
MInt node = 0; node < m_solver->a_noNodes(cellId); node++) {
694 if(nodeOnSurface(node))
continue;
695 for(
MInt d = 0; d < nDim; d++) {
696 L_coef(d, node * nDim + d) = F0;
701 for(
MInt n1 = 0; n1 < m_solver->a_noNodes(cellId); n1++) {
702 for(
MInt n2 = 0; n2 < m_solver->a_noNodes(cellId); n2++) {
703 for(
MInt d = 0; d < nDim; d++) {
704 MFloat k_factor = (fabs(m_bndryCells[i].m_directionOfAction[d]) > m_solver->m_eps) ? m_kFactor : F0;
707 for(
MInt dim = 0; dim < nDim; dim++) {
708 if(fabs(m_bndryCells[i].m_avgFaceNormal[dim]) > F0)
continue;
709 L1 *= L_coef(dim, n1);
710 L2 *= L_coef(dim, n2);
712 penalty(n1 * nDim + d, n2 * nDim + d) += (L1 * k_factor * L2);
719 m_solver->computeAssembledBndryMatrix(penalty, cellId);
736 MInt segId = m_bndryCndSegIds[index];
737 const MInt noTriEdges = (nDim == 3) ? 3 : 1;
738 cout <<
"bc8012(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
739 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
742 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
743 const MInt cellId = m_bndryCells[i].m_cellId;
745 const MInt dof = nDim * m_solver->a_noNodes(cellId);
746 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
747 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
748 std::vector<MFloat> transformedTriangle;
749 MFloat normal[nDim] = {F0};
750 for(
MInt d = 0; d < nDim; d++) {
753 for(
MInt d1 = 0; d1 < nDim; d1++) {
754 x[d1] = m_bndryCells[i].m_cutFaces[t][d * nDim + d1];
756 m_solver->transformToLocal(cellId, x, z);
757 for(
MInt d1 = 0; d1 < nDim; d1++) {
758 transformedTriangle.push_back(z[d1]);
760 normal[d] = m_bndryCells[i].m_faceNormals[t][d];
762 MFloat determinant = solveIntegrationOnTriangle(transformedTriangle, normal);
766 for(
MInt e = 0; e < noTriEdges; e++) {
770 for(
MInt d = 0; d < nDim; d++) {
772 MInt e2 = ((e + 1) < nDim) ? (e + 1) : 0;
773 z[d] = (transformedTriangle[e1 * nDim + d] + transformedTriangle[e2 * nDim + d]) * F1B2;
775 m_solver->getDisplacementInterpolationMatrix(cellId, z, L_coef);
776 if(m_solver->m_testRun && m_solver->m_polyDeg < 1) {
777 m_solver->getDisplacementInterpolationMatrixDebug(cellId, z, L_coef);
780 for(
MInt n1 = 0; n1 < dof; n1++) {
781 for(
MInt n2 = 0; n2 < dof; n2++) {
783 for(
MInt d = 0; d < nDim; d++) {
784 MFloat k_factor = (fabs(m_bndryCells[i].m_directionOfAction[d]) > m_solver->m_eps) ? m_kFactor : F0;
785 product += L_coef(d, n1) * k_factor * L_coef(d, n2);
787 penalty(n1, n2) += product * determinant * weight;
791 m_solver->computeAssembledBndryMatrix(penalty, cellId);
804 MInt segId = m_bndryCndSegIds[index];
805 cout <<
"bc8020(" << index <<
", " << segId <<
"), offset [" << m_bndryCndOffsets[index] <<
", "
806 << m_bndryCndOffsets[index + 1] <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]"
810 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
811 cellId = m_bndryCells[i].m_cellId;
812 cout <<
"bndryId = " << i <<
", cellId = " << cellId <<
", primeBndryId = " << m_solver->a_bndId(cellId) << endl;
830 MInt segId = m_bndryCndSegIds[index];
831 cout <<
"bc8030(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
832 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
834 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
835 const MInt cellId = m_bndryCells[i].m_cellId;
836 const MFloat halfLength = m_solver->c_cellLengthAtCell(cellId) * F1B2;
837 std::vector<MInt> nodeList;
838 getStlNodeList(cellId, nodeList);
840 MInt noNodes = m_solver->a_noNodes(cellId);
841 for(
MInt node = 0; node < noNodes; node++) {
843 m_solver->getCoordinatesOfNode(node, cellId, nodalCoord);
848 for(
MInt dim = 0; dim < nDim; dim++) {
849 d[dim] = nodalCoord[dim] - m_bndryCells[i].m_avgFaceNormal[dim] * halfLength;
850 e[dim] = nodalCoord[dim] + m_bndryCells[i].m_avgFaceNormal[dim] * halfLength;
851 radius += (d[dim] - nodalCoord[dim]) * (d[dim] - nodalCoord[dim]);
853 radius = sqrt(radius);
855 for(
MInt n = 0; n < (signed)nodeList.size(); n++) {
856 if(m_solver->m_geometry->elements[nodeList[n]].m_segmentId != segId)
continue;
859 MFloat**
const v = m_solver->m_geometry->elements[nodeList[n]].m_vertices;
861 m_solver->m_geometry->getLineTriangleIntersectionSimpleDistance(d, e, v[0], v[1], v[2], &distance);
862 std::ignore = hasCut;
863 MInt nodeId = m_solver->a_nodeIdsLocal(cellId, node);
864 if(
approx(distance, radius, 1e-6)) {
865 for(
MInt dim = 0; dim < nDim; dim++) {
866 m_solver->m_externalLoadVector[nodeId * nDim + dim] =
867 m_bndryCells[i].m_directionOfAction[dim] * m_bndryCells[i].m_load[dim];
889 MInt segId = m_bndryCndSegIds[index];
890 const MInt noTriEdges = (nDim == 3) ? 3 : 1;
891 cout <<
"bc8031(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
892 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
896 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
897 const MInt cellId = m_bndryCells[i].m_cellId;
898 const MFloat cellLength = m_solver->c_cellLengthAtCell(cellId);
901 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
902 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
903 std::vector<MFloat> transformedTriangle;
904 MFloat normal[nDim] = {F0};
905 for(
MInt d = 0; d < nDim; d++) {
908 for(
MInt d1 = 0; d1 < nDim; d1++) {
909 x[d1] = m_bndryCells[i].m_cutFaces[t][d * nDim + d1];
911 m_solver->transformToLocal(cellId, x, z);
912 for(
MInt d1 = 0; d1 < nDim; d1++) {
913 transformedTriangle.push_back(z[d1]);
914 normal[d1] = m_bndryCells[i].m_faceNormals[t][d];
917 MFloat determinant = solveIntegrationOnTriangle(transformedTriangle, normal);
919 for(
MInt e = 0; e < noTriEdges; e++) {
923 for(
MInt d = 0; d < nDim; d++) {
925 MInt e2 = ((e + 1) < nDim) ? (e + 1) : 0;
926 z[d] = (transformedTriangle[e1 * nDim + d] + transformedTriangle[e2 * nDim + d]) * F1B2;
928 m_solver->getDisplacementInterpolationMatrix(cellId, z, L_coef);
929 if(m_solver->m_testRun && m_solver->m_polyDeg < 1) {
930 m_solver->getDisplacementInterpolationMatrixDebug(cellId, z, L_coef);
933 for(
MInt node = 0; node < m_solver->a_noNodes(cellId); node++) {
934 for(
MInt dim = 0; dim < nDim; dim++) {
935 MInt nodeId = m_solver->a_nodeIdsLocal(cellId, node);
936 MFloat sigma[nDim] = {F0};
937 for(
MInt d = 0; d < nDim; d++) {
938 sigma[d] = m_bndryCells[i].m_load[d];
941 for(
MInt d = 0; d < nDim; d++) {
942 load += L_coef(d, node * nDim + dim) * sigma[d] * determinant * weight;
944 m_solver->m_externalLoadVector[nodeId * nDim + dim] += (F1B4 * cellLength * cellLength) * load;
967 MInt segId = m_bndryCndSegIds[index];
968 const MInt noTriEdges = (nDim == 3) ? 3 : 1;
969 cout <<
"bc8032(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
970 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
974 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
975 const MInt cellId = m_bndryCells[i].m_cellId;
976 const MFloat cellLength = m_solver->c_cellLengthAtCell(cellId);
979 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
980 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
981 std::vector<MFloat> transformedTriangle;
982 MFloat normal[nDim] = {F0};
983 for(
MInt d = 0; d < nDim; d++) {
986 for(
MInt d1 = 0; d1 < nDim; d1++) {
987 x[d1] = m_bndryCells[i].m_cutFaces[t][d * nDim + d1];
989 m_solver->transformToLocal(cellId, x, z);
990 for(
MInt d1 = 0; d1 < nDim; d1++) {
991 transformedTriangle.push_back(z[d1]);
992 normal[d1] = m_bndryCells[i].m_faceNormals[t][d];
995 MFloat determinant = solveIntegrationOnTriangle(transformedTriangle, normal);
997 for(
MInt e = 0; e < noTriEdges; e++) {
1001 MFloat coord[nDim] = {F0};
1002 for(
MInt d = 0; d < nDim; d++) {
1004 MInt e2 = ((e + 1) < nDim) ? (e + 1) : 0;
1005 z[d] = (transformedTriangle[e1 * nDim + d] + transformedTriangle[e2 * nDim + d]) * F1B2;
1007 (m_bndryCells[i].m_cutFaces[t][e1 * nDim + d] + m_bndryCells[i].m_cutFaces[t][e2 * nDim + d]) * F1B2;
1009 m_solver->getDisplacementInterpolationMatrix(cellId, z, L_coef);
1010 if(m_solver->m_testRun && m_solver->m_polyDeg < 1) {
1011 m_solver->getDisplacementInterpolationMatrixDebug(cellId, z, L_coef);
1017 MFloat cosTheta = x / sqrt(r_squared);
1018 MFloat sinTheta =
y / sqrt(r_squared);
1019 MFloat cos2Theta = F2 * cosTheta * cosTheta - 1;
1020 MFloat sin2Theta = F2 * cosTheta * sinTheta;
1022 m_bndryCells[i].m_load[0] * F1B2 * (F1 - F1 / r_squared)
1023 + m_bndryCells[i].m_load[0] * F1B2 * (F1 + F3 / (r_squared * r_squared) - F4 / r_squared) * cos2Theta;
1024 MFloat sigmaTT = m_bndryCells[i].m_load[1] * F1B2 * (F1 + F1 / r_squared)
1025 - m_bndryCells[i].m_load[1] * F1B2 * (F1 + F3 / (r_squared * r_squared)) * cos2Theta;
1027 -m_bndryCells[i].m_load[0] * F1B2 * (F1 + F2 / r_squared - F3 / (r_squared * r_squared)) * sin2Theta;
1029 sigmaRR * cosTheta * cosTheta + sigmaTT * sinTheta * sinTheta - F2 * sigmaRT * cosTheta * sinTheta;
1031 sigmaTT * cosTheta * cosTheta + sigmaRR * sinTheta * sinTheta + F2 * sigmaRT * cosTheta * sinTheta;
1033 (sigmaRR - sigmaTT) * cosTheta * sinTheta + sigmaRT * (cosTheta * cosTheta - sinTheta * sinTheta);
1035 for(
MInt node = 0; node < m_solver->a_noNodes(cellId); node++) {
1036 for(
MInt dim = 0; dim < nDim; dim++) {
1037 MInt nodeId = m_solver->a_nodeIdsLocal(cellId, node);
1038 MFloat sigma[nDim] = {F0};
1039 if(
approx(m_bndryCells[i].m_avgFaceNormal[0], F0, 1e-6)) {
1047 for(
MInt d = 0; d < nDim; d++) {
1048 load += L_coef(d, node * nDim + dim) * sigma[d] * determinant * weight;
1050 m_solver->m_externalLoadVector[nodeId * nDim + dim] += (F1B4 * cellLength * cellLength) * load;
1068 MInt segId = m_bndryCndSegIds[index];
1069 const MInt noTriEdges = (nDim == 3) ? 3 : 1;
1070 cout <<
"bc8035(" << index <<
"), offset [" << m_bndryCndOffsets[index] <<
", " << m_bndryCndOffsets[index + 1]
1071 <<
"; diff = " << m_bndryCndOffsets[index + 1] - m_bndryCndOffsets[index] <<
"]" << endl;
1075 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
1076 const MInt cellId = m_bndryCells[i].m_cellId;
1077 const MFloat cellLength = m_solver->c_cellLengthAtCell(cellId);
1080 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
1081 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
1082 std::vector<MFloat> transformedTriangle;
1083 MFloat normal[nDim] = {F0};
1084 for(
MInt d = 0; d < nDim; d++) {
1087 for(
MInt d1 = 0; d1 < nDim; d1++) {
1088 x[d1] = m_bndryCells[i].m_cutFaces[t][d * nDim + d1];
1090 m_solver->transformToLocal(cellId, x, z);
1091 for(
MInt d1 = 0; d1 < nDim; d1++) {
1092 transformedTriangle.push_back(z[d1]);
1094 normal[d] = m_bndryCells[i].m_faceNormals[t][d];
1096 MFloat determinant = solveIntegrationOnTriangle(transformedTriangle, normal);
1098 for(
MInt e = 0; e < noTriEdges; e++) {
1102 for(
MInt d = 0; d < nDim; d++) {
1104 MInt e2 = ((e + 1) < nDim) ? (e + 1) : 0;
1105 z[d] = (transformedTriangle[e1 * nDim + d] + transformedTriangle[e2 * nDim + d]) * F1B2;
1107 m_solver->getDisplacementInterpolationMatrix(cellId, z, L_coef);
1108 if(m_solver->m_testRun && m_solver->m_polyDeg < 1) {
1109 m_solver->getDisplacementInterpolationMatrixDebug(cellId, z, L_coef);
1112 for(
MInt node = 0; node < m_solver->a_noNodes(cellId); node++) {
1113 for(
MInt dim = 0; dim < nDim; dim++) {
1114 MInt nodeId = m_solver->a_nodeIdsLocal(cellId, node);
1115 MFloat sigma[nDim] = {F0};
1116 for(
MInt d = 0; d < nDim; d++) {
1117 sigma[d] = normal[d] * 1.0;
1120 for(
MInt d = 0; d < nDim; d++) {
1121 load += L_coef(d, node * nDim + dim) * sigma[d] * determinant * weight;
1123 m_solver->m_externalLoadVector[nodeId * nDim + dim] += (F1B4 * cellLength * cellLength) * load;
1139 std::ignore = index;
1150 for(
MInt i = 0; i < (
MInt)(m_bndryCndIds.size()); i++) {
1151 (this->*bndryCndHandlerSystemMatrix[i])(i);
1163 for(
MInt i = 0; i < (
MInt)(m_bndryCndIds.size()); i++) {
1164 (this->*bndryCndHandlerForce[i])(i);
1178 for(
MInt index = 0; index < (
MInt)(m_bndryCndSegIds.size()); index++) {
1179 const MInt bc_id = m_bndryCndIds[index];
1180 const MInt segId = m_bndryCndSegIds[index];
1182 if(bc_id == 0)
continue;
1183 if(bc_id > 8020)
continue;
1185 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
1186 const MInt cellId = m_bndryCells[i].m_cellId;
1187 const MFloat halfLength = m_solver->c_cellLengthAtCell(cellId) * F1B2;
1189 const MInt noNodes = m_solver->a_noNodes(cellId);
1191 for(
MInt node = 0; node < noNodes; node++) {
1192 std::array<MFloat, nDim> nodalCoord{};
1193 m_solver->getCoordinatesOfNode(node, cellId, nodalCoord.data());
1195 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
1196 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
1198 for(
MInt d = F0; d < nDim; d++) {
1200 for(
MInt dim = 0; dim < nDim; dim++) {
1201 const MFloat normal = m_bndryCells[i].m_faceNormals[t][dim];
1202 const MFloat diff = (nodalCoord[dim] - m_bndryCells[i].m_cutFaces[t][d * nDim + dim]);
1203 dist += normal * normal * diff * diff;
1205 const MFloat eps = halfLength * 1e-3;
1206 if(
dist < (eps * eps)) {
1207 for(
MInt dim = 0; dim < nDim; dim++) {
1208 const MInt pos = m_solver->a_nodeIdsLocal(cellId, node) * nDim + dim;
1209 if(m_bndryCells[i].m_directionOfAction[dim] > F0) {
1210 m_solver->m_reactionForceVector[pos] = m_solver->m_internalLoadVector[pos];
1231 if(subCellLvl > m_solver->a_maxSubCellLvl(pCellId))
return;
1233 std::vector<MInt> nodeList;
1236 const MFloat subCellHalfLength = m_solver->c_cellLengthAtCell(pCellId) *
FFPOW2(subCellLvl + 1);
1238 MFloat target[2 * nDim] = {F0};
1239 MFloat subCellCoord[nDim] = {F0};
1240 for(
MInt d = 0; d < nDim; d++) {
1241 MFloat dir = Fd::vertexPosition(subCellPos, d);
1242 subCellCoord[d] = subCellParentCoord[d] + dir * subCellHalfLength;
1243 target[d] = subCellCoord[d] - subCellHalfLength;
1244 target[d + nDim] = subCellCoord[d] + subCellHalfLength;
1248 const MInt childLevel = subCellLvl + 1;
1251 m_solver->m_geometry->getIntersectionElements(target, nodeList, subCellHalfLength, subCellCoord);
1255 if(nodeList.size() > 0) {
1256 if(childLevel <= m_solver->a_maxSubCellLvl(pCellId)) {
1257 for(
MInt child = 0; child <
IPOW2(nDim); child++) {
1258 subCellIntegration(childLevel, subCellCoord, child, pCellId, Ke_final);
1262 MFloatScratchSpace Ke(m_solver->a_noNodes(pCellId) * nDim, m_solver->a_noNodes(pCellId) * nDim, AT_,
"Ke");
1264 for(
MInt m1 = 0; m1 < m_solver->a_noNodes(pCellId) * nDim; m1++) {
1265 for(
MInt m2 = 0; m2 < m_solver->a_noNodes(pCellId) * nDim; m2++) {
1272 const MFloat alpha = (F1 - m_solver->m_alpha);
1273 m_solver->getElementMatrix(Ke, pCellId, alpha, subCellLvl, subCellCoord);
1274 for(
MInt m1 = 0; m1 < m_solver->a_noNodes(pCellId) * nDim; m1++) {
1275 for(
MInt m2 = 0; m2 < m_solver->a_noNodes(pCellId) * nDim; m2++) {
1276 Ke_final[m1][m2] += Ke(m1, m2);
1284 MBool outside = m_solver->m_geometry->pointIsInside2(subCellCoord);
1290 MFloatScratchSpace Ke(m_solver->a_noNodes(pCellId) * nDim, m_solver->a_noNodes(pCellId) * nDim, AT_,
"Ke");
1292 for(
MInt m1 = 0; m1 < m_solver->a_noNodes(pCellId) * nDim; m1++) {
1293 for(
MInt m2 = 0; m2 < m_solver->a_noNodes(pCellId) * nDim; m2++) {
1299 const MFloat alpha = (F1 - m_solver->m_alpha);
1300 m_solver->getElementMatrix(Ke, pCellId, alpha, subCellLvl, subCellCoord);
1301 for(
MInt m1 = 0; m1 < m_solver->a_noNodes(pCellId) * nDim; m1++) {
1302 for(
MInt m2 = 0; m2 < m_solver->a_noNodes(pCellId) * nDim; m2++) {
1303 Ke_final[m1][m2] += Ke(m1, m2);
1319 for(
MInt cell = 0; cell < m_solver->a_noCells(); cell++) {
1320 m_solver->a_needsSubCells(cell) =
false;
1321 m_solver->a_maxSubCellLvl(cell) = 0;
1323 for(
MInt cell = 0; cell < (
MInt)m_bndryCells.size(); cell++) {
1324 MInt pCellId = m_bndryCells[cell].m_cellId;
1326 for(
MInt noSeg = 0; noSeg < (
MInt)m_bndryCells[cell].m_segmentId.size(); noSeg++) {
1327 MInt segId = m_bndryCells[cell].m_segmentId[noSeg];
1328 if(m_subCellLayerDepth[segId] > depth) {
1329 depth = m_subCellLayerDepth[segId];
1333 m_solver->a_needsSubCells(pCellId) =
true;
1334 m_solver->a_maxSubCellLvl(pCellId) = depth;
1345std::vector<std::vector<MFloat>>
1352 for(
MInt d = 0; d < nDim; d++) {
1353 for(
MInt c1 = 0; c1 < (
MInt)cutPointList.size(); c1++) {
1354 COG[d] += cutPointList[c1][d];
1356 COG[d] /= (
MInt)cutPointList.size();
1369 std::vector<MFloat> angles;
1370 angles.push_back(0);
1371 for(
MInt c1 = 1; c1 < (
MInt)cutPointList.size(); c1++) {
1372 MFloat crossProduct[nDim] = {F0};
1381 for(
MInt d = 0; d < nDim; d++) {
1383 crossProduct[d] = F0;
1384 MInt d1 = ((d + 1) < nDim) ? (d + 1) : 0;
1385 MInt d2 = ((d1 + 1) < nDim) ? (d1 + 1) : 0;
1386 crossProduct[d] = ((cutPointList[0][d1] - COG[d1]) * (cutPointList[c1][d2] - COG[d2]))
1387 - ((cutPointList[0][d2] - COG[d2]) * (cutPointList[c1][d1] - COG[d1]));
1390 cosPhi += ((cutPointList[0][d] - COG[d]) * (cutPointList[c1][d] - COG[d]));
1393 l1 += ((cutPointList[0][d] - COG[d]) * (cutPointList[0][d] - COG[d]));
1394 l2 += ((cutPointList[c1][d] - COG[d]) * (cutPointList[c1][d] - COG[d]));
1395 lCross += (crossProduct[d] * crossProduct[d]);
1396 lNormal += (triangleNormal[d] * triangleNormal[d]);
1398 cosPhi /= (sqrt(l1) * sqrt(l2));
1402 for(
MInt d = 0; d < nDim; d++) {
1403 oppDir += (triangleNormal[d] * crossProduct[d]);
1405 oppDir /= (sqrt(lCross) * sqrt(lNormal));
1411 if(cosPhi > F1 || cosPhi < -F1) {
1412 cosPhi = round(cosPhi);
1415 angles.push_back(acos(cosPhi));
1417 angles.push_back((2 * PI) - acos(cosPhi));
1422 for(
MInt i = 0; i < (
MInt)(angles.size() - 1); i++) {
1423 for(
MInt j = 0; j < (
MInt)(angles.size() - i - 1); j++) {
1424 if(angles.at(j) > angles.at(j + 1)) {
1425 std::swap(angles.at(j), angles.at(j + 1));
1426 std::swap(cutPointList.at(j), cutPointList.at(j + 1));
1432 std::vector<std::vector<MFloat>> triangleList;
1433 for(
MInt c = 1; c < (
MInt)cutPointList.size() - 1; c++) {
1434 std::vector<MFloat> triangle;
1435 for(
MInt d1 = 0; d1 < nDim; d1++) {
1436 for(
MInt d2 = 0; d2 < nDim; d2++) {
1437 MInt point = (d1 == 0) ? d1 : (c + d1 - 1);
1438 triangle.push_back(cutPointList[point][d2]);
1441 triangleList.push_back(triangle);
1444 return triangleList;
1454std::vector<std::vector<MFloat>>
1458 ASSERT((
MInt)cutPointList.size() == 2,
"A line can only have two cut points with a cell");
1459 std::vector<std::vector<MFloat>> edgeList;
1460 std::vector<MFloat> edge;
1462 for(
MInt c = 0; c < (
MInt)cutPointList.size(); c++) {
1463 for(
MInt p = 0; p < (
MInt)cutPointList[c].size(); p++) {
1464 edge.push_back(cutPointList[c][p]);
1468 ASSERT((
MInt)edge.size() == 4,
"A edge must have only four coordinates");
1469 edgeList.push_back(edge);
1482 std::vector<MFloat> transformedTriPoints;
1484 MFloat edge1[nDim] = {F0};
1485 MFloat edge2[nDim] = {F0};
1486 MFloat result[nDim] = {F0};
1488 for(
MInt d1 = 0; d1 < nDim; d1++) {
1489 for(
MInt d2 = 0; d2 < nDim; d2++) {
1490 MFloat transformed = trianglePoints[d1 * nDim + d2] - trianglePoints[d2];
1491 if(d1 == nDim - 2) edge1[d2] = (trianglePoints[d1 * nDim + d2] - trianglePoints[d2]);
1492 if(d1 == nDim - 1) edge2[d2] = (trianglePoints[d1 * nDim + d2] - trianglePoints[d2]);
1493 transformedTriPoints.push_back(transformed);
1502 for(
MInt d1 = 0; d1 < nDim; d1++) {
1503 determinant += (result[d1] * result[d1]);
1505 determinant = sqrt(determinant);
1509 std::ignore = triangleNormal;
1688 const MInt edgeEndPos[4] = {1, 3, 0, 2};
1692 MFloat normals[2 * nDim][nDim];
1693 for(
MInt d1 = 0; d1 < 2 * nDim; d1++) {
1694 for(
MInt d2 = 0; d2 < nDim; d2++) {
1695 if(d1 >= (2 * d2) && d1 < (2 * (d2 + 1))) {
1697 normals[d1][d2] = pow(-F1, expo);
1699 normals[d1][d2] = F0;
1704 const MInt noStlElementEdges = (nDim == 3) ? 3 : 1;
1705 const MInt noElementEdges = (nDim == 3) ? 12 : 4;
1706 const MFloat eps = m_solver->m_eps;
1709 MFloat points[nDim][nDim];
1710 MFloat edges[noStlElementEdges][2 * nDim];
1711 std::array<MFloat, nDim> normal;
1712 std::array<MBool, nDim> pointInsideCell;
1713 MInt noInsidePoints;
1714 std::array<MInt, noStlElementEdges> noCutsPerEdge;
1715 MBool cutSurfPerEdge[noStlElementEdges][2 * nDim];
1716 MInt noCuttedSurfaces;
1717 std::array<MBool, noStlElementEdges> edgeNotCutted;
1718 std::array<MBool, noStlElementEdges> edgeOnSurface;
1722 MFloat edges[noElementEdges][2 * nDim];
1723 std::array<MBool, noElementEdges> edgeIsCut;
1725 std::array<MBool, noElementEdges> edgeOnSurface;
1729 for(
MInt index = 0; index < (
MInt)(m_bndryCndIds.size()); index++) {
1730 MInt segId = m_bndryCndSegIds[index];
1732 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
1733 const MInt cellId = m_bndryCells[i].m_cellId;
1734 const MFloat cellLength = m_solver->c_cellLengthAtCell(cellId);
1735 const MFloat halfLength = cellLength * 0.5;
1740 for(
MInt e = 0; e < noElementEdges; e++) {
1742 for(
MInt d = 0; d < nDim; d++) {
1743 MFloat coord = m_solver->c_coordinate(cellId, d);
1744 ele.edges[e][d] = coord + Fd::vertexPosition(e, d) * halfLength;
1745 ele.edges[e][d + nDim] = coord + Fd::vertexPosition(edgeEndPos[e], d) * halfLength;
1749 for(
MInt d = 0; d < nDim; d++) {
1750 MFloat coord = m_solver->c_coordinate(cellId, d);
1751 ele.edges[e][d] = coord + Fd::vertexPosition(e, d) * halfLength;
1752 ele.edges[e][d + nDim] = coord + Fd::vertexPosition(edgeEndPos[e], d) * halfLength;
1755 for(
MInt d = 0; d < nDim; d++) {
1756 MFloat coord = m_solver->c_coordinate(cellId, d);
1757 ele.edges[e][d] = coord + Fd::vertexPosition(e - 4, d) * halfLength;
1758 ele.edges[e][d + nDim] = coord + Fd::vertexPosition(e, d) * halfLength;
1761 for(
MInt d = 0; d < nDim; d++) {
1762 MFloat coord = m_solver->c_coordinate(cellId, d);
1763 ele.edges[e][d] = coord + Fd::vertexPosition(e - 4, d) * halfLength;
1764 MInt h = edgeEndPos[e - 8] + 4;
1765 ele.edges[e][d + nDim] = coord + Fd::vertexPosition(h, d) * halfLength;
1773 for(
MInt j = 0; j < nDim; j++) {
1774 target[j] = m_solver->c_coordinate(cellId, j) - halfLength;
1775 target[j + nDim] = m_solver->c_coordinate(cellId, j) + halfLength;
1777 std::vector<MInt> nodeList;
1778 getStlNodeList(cellId, nodeList);
1779 for(
MInt n = 0; n < (
MInt)nodeList.size(); n++) {
1780 std::vector<std::vector<MFloat>> cutPointList;
1783 if(m_solver->m_geometry->elements[nodeList[n]].m_segmentId != segId) {
1790 for(
MInt e = 0; e < noStlElementEdges; e++) {
1791 for(
MInt d = 0; d < nDim; d++) {
1792 stl.edges[e][d] = m_solver->m_geometry->elements[nodeList[n]].m_vertices[e][d];
1794 stl.edges[e][d + nDim] = m_solver->m_geometry->elements[nodeList[n]].m_vertices[e + 1][d];
1796 stl.edges[e][d + nDim] = m_solver->m_geometry->elements[nodeList[n]].m_vertices[0][d];
1801 for(
MInt d = 0; d < nDim; d++) {
1802 stl.normal[d] = m_solver->m_geometry->elements[nodeList[n]].m_normal[d];
1805 stl.normal[0] = stl.edges[0][1 + nDim] - stl.edges[0][1];
1806 stl.normal[1] = stl.edges[0][0 + nDim] - stl.edges[0][0];
1810 stl.noInsidePoints = 0;
1811 for(
MInt point = 0; point < nDim; point++) {
1812 stl.pointInsideCell[point] =
false;
1813 MBool isInside =
true;
1814 for(
MInt d = 0; d < nDim; d++) {
1815 stl.points[point][d] = m_solver->m_geometry->elements[nodeList[n]].m_vertices[point][d];
1816 if(stl.points[point][d] < (target[d]) || stl.points[point][d] > (target[d + nDim])) {
1820 stl.pointInsideCell[point] = isInside;
1822 if(stl.pointInsideCell[point]) {
1823 stl.noInsidePoints++;
1824 std::vector<MFloat> cutPoint;
1825 for(
MInt d = 0; d < nDim; d++) {
1826 cutPoint.push_back(stl.points[point][d]);
1828 cutPointList.push_back(cutPoint);
1835 for(
MInt e = 0; e < noStlElementEdges; e++) {
1837 MInt point2 = (e + 1 < nDim) ? (e + 1) : 0;
1838 stl.edgeNotCutted[e] = (stl.pointInsideCell[point1] && stl.pointInsideCell[point2]);
1839 stl.noCutsPerEdge[e] = 0;
1840 stl.noCuttedSurfaces = 0;
1841 stl.edgeOnSurface[e] =
false;
1842 for(
MInt surface = 0; surface < 2 * nDim; surface++) {
1843 stl.cutSurfPerEdge[e][surface] =
false;
1855 if(stl.noInsidePoints < nDim) {
1858 for(
MInt e = 0; e < noStlElementEdges; e++) {
1860 if(stl.edgeNotCutted[e])
continue;
1865 for(
MInt surface = 0; surface < 2 * nDim; surface++) {
1866 const MFloat numer = stl.edges[e][1 + nDim] - stl.edges[e][1];
1867 const MFloat denom = stl.edges[e][0 + nDim] - stl.edges[e][0];
1868 const MFloat coordX = m_solver->c_coordinate(cellId, 0);
1869 const MFloat coordY = m_solver->c_coordinate(cellId, 1);
1870 const MFloat minStlEdgeX =
mMin(stl.edges[e][0], stl.edges[e][0 + nDim]);
1871 const MFloat minStlEdgeY =
mMin(stl.edges[e][1], stl.edges[e][1 + nDim]);
1872 const MFloat maxStlEdgeX =
mMax(stl.edges[e][0], stl.edges[e][0 + nDim]);
1873 const MFloat maxStlEdgeY =
mMax(stl.edges[e][1], stl.edges[e][1 + nDim]);
1876 if(
approx(normals[surface][0], F0, eps)) {
1877 const MFloat y = coordY + normals[surface][1] * halfLength;
1878 const MFloat x1 = coordX - halfLength;
1879 const MFloat x2 = coordX + halfLength;
1884 if(
approx(numer, F0, eps)) {
1889 else if(
approx(denom, F0, eps)) {
1892 if(x1 <= stl.edges[e][0 + nDim] && x2 >= stl.edges[e][0 + nDim]) {
1895 if(minStlEdgeY <= y && maxStlEdgeY >=
y) {
1896 std::vector<MFloat> cutPoint;
1897 cutPoint.push_back(stl.edges[e][0 + nDim]);
1898 cutPoint.push_back(
y);
1899 cutPointList.push_back(cutPoint);
1908 const MFloat cutPointX = (denom / numer) * (
y - stl.edges[e][1]) + stl.edges[e][0];
1910 if(cutPointX >= x1 && cutPointX <= x2 && cutPointX >= minStlEdgeX && cutPointX <= maxStlEdgeX) {
1911 std::vector<MFloat> cutPoint;
1912 cutPoint.push_back(cutPointX);
1913 cutPoint.push_back(cutPointY);
1914 cutPointList.push_back(cutPoint);
1919 if(
approx(normals[surface][1], F0, eps)) {
1920 const MFloat x = coordX + normals[surface][0] * halfLength;
1921 const MFloat y1 = coordY - halfLength;
1922 const MFloat y2 = coordY + halfLength;
1927 if(
approx(denom, F0, eps)) {
1932 else if(
approx(numer, F0, eps)) {
1935 if(y1 <= stl.edges[e][1 + nDim] && y2 >= stl.edges[e][1 + nDim]) {
1938 if(minStlEdgeX <= x && maxStlEdgeX >= x) {
1939 std::vector<MFloat> cutPoint;
1940 cutPoint.push_back(x);
1941 cutPoint.push_back(stl.edges[e][1 + nDim]);
1942 cutPointList.push_back(cutPoint);
1951 const MFloat cutPointX = x;
1952 const MFloat cutPointY = (numer / denom) * (x - stl.edges[e][0]) + stl.edges[e][1];
1954 if(cutPointY >= y1 && cutPointY <= y2 && cutPointY >= minStlEdgeY && cutPointY <= maxStlEdgeY) {
1955 std::vector<MFloat> cutPoint;
1956 cutPoint.push_back(cutPointX);
1957 cutPoint.push_back(cutPointY);
1958 cutPointList.push_back(cutPoint);
1967 for(
MInt e = 0; e < noStlElementEdges; e++) {
1969 if(stl.edgeNotCutted[e])
continue;
1973 for(
MInt surface = 0; surface < 2 * nDim; surface++) {
1976 for(
MInt d = 0; d < nDim; d++) {
1977 MFloat locationVec = m_solver->c_coordinate(cellId, d) + normals[surface][d] * halfLength;
1978 denom += (normals[surface][d] * (stl.edges[e][d + nDim] - stl.edges[e][d]));
1979 numer += (normals[surface][d] * locationVec);
1981 for(
MInt d = 0; d < nDim; d++) {
1982 numer -= (normals[surface][d] * stl.edges[e][d]);
1984 if(!
approx(denom, F0, eps)) {
1986 MFloat lambda = numer / denom;
1987 if((lambda >= F0) && (lambda <= F1)) {
1988 MBool validIntersection =
true;
1989 std::vector<MFloat> cutPoint;
1990 for(
MInt d = 0; d < nDim; d++) {
1991 MFloat point = stl.edges[e][d] + lambda * (stl.edges[e][d + nDim] - stl.edges[e][d]);
1992 if(fabs(point - target[d]) < m_solver->m_eps) {
1994 }
else if(fabs(point - target[d + nDim]) < m_solver->m_eps) {
1995 point = target[d + nDim];
1997 cutPoint.push_back(point);
1998 if(point < (target[d]) || point > (target[d + nDim])) {
1999 validIntersection =
false;
2002 if(validIntersection) {
2003 stl.cutSurfPerEdge[e][surface] =
true;
2004 cutPointList.push_back(cutPoint);
2005 MBool surfCutBefore =
false;
2006 for(
MInt prevE = 0; prevE < e - 1; prevE++) {
2007 if(stl.cutSurfPerEdge[prevE][surface]) {
2008 surfCutBefore =
true;
2012 if(!surfCutBefore) stl.noCuttedSurfaces++;
2013 stl.noCutsPerEdge[e]++;
2022 mTerm(1, AT_,
"ERROR: Wrong number of dimensions! Aborting.");
2029 for(
MInt e = 0; e < noElementEdges; e++) {
2030 ele.edgeOnSurface[e] =
false;
2033 for(
MInt d = 0; d < nDim; d++) {
2034 denom += (stl.normal[d] * (ele.edges[e][d + nDim] - ele.edges[e][d]));
2035 numer += (stl.normal[d] * stl.points[0][d]);
2037 for(
MInt d = 0; d < nDim; d++) {
2038 numer -= (stl.normal[d] * ele.edges[e][d]);
2040 if(
approx(denom, F0, eps)) {
2041 if(
approx(numer, F0, eps)) {
2044 ele.edgeOnSurface[e] =
true;
2045 std::vector<MFloat> cutPoint1;
2046 std::vector<MFloat> cutPoint2;
2047 for(
MInt d = 0; d < nDim; d++) {
2048 cutPoint1.push_back(ele.edges[e][d]);
2049 cutPoint2.push_back(ele.edges[e][d + nDim]);
2051 MBool inside = pointInTriangle(stl.points[0], stl.points[1], stl.points[2], cutPoint1);
2053 cutPointList.push_back(cutPoint1);
2056 inside = pointInTriangle(stl.points[0], stl.points[1], stl.points[2], cutPoint2);
2058 cutPointList.push_back(cutPoint2);
2066 MFloat lambda = numer / denom;
2067 MBool inside =
false;
2068 std::vector<MFloat> cutPoint;
2069 if((lambda >= F0) && (lambda <= F1)) {
2070 for(
MInt d = 0; d < nDim; d++) {
2071 MFloat point = ele.edges[e][d] + lambda * (ele.edges[e][d + nDim] - ele.edges[e][d]);
2072 cutPoint.push_back(point);
2074 inside = pointInTriangle(stl.points[0], stl.points[1], stl.points[2], cutPoint);
2076 cutPointList.push_back(cutPoint);
2084 for(
MInt c1 = 0; c1 < (
MInt)cutPointList.size(); c1++) {
2086 while(c2 < (
MInt)cutPointList.size()) {
2087 MBool dublicated =
true;
2088 for(
MInt d = 0; d < nDim; d++) {
2089 if(!
approx(cutPointList[c1][d], cutPointList[c2][d], eps)) {
2095 cutPointList.erase(cutPointList.begin() + c2);
2102 if((
MInt)cutPointList.size() < nDim)
continue;
2103 setBoundaryStlElements(cutPointList, stl.normal.data(), segId, i);
2118 std::vector<std::vector<MFloat>> newStlElementList;
2120 newStlElementList = createEdgesFromCutPoints(cutPointList);
2122 newStlElementList = createTrianglesFromCutPoints(cutPointList, normal);
2124 MFloat normalLength = F0;
2125 for(
MInt d = 0; d < nDim; d++) {
2126 normalLength += (normal[d] * normal[d]);
2128 normalLength = sqrt(normalLength);
2130 for(
MInt t = 0; t < (
MInt)newStlElementList.size(); t++) {
2131 std::vector<MFloat> vertices;
2132 std::vector<MFloat> elementNormal;
2133 for(
MInt v = 0; v < nDim; v++) {
2134 for(
MInt p = 0; p < nDim; p++) {
2135 vertices.push_back(newStlElementList[t][v * nDim + p]);
2137 MFloat n = normal[v] / normalLength;
2138 elementNormal.push_back(n);
2140 m_bndryCells[i].m_cutFaces.push_back(vertices);
2141 m_bndryCells[i].m_faceNormals.push_back(elementNormal);
2142 m_bndryCells[i].m_segmentIdOfCutFace.push_back(segId);
2155 MInt segId = m_bndryCndSegIds[index];
2157 MString fileName =
"Segment_" + std::to_string(segId) + prefix +
".stl";
2159 stlFile.open(fileName);
2161 stlFile <<
"solid Visualization Toolkit generated SLA File\n";
2162 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
2163 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
2164 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
2165 stlFile <<
" facet normal ";
2166 for(
MInt d = 0; d < nDim; d++) {
2167 if(d < (nDim - 1)) {
2168 stlFile << m_bndryCells[i].m_faceNormals[t][d] <<
" ";
2170 stlFile << m_bndryCells[i].m_faceNormals[t][d] <<
"\n";
2173 stlFile <<
" outer loop\n";
2174 for(
MInt v = 0; v < nDim; v++) {
2175 stlFile <<
" vertex ";
2176 for(
MInt p = 0; p < nDim; p++) {
2177 if(p < (nDim - 1)) {
2178 stlFile << m_bndryCells[i].m_cutFaces[t][v * nDim + p] <<
" ";
2180 stlFile << m_bndryCells[i].m_cutFaces[t][v * nDim + p] <<
"\n";
2184 stlFile <<
" endloop\n";
2185 stlFile <<
" endFacet\n";
2188 stlFile <<
"endsolid";
2200 MInt segId = m_bndryCndSegIds[index];
2203 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
2204 MFloat avgNormal[nDim] = {F0};
2206 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
2207 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
2208 for(
MInt d = 0; d < nDim; d++) {
2209 avgNormal[d] += m_bndryCells[i].m_faceNormals[t][d];
2213 MFloat normalLength = F0;
2214 for(
MInt d = 0; d < nDim; d++) {
2215 m_bndryCells[i].m_avgFaceNormal[d] = avgNormal[d] / cnt;
2216 normalLength += (m_bndryCells[i].m_avgFaceNormal[d] * m_bndryCells[i].m_avgFaceNormal[d]);
2218 normalLength = sqrt(normalLength);
2219 for(
MInt d = 0; d < nDim; d++) {
2220 m_bndryCells[i].m_avgFaceNormal[d] = avgNormal[d] / normalLength;
2233 for(
MInt index = 0; index < (
MInt)(m_bndryCndIds.size()); index++) {
2234 MInt segId = m_bndryCndSegIds[index];
2236 if(!m_solver->m_testRun) {
2238 writeOutSTLBoundaries(index, prefix);
2240 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
2241 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
2242 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
2243 for(
MInt d1 = 0; d1 < nDim; d1++) {
2246 for(
MInt d2 = 0; d2 < nDim; d2++) {
2247 x[d2] = m_bndryCells[i].m_cutFaces[t][d1 * nDim + d2];
2249 const MInt pCellId = m_bndryCells[i].m_cellId;
2250 m_solver->transformToLocal(pCellId, x, z);
2253 m_solver->getDisplacementInterpolationMatrix(pCellId, z, L_coef);
2255 for(
MInt d2 = 0; d2 < nDim; d2++) {
2256 MFloat displacement = F0;
2257 for(
MInt node = 0; node < m_solver->a_noNodes(pCellId); node++) {
2258 for(
MInt d3 = 0; d3 < nDim; d3++) {
2259 MInt nodeId = m_solver->a_nodeIdsLocal(pCellId, node);
2260 displacement += L_coef(d2, node * nDim + d3) * m_solver->m_totalNodalDisplacements[nodeId * nDim + d3];
2263 m_bndryCells[i].m_cutFaces[t][d1 * nDim + d2] += displacement;
2268 if(!m_solver->m_testRun) {
2270 writeOutSTLBoundaries(index, prefix);
2284 for(
MInt index = 0; index < (
MInt)(m_bndryCndIds.size()); index++) {
2285 MInt segId = m_bndryCndSegIds[index];
2287 stringstream prefix;
2289 MString fileName =
"Segment_" + std::to_string(segId) + prefix.str() +
".stl";
2291 stlFile.open(fileName);
2293 stlFile <<
"solid Visualization Toolkit generated SLA File\n";
2294 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
2295 for(
MInt t = 0; t < (
MInt)m_bndryCells[i].m_cutFaces.size(); t++) {
2296 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
2297 stlFile <<
" facet normal ";
2298 for(
MInt d = 0; d < nDim; d++) {
2299 if(d < (nDim - 1)) {
2300 stlFile << m_bndryCells[i].m_faceNormals[t][d] <<
" ";
2302 stlFile << m_bndryCells[i].m_faceNormals[t][d] <<
"\n";
2307 for(
MInt d1 = 0; d1 < nDim; d1++) {
2308 std::array<MFloat, nDim> x{};
2309 std::array<MFloat, nDim> z{};
2310 for(
MInt d2 = 0; d2 < nDim; d2++) {
2311 x[d2] = m_bndryCells[i].m_cutFaces[t][d1 * nDim + d2];
2313 const MInt pCellId = m_bndryCells[i].m_cellId;
2314 m_solver->transformToLocal(pCellId, x.data(), z.data());
2317 m_solver->getDisplacementInterpolationMatrix(pCellId, z.data(), L_coef);
2319 for(
MInt d2 = 0; d2 < nDim; d2++) {
2320 MFloat displacement = F0;
2321 for(
MInt node = 0; node < m_solver->a_noNodes(pCellId); node++) {
2322 for(
MInt d3 = 0; d3 < nDim; d3++) {
2323 MInt nodeId = m_solver->a_nodeIdsLocal(pCellId, node);
2324 displacement += L_coef(d2, node * nDim + d3) * m_solver->m_totalNodalDisplacements[nodeId * nDim + d3];
2327 points(d1, d2) = displacement + m_bndryCells[i].m_cutFaces[t][d1 * nDim + d2];
2330 stlFile <<
" outer loop\n";
2331 for(
MInt v = 0; v < nDim; v++) {
2332 stlFile <<
" vertex ";
2333 for(
MInt p = 0; p < nDim; p++) {
2334 if(p < (nDim - 1)) {
2335 stlFile << points(v, p) <<
" ";
2337 stlFile << points(v, p) <<
"\n";
2341 stlFile <<
" endloop\n";
2342 stlFile <<
" endFacet\n";
2345 stlFile <<
"endsolid";
2362 for(
MInt d = 0; d < nDim; d++) {
2363 dot[0] += (C[d] - A[d]) * (C[d] - A[d]);
2364 dot[1] += (C[d] - A[d]) * (B[d] - A[d]);
2365 dot[2] += (C[d] - A[d]) * (P[d] - A[d]);
2366 dot[3] += (B[d] - A[d]) * (B[d] - A[d]);
2367 dot[4] += (B[d] - A[d]) * (P[d] - A[d]);
2369 u = (dot[3] * dot[2] - dot[1] * dot[4]) / (dot[0] * dot[3] - dot[1] * dot[1]);
2370 v = (dot[0] * dot[4] - dot[1] * dot[2]) / (dot[0] * dot[3] - dot[1] * dot[1]);
2371 if((u >= F0) && (v >= F0) && ((u + v) <= F1)) {
2385 MInt segId = m_bndryCndSegIds[index];
2388 for(
MInt i = m_bndryCndOffsets[index]; i < m_bndryCndOffsets[index + 1]; i++) {
2389 MInt noCutFaces = (
MInt)m_bndryCells[i].m_cutFaces.size();
2390 for(
MInt t = 0; t < noCutFaces; t++) {
2391 if(m_bndryCells[i].m_segmentIdOfCutFace[t] != segId)
continue;
2396 std::vector<MFloat> triangleNormal;
2397 for(
MInt d = 0; d < nDim; d++) {
2398 pointA[d] = m_bndryCells[i].m_cutFaces[t][0 * nDim + d];
2399 pointB[d] = m_bndryCells[i].m_cutFaces[t][1 * nDim + d];
2400 pointC[d] = m_bndryCells[i].m_cutFaces[t][2 * nDim + d];
2401 triangleNormal.push_back(m_bndryCells[i].m_faceNormals[t][d]);
2406 for(
MInt d = 0; d < nDim; d++) {
2407 lenAB += (pointA[d] - pointB[d]) * (pointA[d] - pointB[d]);
2408 lenAC += (pointA[d] - pointC[d]) * (pointA[d] - pointC[d]);
2409 lenBC += (pointB[d] * pointC[d]) * (pointB[d] * pointC[d]);
2411 lenAB = sqrt(lenAB);
2412 lenAC = sqrt(lenAC);
2413 lenBC = sqrt(lenBC);
2414 std::vector<MFloat> newTriangle;
2415 if((lenAB > lenAC) && (lenAB > lenBC)) {
2416 for(
MInt d = 0; d < nDim; d++) {
2417 midPoint[d] = F1B2 * (pointA[d] + pointB[d]);
2418 m_bndryCells[i].m_cutFaces[t][0 * nDim + d] = midPoint[d];
2420 for(
MInt d = 0; d < nDim; d++) {
2421 newTriangle.push_back(midPoint[d]);
2423 for(
MInt d = 0; d < nDim; d++) {
2424 newTriangle.push_back(pointA[d]);
2426 for(
MInt d = 0; d < nDim; d++) {
2427 newTriangle.push_back(pointC[d]);
2429 }
else if((lenAC > lenAB) && (lenAC > lenBC)) {
2430 for(
MInt d = 0; d < nDim; d++) {
2431 midPoint[d] = F1B2 * (pointA[d] + pointC[d]);
2432 m_bndryCells[i].m_cutFaces[t][0 * nDim + d] = midPoint[d];
2434 for(
MInt d = 0; d < nDim; d++) {
2435 newTriangle.push_back(midPoint[d]);
2437 for(
MInt d = 0; d < nDim; d++) {
2438 newTriangle.push_back(pointA[d]);
2440 for(
MInt d = 0; d < nDim; d++) {
2441 newTriangle.push_back(pointB[d]);
2443 }
else if((lenBC > lenAB) && (lenBC > lenAC)) {
2444 for(
MInt d = 0; d < nDim; d++) {
2445 midPoint[d] = F1B2 * (pointB[d] + pointC[d]);
2446 m_bndryCells[i].m_cutFaces[t][1 * nDim + d] = midPoint[d];
2448 for(
MInt d = 0; d < nDim; d++) {
2449 newTriangle.push_back(midPoint[d]);
2451 for(
MInt d = 0; d < nDim; d++) {
2452 newTriangle.push_back(pointA[d]);
2454 for(
MInt d = 0; d < nDim; d++) {
2455 newTriangle.push_back(pointB[d]);
2458 m_bndryCells[i].m_cutFaces.push_back(newTriangle);
2459 m_bndryCells[i].m_faceNormals.push_back(triangleNormal);
2460 m_bndryCells[i].m_segmentIdOfCutFace.push_back(segId);
2477 for(
MInt d = 0; d < nDim; d++) {
2478 cellHalfLength = F1B2 * m_solver->c_cellLengthAtCell(cellId);
2479 target[d] = m_solver->c_coordinate(cellId, d) - cellHalfLength;
2480 target[d + nDim] = m_solver->c_coordinate(cellId, d) + cellHalfLength;
2484 m_solver->m_geometry->getIntersectionElements(target, nodeList, cellHalfLength, &m_solver->c_coordinate(cellId, 0));
void mAlloc(T *&a, const MLong N, const MString &objectName, MString function)
allocates memory for one-dimensional array 'a' of size N
MBool mDeallocate(T *&a)
deallocates the memory previously allocated for element 'a'
static MBool propertyExists(const MString &name, MInt solver=m_noSolvers)
This function checks if a property exists in general.
void setBndryCndHandler()
This function sets the BndryCndHandler objects at solver setup \adaptation 22.04.2021,...
void sortBoundaryCells()
This function sorts the boundary cells according to the BC id.
void bc8030(MInt index)
This function applies the loads boundary condition.
void createBoundaryCells()
Creates boundary cells according to the geometry information.
void updateForceVector()
Execution of the force boundary conditions.
void initBndryCnds()
Initializes boundary cells.
void writeOutSTLBoundaries(MInt index, MString prefix)
Write out the boundary segments in stl-file format.
void writeOutModifiedBoundaries()
Write out the boundary segments in stl-file format.
void bc8011(MInt index)
This function applies the fixation boundary condition.
std::vector< std::vector< MFloat > > createEdgesFromCutPoints(std::vector< std::vector< MFloat > > cutPointList)
Calculation of the surface edges.
void bc8031(MInt index)
This function applies the loads boundary condition.
void bc8032(MInt index)
This function applies the loads boundary condition.
void bc8035(MInt index)
This function applies the loads boundary condition.
void bc8012(MInt index)
This function applies the fixation boundary condition.
FcBndryCnd(FcSolver< nDim > *solver)
void refineTriangle(MInt index)
Refines the triangles of a segment by deviding them in the middle.
std::vector< std::vector< MFloat > > createTrianglesFromCutPoints(std::vector< std::vector< MFloat > > cutPointList, MFloat *triangleNormal)
Triangulation algorithm of the cut points.
void getStlNodeList(const MInt cellId, std::vector< MInt > &nodeList)
Returns a list of all elements cutting the target cell.
void findCellsRequireSubCellIntegration()
Set the subcell tree depth for cells requiring subcell integration.
void subCellIntegration(const MInt subCellLvl, MFloat *subCellParentCoord, const MInt childPos, const MInt pCellId, MFloat **Ke)
Execution of the subcell integration.
void updateSystemMatrix()
Execution of the displacement boundary conditions.
void setBoundaryStlElements(std::vector< std::vector< MFloat > > cutPointList, MFloat *normal, MInt segId, MInt i)
Add cut faces to the collector of the boundary cell.
virtual void bc0(MInt index)
Boundary condition for free surfaces.
void updateTrianglePosition()
Moves a triangle depending on the simulated displacment inside a cell.
void bc8010(MInt index)
This function applies the fixation boundary condition.
void bc8020(MInt index)
This function applies a non-zero displacement boundary condition.
void calculateCutPoints()
Calculation of the cutpoints of each segment.
MFloat solveIntegrationOnTriangle(std::vector< MFloat > trianglePoints, MFloat *triangleNormal)
Gauss quadrature on triangles.
void calcReactionForces()
Calculation of reaction forces.
void calcAvgFaceNormal(MInt index)
Calculation of the normal vector of the cut faces.
MBool pointInTriangle(MFloat *A, MFloat *B, MFloat *C, std::vector< MFloat > P)
Checks if a point is inside a triangle.
This class represents a structure solver using the Finite Cell Method.
Geometry< nDim > * m_geometry
This class is a ScratchSpace.
void fill(T val)
fill the scratch with a given value
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MBool approx(const T &, const U &, const T)
constexpr T mMin(const T &x, const T &y)
constexpr T mMax(const T &x, const T &y)
constexpr MLong IPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
std::basic_string< char > MString
void cross(const T *const u, const T *const v, T *const c)
MFloat dist(const Point< DIM > &p, const Point< DIM > &q)