12#include <unordered_map>
25 :
maia::CartesianSolver<nDim,
FcSolver<nDim>>(
id, gridProxy_, comm), m_geometry(&geometry_) {
29 RECORD_TIMER_START(m_t.solver);
41 m_isThermal = Context::getSolverProperty<MBool>(
"isThermal", m_solverId, AT_, &m_isThermal);
42 m_cells.setThermal(m_isThermal);
52 m_polyDeg = Context::getSolverProperty<MInt>(
"polyDeg", m_solverId, AT_, &m_polyDeg);
53 m_cells.setMaxPRfnmnt(m_polyDeg);
63 m_testRun = Context::getSolverProperty<MBool>(
"testRun", m_solverId, AT_, &m_testRun);
72 m_analyticSolution = F1;
73 m_analyticSolution = Context::getSolverProperty<MFloat>(
"analyticSolution", m_solverId, AT_, &m_analyticSolution);
81 m_printEigenValues =
false;
82 m_printEigenValues = Context::getSolverProperty<MBool>(
"printEigenValues", m_solverId, AT_, &m_printEigenValues);
93 m_E = Context::getSolverProperty<MFloat>(
"EModule", m_solverId, AT_, &m_E);
103 m_eps = Context::getSolverProperty<MFloat>(
"epsBiCG", m_solverId, AT_, &m_eps);
113 m_alpha = Context::getSolverProperty<MFloat>(
"alpha", m_solverId, AT_, &m_alpha);
122 m_maxNoIterations = 10000;
123 m_maxNoIterations = Context::getSolverProperty<MInt>(
"noIterations", m_solverId, AT_, &m_maxNoIterations);
133 m_noLoadSteps = Context::getSolverProperty<MInt>(
"noLoadSteps", m_solverId, AT_, &m_noLoadSteps);
142 m_solveSoEIteratively =
true;
143 m_solveSoEIteratively =
144 Context::getSolverProperty<MBool>(
"solveSoEIteratively", m_solverId, AT_, &m_solveSoEIteratively);
153 m_fcInterpolationMethod =
"LAGRANGE_INTERP";
154 m_fcInterpolationMethod =
155 Context::getSolverProperty<MString>(
"fcInterpolationMethod", m_solverId, AT_, &m_fcInterpolationMethod);
160 m_cells.reset(grid().raw().treeb().capacity());
161 m_cells.append(grid().noCells());
164 updateCellCollectorFromGrid();
166 setIntegrationWeights();
169 initJacobianMatrix();
172 grid().findEqualLevelNeighborsParDiagonal(
false);
180 allocateNodeVectors();
202 RECORD_TIMER_STOP(m_t.solver);
223 for(
MInt i = 0; i < a_noCells(); i++) {
225 a_isWindow(i) =
false;
226 a_poissonRatio(i) = m_poissonRatio;
227 a_pRfnmnt(i) = m_polyDeg;
228 a_noNodes(i) = (a_pRfnmnt(i) + 2) * (a_pRfnmnt(i) + 2);
229 a_isActive(i) =
true;
230 if(nDim == 3) a_noNodes(i) *= (a_pRfnmnt(i) + 2);
232 for(
MInt strain = 0; strain < m_noStrains; strain++) {
233 a_elementStrains(i, strain) = F0;
236 for(
MInt stress = 0; stress < m_noStrains; stress++) {
237 a_elementStresses(i, stress) = F0;
242 for(
MInt deg = 0; deg < a_pRfnmnt(i) + 2; deg++) {
243 a_nodePosition(i, deg) = Fd::nodePosLobattoPoints(a_pRfnmnt(i), deg - 1);
248 for(
MInt deg = 0; deg < a_pRfnmnt(i) + 2; deg++) {
250 a_nodePosition(i, deg) = -F1;
251 }
else if(deg < a_pRfnmnt(i) + 1) {
252 a_nodePosition(i, deg) = Fd::nodePosLobattoPoints(a_pRfnmnt(i), deg - 1);
254 a_nodePosition(i, deg) = F1;
260 for(
MInt deg = 0; deg < a_pRfnmnt(i) + 2; deg++) {
261 a_nodePosition(i, deg) = Fd::nodePosLobattoPoints(a_pRfnmnt(i), deg - 1);
266 for(
MInt deg = 0; deg < a_pRfnmnt(i) + 2; deg++) {
268 a_nodePosition(i, deg) = -F1;
269 }
else if(deg < a_pRfnmnt(i) + 1) {
270 a_nodePosition(i, deg) = Fd::nodePosLobattoPoints(a_pRfnmnt(i), deg - 1);
272 a_nodePosition(i, deg) = F1;
278 mTerm(1, AT_,
"ERROR: Interpolation method unknown in FC solver!!!");
283 for(
MInt i = 0; i < noNeighborDomains(); i++) {
284 for(
MInt c = 0; c < noHaloCells(i); c++) {
285 a_isHalo(haloCell(i, c)) =
true;
288 for(
MInt i = 0; i < noNeighborDomains(); i++) {
289 for(
MInt c = 0; c < noWindowCells(i); c++) {
290 a_isWindow(windowCell(i, c)) =
true;
306 if(m_gaussPoints !=
nullptr) {
309 if(m_gaussPoints !=
nullptr) {
312 mAlloc(m_gaussPoints, m_polyDeg + 1, m_polyDeg + 2,
"m_gaussPoints", F0, AT_);
313 mAlloc(m_gaussWeights, m_polyDeg + 1, m_polyDeg + 2,
"m_gaussWeights", F0, AT_);
315 for(
MInt p = 0;
p < m_polyDeg + 1;
p++) {
316 Fd::gaussPoint(p + 1, m_gaussPoints[p], m_gaussWeights[p]);
317 MInt halfLen = (m_polyDeg + 2 + 1) / 2;
318 for(
MInt n = 0; n < halfLen; n++) {
319 MFloat saveP = m_gaussPoints[
p][n];
320 MFloat saveW = m_gaussWeights[
p][n];
321 m_gaussPoints[
p][n] = m_gaussPoints[
p][m_polyDeg + 1 - n];
322 m_gaussPoints[
p][m_polyDeg + 1 - n] = saveP;
323 m_gaussWeights[
p][n] = m_gaussWeights[
p][m_polyDeg + 1 - n];
324 m_gaussWeights[
p][m_polyDeg + 1 - n] = saveW;
342 for(
MInt i = 0; i < a_noCells(); i++) {
343 if(!c_isLeafCell(i))
continue;
344 if(a_isBndryCell(i))
continue;
346 MFloat point[nDim] = {F0};
347 for(
MInt d = 0; d < nDim; d++) {
348 point[d] = c_coordinate(i, d);
350 MBool outside = m_geometry->pointIsInside2(point);
351 a_isActive(i) = !outside;
369 m_log <<
"Initializing inverse Jacobian determinant... ";
371 for(
MInt i = 0; i < a_noCells(); i++) {
372 a_invJacobian(i) = F2 / grid().cellLengthAtCell(i);
375 m_log <<
"done" << endl;
388 createElementToNodeMapping();
390 mAlloc(m_globalNodeIdOffsets, noDomains() + 1,
"m_globalNodeIdOffsets", 0, AT_);
393 if(noDomains() > 1) {
397 for(
MInt d = 0; d < noDomains(); d++) {
398 if(domainId() == d) {
399 createElementToNodeMappingGlobal();
404 MPI_Allreduce(MPI_IN_PLACE, &m_totalNoNodesGlobal, 1, MPI_INT, MPI_MAX, mpiComm(), AT_,
"MPI_IN_PLACE",
405 "m_totalNoNodesGlobal");
406 m_globalNodeIdOffsets[d + 1] = m_totalNoNodesGlobal;
409 reorderLocalNodeIds();
411 createElementToNodeMappingGlobal();
413 m_globalNodeIdOffsets[1] = m_totalNoNodesGlobal;
416 m_noInternalNodes = m_globalNodeIdOffsets[domainId() + 1] - m_globalNodeIdOffsets[domainId()];
421 if(noDomains() > 1) consistencyCheck2();
424 mAlloc(m_nodalDisplacements, m_totalNoNodes * nDim,
"m_nodalDisplacements", F0, AT_);
425 mAlloc(m_totalNodalDisplacements, m_totalNoNodes * nDim,
"m_totalNodalDisplacements", F0, AT_);
427 mAlloc(m_nodalLoadVector, m_totalNoNodes * nDim,
"m_nodalLoadVector", F0, AT_);
428 mAlloc(m_externalLoadVector, m_totalNoNodes * nDim,
"m_externalLoadVector", F0, AT_);
429 mAlloc(m_internalLoadVector, m_totalNoNodes * nDim,
"m_internalLoadVector", F0, AT_);
430 mAlloc(m_reactionForceVector, m_totalNoNodes * nDim,
"m_reactionForceVector", F0, AT_);
431 mAlloc(m_localToGlobalId, m_totalNoNodes,
"m_localToGlobalId", -1, AT_);
432 mAlloc(m_globalToLocalId, m_totalNoNodesGlobal,
"m_globalToLocalId", -1, AT_);
434 for(
MInt cell = 0; cell < a_noCells(); cell++) {
435 if(!a_isActive(cell))
continue;
436 for(
MInt node = 0; node < a_noNodes(cell); node++) {
437 MInt localNodeId = a_nodeIdsLocal(cell, node);
438 MInt globalNodeId = a_nodeIdsGlobal(cell, node);
439 if(m_localToGlobalId[localNodeId] == -1) {
440 m_localToGlobalId[localNodeId] = globalNodeId;
442 if(m_localToGlobalId[localNodeId] != globalNodeId) {
443 mTerm(1, AT_,
"ERROR in local to global Mapping");
446 if(m_globalToLocalId[globalNodeId] == -1) {
447 m_globalToLocalId[globalNodeId] = localNodeId;
449 if(m_globalToLocalId[globalNodeId] != localNodeId) {
450 mTerm(1, AT_,
"ERROR in global to local Mapping");
462 MInt noEdges = (nDim == 2) ? 0 : 12;
463 MInt noSurfaces = 2 * nDim;
466 for(
MInt cell = 0; cell < a_noCells(); cell++) {
467 if(!c_isLeafCell(cell))
continue;
468 if(!a_isActive(cell))
continue;
469 for(
MInt node = 0; node < a_noNodes(cell); node++) {
470 if(a_nodeIdsGlobal(cell, node) >= m_globalNodeIdOffsets[domainId()]
471 && a_nodeIdsGlobal(cell, node) < m_globalNodeIdOffsets[domainId() + 1]) {
472 a_nodeIdsLocal(cell, node) = a_nodeIdsGlobal(cell, node) - m_globalNodeIdOffsets[domainId()];
474 a_nodeIdsLocal(cell, node) = -1;
479 for(
MInt cell = 0; cell < a_noCells(); cell++) {
480 if(!c_isLeafCell(cell))
continue;
481 if(!a_isActive(cell))
continue;
482 for(
MInt node = 0; node < a_noNodes(cell); node++) {
483 if(a_nodeIdsLocal(cell, node) == -1) {
484 a_nodeIdsLocal(cell, node) =
485 (m_globalNodeIdOffsets[domainId() + 1] - m_globalNodeIdOffsets[domainId()]) + counter;
487 if(node < noVertices) {
488 for(
MInt dir = 0; dir < noVertices - 1; dir++) {
489 if(c_neighborId(cell, Fd::nghbrCellOfVertex(node, dir)) < 0)
continue;
490 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfVertex(node, dir));
491 if(a_nodeIdsLocal(nghbrId, Fd::vertexIdOfOppCell(node, dir)) > -1) {
492 cerr << a_nodeIdsLocal(nghbrId, Fd::vertexIdOfOppCell(node, dir)) <<
" OVERWRITTEN in REORDER" << endl;
494 a_nodeIdsLocal(nghbrId, Fd::vertexIdOfOppCell(node, dir)) = a_nodeIdsLocal(cell, node);
497 }
else if(node < (noVertices + noEdges * a_pRfnmnt(cell))) {
498 MInt pos = node - noVertices;
500 for(
MInt e = 0; e < noEdges; e++) {
501 if(e * a_pRfnmnt(cell) < pos) {
508 MInt point = pos - (edge * a_pRfnmnt(cell));
509 pos = noVertices + (edge * a_pRfnmnt(cell));
510 for(
MInt dir = 0; dir < 3; dir++) {
511 if(c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir)) < 0)
continue;
512 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir));
513 MInt oppositePos = noVertices + Fd::edgeIdOfOppCell(edge, dir) * a_pRfnmnt(cell);
514 if(a_nodeIdsLocal(nghbrId, oppositePos + point) > -1) {
515 cerr << a_nodeIdsLocal(nghbrId, oppositePos + point) <<
" OVERWRITTEN in REORDER" << endl;
517 a_nodeIdsLocal(nghbrId, oppositePos + point) = a_nodeIdsLocal(cell, pos + point);
520 }
else if(node < (noVertices + noEdges * a_pRfnmnt(cell) + noSurfaces * a_pRfnmnt(cell) * a_pRfnmnt(cell))) {
521 MInt pos = node - noVertices + noEdges * a_pRfnmnt(cell);
523 for(
MInt s = 0; s < noSurfaces; s++) {
524 if(s * a_pRfnmnt(cell) * a_pRfnmnt(cell) < pos) {
531 MInt point = pos - (surface * a_pRfnmnt(cell) * a_pRfnmnt(cell));
532 pos = noVertices + (noEdges * a_pRfnmnt(cell)) + (surface * a_pRfnmnt(cell) * a_pRfnmnt(cell));
533 if(c_neighborId(cell, Fd::nghbrCellOfSurface(surface)) < 0)
continue;
534 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfSurface(surface));
535 MInt oppositePos = noVertices + noEdges * a_pRfnmnt(cell)
536 + Fd::surfaceIdOfOppCell(surface) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
537 if(a_nodeIdsLocal(nghbrId, oppositePos + point) > -1) {
538 cerr << a_nodeIdsLocal(nghbrId, oppositePos + point) <<
" OVERWRITTEN in REORDER" << endl;
540 a_nodeIdsLocal(nghbrId, oppositePos + point) = a_nodeIdsLocal(cell, pos + point);
559 MInt noEdges = (nDim == 2) ? 0 : 12;
560 MInt noSurfaces = 2 * nDim;
563 MIntScratchSpace windowDataPerRank(noNeighborDomains(),
"windowDataPerRank", AT_);
564 MIntScratchSpace haloDataPerRank(noNeighborDomains(),
"haloDataPerRank", AT_);
565 MIntScratchSpace windowDataOffsets(noNeighborDomains() + 1,
"windowDataOffsets", AT_);
566 MIntScratchSpace haloDataOffsets(noNeighborDomains() + 1,
"haloDataOffsets", AT_);
567 windowDataPerRank.fill(0);
568 haloDataPerRank.fill(0);
569 windowDataOffsets.fill(0);
570 haloDataOffsets.fill(0);
573 MInt totalCounterWindow = 0;
574 MInt totalCounterHalo = 0;
575 for(
MInt n = 0; n < noNeighborDomains(); n++) {
576 MInt dataCounterWindow = 0;
577 MInt dataCounterHalo = 0;
578 for(
MInt w = 0; w < noWindowCells(n); w++) {
579 dataCounterWindow += a_noNodes(windowCell(n, w));
581 for(
MInt h = 0; h < noHaloCells(n); h++) {
582 dataCounterHalo += a_noNodes(haloCell(n, h));
584 windowDataPerRank(n) = dataCounterWindow;
585 haloDataPerRank(n) = dataCounterHalo;
586 totalCounterWindow += dataCounterWindow;
587 totalCounterHalo += dataCounterHalo;
588 windowDataOffsets(n + 1) = totalCounterWindow;
589 haloDataOffsets(n + 1) = totalCounterHalo;
594 MInt* receiveBuffers{};
595 MPI_Request* mpi_request{};
596 mAlloc(sendBuffers, totalCounterWindow,
"sendBuffers", 0, AT_);
597 mAlloc(receiveBuffers, totalCounterHalo,
"receiveBuffers", 0, AT_);
598 mAlloc(mpi_request, noNeighborDomains(),
"mpi_request", AT_);
601 if(domainId() == currentDomain) {
602 for(
MInt n = 0; n < noNeighborDomains(); n++) {
604 for(
MInt j = 0; j < noWindowCells(n); j++) {
605 for(
MInt node = 0; node < a_noNodes(windowCell(n, j)); node++) {
606 sendBuffers[windowDataOffsets(n) + cnt] = a_nodeIdsGlobal(windowCell(n, j), node);
613 for(
MInt n = 0; n < noNeighborDomains(); n++) {
614 MPI_Issend(&sendBuffers[windowDataOffsets(n)], windowDataPerRank(n), MPI_INT, neighborDomain(n), 0, mpiComm(),
615 &mpi_request[n], AT_,
"sendBuffers[n]");
621 for(
MInt n = 0; n < noNeighborDomains(); n++) {
622 if(currentDomain != neighborDomain(n))
continue;
623 MPI_Recv(&receiveBuffers[haloDataOffsets(n)], haloDataPerRank(n), MPI_INT, neighborDomain(n), 0, mpiComm(), &status,
624 AT_,
"receiveBuffers[n]");
626 if(domainId() == currentDomain) {
627 for(
MInt n = 0; n < noNeighborDomains(); n++) {
628 MPI_Wait(&mpi_request[n], &status, AT_);
633 for(
MInt n = 0; n < noNeighborDomains(); n++) {
634 if(currentDomain != neighborDomain(n))
continue;
636 for(
MInt j = 0; j < noHaloCells(n); j++) {
637 for(
MInt node = 0; node < a_noNodes(haloCell(n, j)); node++) {
639 if(receiveBuffers[haloDataOffsets(n) + cnt - 1] == -1)
continue;
640 if((a_nodeIdsGlobal(haloCell(n, j), node) > -1))
continue;
641 a_nodeIdsGlobal(haloCell(n, j), node) = receiveBuffers[haloDataOffsets(n) + cnt - 1];
644 if(node < noVertices) {
645 for(
MInt dir = 0; dir < noVertices - 1; dir++) {
646 if(c_neighborId(haloCell(n, j), Fd::nghbrCellOfVertex(node, dir)) < 0)
continue;
647 MInt nghbrId = c_neighborId(haloCell(n, j), Fd::nghbrCellOfVertex(node, dir));
648 if(a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(node, dir)) > -1) {
649 cerr << a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(node, dir)) <<
" OVERWRITTEN in EXCHANGE" << endl;
651 a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(node, dir)) = a_nodeIdsGlobal(haloCell(n, j), node);
654 }
else if(node < (noVertices + noEdges * a_pRfnmnt(haloCell(n, j)))) {
655 MInt pos = node - noVertices;
657 for(
MInt e = 0; e < noEdges; e++) {
658 if(e * a_pRfnmnt(haloCell(n, j)) < pos) {
665 MInt point = pos - (edge * a_pRfnmnt(haloCell(n, j)));
666 pos = noVertices + (edge * a_pRfnmnt(haloCell(n, j)));
667 for(
MInt dir = 0; dir < 3; dir++) {
668 if(c_neighborId(haloCell(n, j), Fd::nghbrCellOfEdge(edge, dir)) < 0)
continue;
669 MInt nghbrId = c_neighborId(haloCell(n, j), Fd::nghbrCellOfEdge(edge, dir));
670 MInt oppositePos = noVertices + Fd::edgeIdOfOppCell(edge, dir) * a_pRfnmnt(haloCell(n, j));
671 if(a_nodeIdsGlobal(nghbrId, oppositePos + point) > -1) {
672 cerr << a_nodeIdsGlobal(nghbrId, oppositePos + point) <<
" OVERWRITTEN in EXCHANGE" << endl;
674 a_nodeIdsGlobal(nghbrId, oppositePos + point) = a_nodeIdsGlobal(haloCell(n, j), pos + point);
677 }
else if(node < (noVertices + noEdges * a_pRfnmnt(haloCell(n, j))
678 + noSurfaces * a_pRfnmnt(haloCell(n, j)) * a_pRfnmnt(haloCell(n, j)))) {
679 MInt pos = node - noVertices + noEdges * a_pRfnmnt(haloCell(n, j));
681 for(
MInt s = 0; s < noSurfaces; s++) {
682 if(s * a_pRfnmnt(haloCell(n, j)) * a_pRfnmnt(haloCell(n, j)) < pos) {
689 MInt point = pos - (surface * a_pRfnmnt(haloCell(n, j)) * a_pRfnmnt(haloCell(n, j)));
690 pos = noVertices + (noEdges * a_pRfnmnt(haloCell(n, j)))
691 + (surface * a_pRfnmnt(haloCell(n, j)) * a_pRfnmnt(haloCell(n, j)));
692 if(c_neighborId(haloCell(n, j), Fd::nghbrCellOfSurface(surface)) < 0)
continue;
693 MInt nghbrId = c_neighborId(haloCell(n, j), Fd::nghbrCellOfSurface(surface));
694 MInt oppositePos = noVertices + noEdges * a_pRfnmnt(haloCell(n, j))
695 + Fd::surfaceIdOfOppCell(surface) * a_pRfnmnt(haloCell(n, j)) * a_pRfnmnt(haloCell(n, j));
696 if(a_nodeIdsGlobal(nghbrId, oppositePos + point) > -1) {
697 cerr << a_nodeIdsGlobal(nghbrId, oppositePos + point) <<
" OVERWRITTEN in EXCHANGE" << endl;
699 a_nodeIdsGlobal(nghbrId, oppositePos + point) = a_nodeIdsGlobal(haloCell(n, j), pos + point);
729 MInt noEdges = (nDim == 2) ? 0 : 12;
730 MInt noSurfaces = 2 * nDim;
732 for(
MInt cell = 0; cell < a_noCells(); cell++) {
733 if(!c_isLeafCell(cell))
continue;
734 if(!a_isActive(cell))
continue;
736 for(
MInt vertex = 0; vertex < noVertices; vertex++) {
737 if(a_nodeIdsGlobal(cell, vertex) == -1) {
739 MInt noDiffCandidates = 0;
740 for(
MInt dir = 0; dir < noVertices - 1; dir++) {
741 if(c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir)) < 0)
continue;
742 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir));
743 if(a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(vertex, dir)) > -1) {
744 if(globalId != a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(vertex, dir))) {
749 if(noDiffCandidates == 1) {
750 a_nodeIdsGlobal(cell, vertex) = globalId;
753 MInt id = a_nodeIdsGlobal(cell, vertex);
754 for(
MInt dir = 0; dir < noVertices - 1; dir++) {
755 if(c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir)) < 0)
continue;
756 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir));
757 if(a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(vertex, dir)) !=
id) {
758 stringstream errorMessage;
759 errorMessage <<
"INCONSISTENCY IN GLOBAL NODE ID FOR GLOBAL CELL ID " << c_globalId(cell) << endl;
760 mTerm(1, AT_, errorMessage.str());
766 for(
MInt edge = 0; edge < noEdges; edge++) {
767 MInt pos = noVertices + edge * a_pRfnmnt(cell);
768 for(
MInt points = 0; points < a_pRfnmnt(cell); points++) {
769 if(a_nodeIdsGlobal(cell, pos + points) == -1) {
771 MInt noDiffCandidates = 0;
772 for(
MInt dir = 0; dir < 3; dir++) {
773 if(c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir)) < 0)
continue;
774 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir));
775 MInt oppositePos = noVertices + Fd::edgeIdOfOppCell(edge, dir) * a_pRfnmnt(cell);
776 if(a_nodeIdsGlobal(nghbrId, oppositePos + points) > -1) {
777 if(globalId != a_nodeIdsGlobal(nghbrId, oppositePos + points)) {
782 if(noDiffCandidates == 1) {
783 a_nodeIdsGlobal(cell, pos + points) = globalId;
786 MInt id = a_nodeIdsGlobal(cell, pos + points);
787 for(
MInt dir = 0; dir < 3; dir++) {
788 if(c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir)) < 0)
continue;
789 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir));
790 MInt oppositePos = noVertices + Fd::edgeIdOfOppCell(edge, dir) * a_pRfnmnt(cell);
791 if(a_nodeIdsGlobal(nghbrId, oppositePos + points) !=
id) {
792 stringstream errorMessage;
793 errorMessage <<
"INCONSISTENCY IN GLOBAL NODE ID FOR GLOBAL CELL ID " << c_globalId(cell) << endl;
794 mTerm(1, AT_, errorMessage.str());
801 for(
MInt surface = 0; surface < noSurfaces; surface++) {
802 MInt pos = noVertices + noEdges * a_pRfnmnt(cell) + surface * a_pRfnmnt(cell) * a_pRfnmnt(cell);
803 for(
MInt points = 0; points < a_pRfnmnt(cell) * a_pRfnmnt(cell); points++) {
804 if(a_nodeIdsGlobal(cell, pos + points) == -1) {
806 if(c_neighborId(cell, Fd::nghbrCellOfSurface(surface)) < 0)
continue;
807 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfSurface(surface));
808 MInt oppositePos = noVertices + noEdges * a_pRfnmnt(cell)
809 + Fd::surfaceIdOfOppCell(surface) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
810 if(globalId != a_nodeIdsGlobal(nghbrId, oppositePos + points)) {
811 a_nodeIdsGlobal(cell, pos + points) = globalId;
814 MInt id = a_nodeIdsGlobal(cell, pos + points);
815 if(c_neighborId(cell, Fd::nghbrCellOfSurface(surface)) < 0)
continue;
816 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfSurface(surface));
817 MInt oppositePos = noVertices + noEdges * a_pRfnmnt(cell)
818 + Fd::surfaceIdOfOppCell(surface) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
819 if(a_nodeIdsGlobal(nghbrId, oppositePos + points) !=
id) {
820 stringstream errorMessage;
821 errorMessage <<
"INCONSISTENCY IN GLOBAL NODE ID FOR GLOBAL CELL ID " << c_globalId(cell) << endl;
822 mTerm(1, AT_, errorMessage.str());
843 MIntScratchSpace windowDataPerRank(noNeighborDomains(),
"windowDataPerRank", AT_);
844 MIntScratchSpace haloDataPerRank(noNeighborDomains(),
"haloDataPerRank", AT_);
845 MIntScratchSpace windowDataOffsets(noNeighborDomains() + 1,
"windowDataOffsets", AT_);
846 MIntScratchSpace haloDataOffsets(noNeighborDomains() + 1,
"haloDataOffsets", AT_);
847 windowDataPerRank.fill(0);
848 haloDataPerRank.fill(0);
849 windowDataOffsets.fill(0);
850 haloDataOffsets.fill(0);
853 MInt totalCounterWindow = 0;
854 MInt totalCounterHalo = 0;
855 for(
MInt n = 0; n < noNeighborDomains(); n++) {
856 MInt dataCounterWindow = 0;
857 MInt dataCounterHalo = 0;
858 for(
MInt w = 0; w < noWindowCells(n); w++) {
859 dataCounterWindow += a_noNodes(windowCell(n, w));
861 for(
MInt h = 0; h < noHaloCells(n); h++) {
862 dataCounterHalo += a_noNodes(haloCell(n, h));
864 windowDataPerRank(n) = dataCounterWindow;
865 haloDataPerRank(n) = dataCounterHalo;
866 totalCounterWindow += dataCounterWindow;
867 totalCounterHalo += dataCounterHalo;
868 windowDataOffsets(n + 1) = totalCounterWindow;
869 haloDataOffsets(n + 1) = totalCounterHalo;
874 MInt* receiveBuffers{};
875 MPI_Request* mpi_request{};
876 mAlloc(sendBuffers, totalCounterWindow,
"sendBuffers", 0, AT_);
877 mAlloc(receiveBuffers, totalCounterHalo,
"receiveBuffers", 0, AT_);
878 mAlloc(mpi_request, noNeighborDomains(),
"mpi_request", AT_);
881 for(
MInt n = 0; n < noNeighborDomains(); n++) {
883 for(
MInt j = 0; j < noWindowCells(n); j++) {
884 for(
MInt node = 0; node < a_noNodes(windowCell(n, j)); node++) {
885 sendBuffers[windowDataOffsets(n) + cnt] = a_nodeIdsGlobal(windowCell(n, j), node);
892 for(
MInt n = 0; n < noNeighborDomains(); n++) {
893 MPI_Issend(&sendBuffers[windowDataOffsets(n)], windowDataPerRank(n), MPI_INT, neighborDomain(n), 0, mpiComm(),
894 &mpi_request[n], AT_,
"sendBuffers[n]");
899 for(
MInt n = 0; n < noNeighborDomains(); n++) {
900 MPI_Recv(&receiveBuffers[haloDataOffsets(n)], haloDataPerRank(n), MPI_INT, neighborDomain(n), 0, mpiComm(), &status,
901 AT_,
"receiveBuffers[n]");
903 for(
MInt n = 0; n < noNeighborDomains(); n++) {
904 MPI_Wait(&mpi_request[n], &status, AT_);
908 for(
MInt n = 0; n < noNeighborDomains(); n++) {
910 for(
MInt j = 0; j < noHaloCells(n); j++) {
911 for(
MInt node = 0; node < a_noNodes(haloCell(n, j)); node++) {
913 if(a_nodeIdsGlobal(haloCell(n, j), node) != receiveBuffers[haloDataOffsets(n) + cnt - 1]) {
914 stringstream errorMessage;
915 errorMessage <<
"INCONSISTENCY IN GLOBAL NODE ID FOR GLOBAL CELL ID " << c_globalId(haloCell(n, j)) << endl;
916 mTerm(1, AT_, errorMessage.str());
946 MInt noEdges = (nDim == 2) ? 0 : 12;
947 MInt noSurfaces = 2 * nDim;
949 for(
MInt cell = 0; cell < a_noCells(); cell++) {
950 if(a_isHalo(cell))
continue;
951 if(!c_isLeafCell(cell))
continue;
952 if(!a_isActive(cell))
continue;
954 for(
MInt vertex = 0; vertex < noVertices; vertex++) {
955 if(a_nodeIdsGlobal(cell, vertex) == -1) {
956 a_nodeIdsGlobal(cell, vertex) = m_totalNoNodesGlobal;
957 m_totalNoNodesGlobal++;
959 for(
MInt dir = 0; dir < noVertices - 1; dir++) {
960 if(c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir)) < 0)
continue;
961 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir));
962 a_nodeIdsGlobal(nghbrId, Fd::vertexIdOfOppCell(vertex, dir)) = a_nodeIdsGlobal(cell, vertex);
967 for(
MInt edge = 0; edge < noEdges; edge++) {
968 MInt pos = noVertices + edge * a_pRfnmnt(cell);
969 for(
MInt points = 0; points < a_pRfnmnt(cell); points++) {
970 if(a_nodeIdsGlobal(cell, pos + points) == -1) {
971 a_nodeIdsGlobal(cell, pos + points) = m_totalNoNodesGlobal;
972 m_totalNoNodesGlobal++;
976 for(
MInt dir = 0; dir < 3; dir++) {
977 if(c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir)) < 0)
continue;
978 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir));
979 MInt oppositePos = noVertices + Fd::edgeIdOfOppCell(edge, dir) * a_pRfnmnt(cell);
980 for(
MInt points = 0; points < a_pRfnmnt(cell); points++) {
981 a_nodeIdsGlobal(nghbrId, oppositePos + points) = a_nodeIdsGlobal(cell, pos + points);
986 for(
MInt surface = 0; surface < noSurfaces; surface++) {
987 MInt pos = noVertices + noEdges * a_pRfnmnt(cell) + surface * a_pRfnmnt(cell) * a_pRfnmnt(cell);
988 for(
MInt points = 0; points < a_pRfnmnt(cell) * a_pRfnmnt(cell); points++) {
989 if(a_nodeIdsGlobal(cell, pos + points) == -1) {
990 a_nodeIdsGlobal(cell, pos + points) = m_totalNoNodesGlobal;
991 m_totalNoNodesGlobal++;
995 if(c_neighborId(cell, Fd::nghbrCellOfSurface(surface)) < 0)
continue;
996 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfSurface(surface));
998 noVertices + noEdges * a_pRfnmnt(cell) + Fd::surfaceIdOfOppCell(surface) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
999 for(
MInt points = 0; points < a_pRfnmnt(cell) * a_pRfnmnt(cell); points++) {
1000 a_nodeIdsGlobal(nghbrId, oppositePos + points) = a_nodeIdsGlobal(cell, pos + points);
1004 MInt noInnerNodes = a_pRfnmnt(cell) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
1005 for(
MInt innerNodes = 0; innerNodes < noInnerNodes; innerNodes++) {
1006 MInt pos = noVertices + noEdges * a_pRfnmnt(cell) + noSurfaces * a_pRfnmnt(cell) * a_pRfnmnt(cell) + innerNodes;
1007 if(a_nodeIdsGlobal(cell, pos) == -1) {
1008 a_nodeIdsGlobal(cell, pos) = m_totalNoNodesGlobal;
1009 m_totalNoNodesGlobal++;
1033 for(
MInt cell = 0; cell < a_noCells(); cell++) {
1034 for(
MInt node = 0; node < a_noNodes(cell); node++) {
1035 a_nodeIdsLocal(cell, node) = -1;
1036 a_nodeIdsGlobal(cell, node) = -1;
1046 MInt noEdges = (nDim == 2) ? 0 : 12;
1047 MInt noSurfaces = 2 * nDim;
1048 MInt innerCounter = 0;
1049 MInt surfaceCounter = 0;
1050 MInt edgeCounter = 0;
1051 MInt vertexCounter = 0;
1053 for(
MInt cell = 0; cell < a_noCells(); cell++) {
1054 if(!c_isLeafCell(cell))
continue;
1055 if(!a_isActive(cell))
continue;
1057 for(
MInt vertex = 0; vertex < noVertices; vertex++) {
1058 if(a_nodeIdsLocal(cell, vertex) == -1) {
1059 a_nodeIdsLocal(cell, vertex) = m_totalNoNodes;
1063 for(
MInt dir = 0; dir < noVertices - 1; dir++) {
1064 if(c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir)) < 0)
continue;
1065 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfVertex(vertex, dir));
1066 a_nodeIdsLocal(nghbrId, Fd::vertexIdOfOppCell(vertex, dir)) = a_nodeIdsLocal(cell, vertex);
1071 for(
MInt edge = 0; edge < noEdges; edge++) {
1072 MInt pos = noVertices + edge * a_pRfnmnt(cell);
1073 for(
MInt points = 0; points < a_pRfnmnt(cell); points++) {
1074 if(a_nodeIdsLocal(cell, pos + points) == -1) {
1075 a_nodeIdsLocal(cell, pos + points) = m_totalNoNodes;
1081 for(
MInt dir = 0; dir < 3; dir++) {
1082 if(c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir)) < 0)
continue;
1083 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfEdge(edge, dir));
1084 MInt oppositePos = noVertices + Fd::edgeIdOfOppCell(edge, dir) * a_pRfnmnt(cell);
1085 for(
MInt points = 0; points < a_pRfnmnt(cell); points++) {
1086 a_nodeIdsLocal(nghbrId, oppositePos + points) = a_nodeIdsLocal(cell, pos + points);
1091 for(
MInt surface = 0; surface < noSurfaces; surface++) {
1092 MInt pos = noVertices + noEdges * a_pRfnmnt(cell) + surface * a_pRfnmnt(cell) * a_pRfnmnt(cell);
1093 for(
MInt points = 0; points < a_pRfnmnt(cell) * a_pRfnmnt(cell); points++) {
1094 if(a_nodeIdsLocal(cell, pos + points) == -1) {
1095 a_nodeIdsLocal(cell, pos + points) = m_totalNoNodes;
1101 if(c_neighborId(cell, Fd::nghbrCellOfSurface(surface)) < 0)
continue;
1102 MInt nghbrId = c_neighborId(cell, Fd::nghbrCellOfSurface(surface));
1104 noVertices + noEdges * a_pRfnmnt(cell) + Fd::surfaceIdOfOppCell(surface) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
1105 for(
MInt points = 0; points < a_pRfnmnt(cell) * a_pRfnmnt(cell); points++) {
1106 a_nodeIdsLocal(nghbrId, oppositePos + points) = a_nodeIdsLocal(cell, pos + points);
1110 MInt noInnerNodes = a_pRfnmnt(cell) * a_pRfnmnt(cell) * a_pRfnmnt(cell);
1111 for(
MInt innerNodes = 0; innerNodes < noInnerNodes; innerNodes++) {
1112 MInt pos = noVertices + noEdges * a_pRfnmnt(cell) + noSurfaces * a_pRfnmnt(cell) * a_pRfnmnt(cell) + innerNodes;
1113 if(a_nodeIdsLocal(cell, pos) == -1) {
1114 a_nodeIdsLocal(cell, pos) = m_totalNoNodes;
1121 cout <<
"Number of Nodes on cell vertices (no vertices per cell: " << noVertices <<
"): " << vertexCounter << endl;
1122 cout <<
"Number of Nodes on cell edges (no edges per cell: " << noEdges <<
") : " << edgeCounter << endl;
1123 cout <<
"Number of Nodes on cell surfaces (no surfaces per cell: " << noSurfaces <<
"): " << surfaceCounter << endl;
1124 cout <<
"Number of Nodes within the cells : " << innerCounter << endl;
1125 cout <<
"Number of Nodes total : " << m_totalNoNodes << endl;
1126 cout <<
"Number of Cells total without halo cells (on domain " << domainId() <<
") : " << grid().noInternalCells()
1128 cout <<
"Number of Cells total with halo cells (on domain " << domainId() <<
") : " << a_noCells() << endl;
1130 m_log <<
"Number of Nodes on cell vertices (no vertices per cell: " << noVertices <<
"): " << vertexCounter << endl;
1131 m_log <<
"Number of Nodes on cell edges (no edges per cell: " << noEdges <<
") : " << edgeCounter << endl;
1132 m_log <<
"Number of Nodes on cell surfaces (no surfaces per cell: " << noSurfaces <<
"): " << surfaceCounter << endl;
1133 m_log <<
"Number of Nodes within the cells : " << innerCounter << endl;
1134 m_log <<
"Number of Nodes total : " << m_totalNoNodes << endl;
1150 const MFloat cellHalfLength = c_cellLengthAtCell(pCellId) * F1B2;
1152 for(
MInt d = 0; d < nDim; d++) {
1153 x[d] = c_coordinate(pCellId, d) + z[d] * cellHalfLength;
1166 const MFloat* subCellCoord) {
1169 const MFloat cellHalfLength = c_cellLengthAtCell(pCellId) *
FFPOW2(subCellLevel + 1);
1171 for(
MInt d = 0; d < nDim; d++) {
1172 x[d] = subCellCoord[d] + z[d] * cellHalfLength;
1187 const MFloat F1BcellHalfLength = F1 / (c_cellLengthAtCell(pCellId) * F1B2);
1189 for(
MInt d = 0; d < nDim; d++) {
1190 z[d] = (x[d] - c_coordinate(pCellId, d)) * F1BcellHalfLength;
1207 for(
MInt cell = 0; cell < a_noCells(); cell++) {
1208 const MInt pCellId = cell;
1210 if(!a_isActive(pCellId)) {
1211 for(
MInt d = 0; d < nDim; d++) {
1212 a_elementDispl(pCellId, d) = F0;
1217 std::array<MFloat, nDim> z{};
1219 getDisplacementsAtPoint(pCellId, z.data(), m_totalNodalDisplacements, &a_elementDispl(pCellId, 0));
1232 getDisplacementInterpolationMatrix(cellId, z, L_coef);
1234 if(m_testRun && m_polyDeg < 1) getDisplacementInterpolationMatrixDebug(cellId, z, L_coef);
1238 for(
MInt dim = 0; dim < nDim; dim++) {
1239 MFloat displacement = F0;
1240 for(
MInt node = 0; node < a_noNodes(cellId); node++) {
1241 for(
MInt d = 0; d < nDim; d++) {
1242 MInt nodeId = a_nodeIdsLocal(cellId, node);
1243 displacement += L_coef(dim, node * nDim + d) * displ[nodeId * nDim + d];
1246 result[dim] = displacement;
1262 for(
MInt cell = 0; cell < a_noCells(); cell++) {
1263 if(!a_isActive(cell))
continue;
1268 getStrainsAtPoint(cell, z, m_totalNodalDisplacements, &a_elementStrains(cell, 0));
1277 getStrainInterpolationMatrix(Be, cellId, z);
1281 for(
MInt d1 = 0; d1 < m_noStrains; d1++) {
1283 for(
MInt node = 0; node < a_noNodes(cellId); node++) {
1284 MInt nodeId = a_nodeIdsLocal(cellId, node);
1285 for(
MInt d2 = 0; d2 < nDim; d2++) {
1286 strain += Be(d1, node * nDim + d2) * displ[nodeId * nDim + d2];
1289 strains[d1] = strain;
1305 for(
MInt cell = 0; cell < a_noCells(); cell++) {
1306 if(!a_isActive(cell))
continue;
1308 std::array<MFloat, nDim> z{};
1309 getStressesAtPoint(cell, z.data(), m_totalNodalDisplacements, &a_elementStresses(cell, 0));
1319 std::array<MFloat, m_noStrains> strains{};
1320 getStrainsAtPoint(cellId, z, displ, strains.data());
1323 getMaterialTensor(C, cellId);
1324 for(
MInt d1 = 0; d1 < m_noStrains; d1++) {
1326 for(
MInt d2 = 0; d2 < m_noStrains; d2++) {
1327 const MFloat strain = strains[d2];
1328 stress += C(d2, d1) * strain;
1330 stresses[d1] = stress;
1351 const MInt p = a_pRfnmnt(pCellId);
1356 MInt noEdges = (nDim == 2) ? 0 : 12;
1357 MInt noSurfaces = (nDim == 2) ? 4 : 6;
1360 for(
MInt d = 0; d < nDim; d++) {
1361 for(
MInt i = 0; i <
p + 2; i++) {
1369 for(
MInt d = 0; d < nDim; d++) {
1370 for(
MInt i = 0; i <
p + 2; i++) {
1371 for(
MInt j = 0; j <
p + 2; j++) {
1372 if(i == j)
continue;
1373 L(d, i) *= (z[d] - a_nodePosition(pCellId, j)) / (a_nodePosition(pCellId, i) - a_nodePosition(pCellId, j));
1382 for(
MInt dim = 0; dim < nDim; dim++) {
1383 for(
MInt node = 0; node < a_noNodes(pCellId); node++) {
1385 if(node < noVertices) {
1386 for(
MInt d = 0; d < nDim; d++) {
1388 L_coef(dim, node * nDim + d) = F1;
1390 L_coef(dim, node * nDim + d) = F0;
1392 for(
MInt d2 = 0; d2 < nDim; d2++) {
1394 if(Fd::vertexPosition(node, d2) < F0) {
1399 L_coef(dim, node * nDim + d) *= L(d2, pos);
1403 }
else if(node < noVertices + noEdges * p) {
1405 MInt edge = (
MInt)floor((node - noVertices) /
p);
1407 MInt l = (node - noVertices) % p;
1408 for(
MInt d = 0; d < nDim; d++) {
1410 L_coef(dim, node * nDim + d) = F1;
1412 L_coef(dim, node * nDim + d) = F0;
1414 for(
MInt d2 = 0; d2 < nDim; d2++) {
1416 if(Fd::edgePosition(edge, d2) < F0) {
1418 }
else if(Fd::edgePosition(edge, d2) > F0) {
1423 L_coef(dim, node * nDim + d) *= L(d2, pos);
1427 }
else if(node < noVertices + noEdges * p + noSurfaces * p * p) {
1429 MInt surface = (
MInt)floor((node - noVertices - noEdges * p) / (
p *
p));
1432 l[1] = (node - noVertices - noEdges *
p) % (p * p);
1437 for(
MInt d = 0; d < nDim; d++) {
1439 L_coef(dim, node * nDim + d) = F1;
1441 L_coef(dim, node * nDim + d) = F0;
1444 for(
MInt d2 = 0; d2 < nDim; d2++) {
1446 if(Fd::surfacePosition(surface, d2) < F0) {
1448 }
else if(Fd::surfacePosition(surface, d2) > F0) {
1451 pos = l[counter] + 1;
1454 L_coef(dim, node * nDim + d) *= L(d2, pos);
1461 l[2] = node - noVertices - noEdges *
p - noSurfaces *
p *
p;
1462 while(l[2] >= (p * p)) {
1470 for(
MInt d = 0; d < nDim; d++) {
1472 L_coef(dim, node * nDim + d) = F1;
1474 L_coef(dim, node * nDim + d) = F0;
1477 for(
MInt d2 = 0; d2 < nDim; d2++) {
1478 MInt pos = l[counter] + 1;
1480 L_coef(dim, node * nDim + d) *= L(d2, pos);
1506 const MInt p = a_pRfnmnt(pCellId);
1512 MInt noEdges = (nDim == 2) ? 0 : 12;
1513 MInt noSurfaces = (nDim == 2) ? 4 : 6;
1516 for(
MInt d = 0; d < nDim; d++) {
1517 for(
MInt i = 0; i <
p + 2; i++) {
1526 for(
MInt d = 0; d < nDim; d++) {
1527 for(
MInt i = 0; i <
p + 2; i++) {
1528 for(
MInt j = 0; j <
p + 2; j++) {
1529 if(i == j)
continue;
1530 L(d, i) *= (z[d] - a_nodePosition(pCellId, j)) / (a_nodePosition(pCellId, i) - a_nodePosition(pCellId, j));
1531 MFloat L_p = (F1 / (a_nodePosition(pCellId, i) - a_nodePosition(pCellId, j)));
1532 for(
MInt l = 0; l <
p + 2; l++) {
1533 if(l == i || l == j)
continue;
1534 L_p *= (z[d] - a_nodePosition(pCellId, l)) / (a_nodePosition(pCellId, i) - a_nodePosition(pCellId, l));
1536 L_deriv(d, i) += L_p;
1545 for(
MInt node = 0; node < a_noNodes(pCellId); node++) {
1547 if(node < noVertices) {
1548 for(
MInt dir = 0; dir < nDim; dir++) {
1549 for(
MInt d = 0; d < nDim; d++) {
1553 if(Fd::vertexPosition(node, d) < F0) {
1559 L_prime(node, dir) *= L_deriv(d, pos);
1561 L_prime(node, dir) *= L(d, pos);
1566 }
else if(node < noVertices + noEdges * p) {
1568 MInt edge = (
MInt)floor((node - noVertices) /
p);
1570 MInt l = (node - noVertices) % p;
1571 for(
MInt dir = 0; dir < nDim; dir++) {
1572 for(
MInt d = 0; d < nDim; d++) {
1574 if(Fd::edgePosition(edge, d) < F0) {
1576 }
else if(Fd::edgePosition(edge, d) > F0) {
1582 L_prime(node, dir) *= L_deriv(d, pos);
1584 L_prime(node, dir) *= L(d, pos);
1589 }
else if(node < noVertices + noEdges * p + noSurfaces * p * p) {
1591 MInt surface = (
MInt)floor((node - noVertices - noEdges * p) / (
p *
p));
1594 l[1] = (node - noVertices - noEdges *
p) % (p * p);
1599 for(
MInt dir = 0; dir < nDim; dir++) {
1601 for(
MInt d = 0; d < nDim; d++) {
1603 if(Fd::surfacePosition(surface, d) < F0) {
1605 }
else if(Fd::surfacePosition(surface, d) > F0) {
1608 pos = l[counter] + 1;
1612 L_prime(node, dir) *= L_deriv(d, pos);
1614 L_prime(node, dir) *= L(d, pos);
1622 l[2] = node - noVertices - noEdges *
p - noSurfaces *
p *
p;
1623 while(l[2] >= (p * p)) {
1631 for(
MInt dir = 0; dir < nDim; dir++) {
1633 for(
MInt d = 0; d < nDim; d++) {
1634 MInt pos = l[counter] + 1;
1637 L_prime(node, dir) *= L_deriv(d, pos);
1639 L_prime(node, dir) *= L(d, pos);
1667 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
1668 for(
MInt d = 0; d < nDim; d++) {
1670 L_mul_Xinverse(n, d) = F0;
1673 getDerivativeOfDisplacementInterpolationMatrix(pCellId, z, L_prime);
1677 for(
MInt d1 = 0; d1 < nDim; d1++) {
1678 for(
MInt d2 = 0; d2 < nDim; d2++) {
1680 X_inverse(d2 + d1 * nDim) = a_invJacobian(pCellId);
1682 X_inverse(d2 + d1 * nDim) = F0;
1686 if(m_testRun && m_polyDeg < 1) getJacobiMatrixDebug(pCellId, z, X_inverse);
1689 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
1690 for(
MInt d1 = 0; d1 < nDim; d1++) {
1691 for(
MInt d2 = 0; d2 < nDim; d2++) {
1692 L_mul_Xinverse(n, d1) += L_prime(n, d2) * X_inverse(d2 + d1 * nDim);
1698 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
1699 for(
MInt d1 = 0; d1 < nDim; d1++) {
1700 for(
MInt d2 = 0; d2 < nDim; d2++) {
1702 Be(d2, n * nDim + d1) = L_mul_Xinverse(n, d2);
1704 Be(d2, n * nDim + d1) = F0;
1708 MInt pos = ((d1 + 1) < nDim) ? (d1 + 1) : (d1 - 1);
1709 Be(nDim, n * nDim + d1) = L_mul_Xinverse(n, pos);
1711 for(
MInt d2 = 0; d2 < nDim; d2++) {
1712 MInt d3 = ((d2 + 1) < nDim) ? (d2 + 1) : 0;
1713 MInt d4 = ((d1 + 1) < nDim) ? (d1 + 1) : 0;
1715 Be(d2 + nDim, n * nDim + d1) = L_mul_Xinverse(n, d3);
1716 }
else if(d2 == d4) {
1717 Be(d2 + nDim, n * nDim + d1) = F0;
1719 Be(d2 + nDim, n * nDim + d1) = L_mul_Xinverse(n, d2);
1725 if(m_testRun && m_polyDeg < 1) getStrainInterpolationMatrixDebug(pCellId, z, Be);
1741 const MFloat nu = a_poissonRatio(pCellId);
1742 const MFloat c1 = m_E * (F1 - nu) / ((F1 + nu) * (F1 - F2 * nu));
1743 const MFloat c2 = m_E * nu / ((F1 + nu) * (F1 - F2 * nu));
1744 const MFloat c3 = m_E / (F2 * (F1 + nu));
1745 if(m_first && m_testRun) {
1746 cout <<
"///////////////////////////////////////////////////////////////" << endl;
1747 cout <<
"///////////////////////////////////////////////////////////////" << endl;
1749 cout <<
"MATERIAL PROPERTIES: " << endl;
1751 cout <<
"E-Modul E = " << m_E << endl;
1752 cout <<
"Poisson Ratio nu = " << nu << endl;
1753 cout <<
"c1 = E * (F1 - nu) / ((F1 + nu) * (F1 - F2 * nu)) = " << c1 << endl;
1754 cout <<
"c2 = E * nu / ((F1 + nu) * (F1 - F2 * nu)) = " << c2 << endl;
1755 cout <<
"c3 = E / (F2 * (F1 + nu)) = " << c3 << endl;
1757 m_log <<
"///////////////////////////////////////////////////////////////" << endl;
1758 m_log <<
"///////////////////////////////////////////////////////////////" << endl;
1760 m_log <<
"MATERIAL PROPERTIES: " << fixed << setprecision(5) << endl;
1762 m_log <<
"E-Modul E = " << m_E << endl;
1763 m_log <<
"Poisson Ratio nu = " << nu << endl;
1764 m_log <<
"c1 = E * (F1 - nu) / ((F1 + nu) * (F1 - F2 * nu)) = " << c1 << endl;
1765 m_log <<
"c2 = E * nu / ((F1 + nu) * (F1 - F2 * nu)) = " << c2 << endl;
1766 m_log <<
"c3 = E / (F2 * (F1 + nu)) = " << c3 << endl;
1770 for(
MInt dirA = 0; dirA < m_noStrains; dirA++) {
1771 for(
MInt dirB = 0; dirB < m_noStrains; dirB++) {
1775 for(
MInt dirA = 0; dirA < nDim; dirA++) {
1776 for(
MInt dirB = 0; dirB < nDim; dirB++) {
1777 C(dirA, dirB) = (dirA == dirB) ? c1 : c2;
1780 for(
MInt dirA = nDim; dirA < m_noStrains; dirA++) {
1781 for(
MInt dirB = nDim; dirB < m_noStrains; dirB++) {
1782 C(dirA, dirB) = (dirA == dirB) ? c3 : F0;
1785 if(m_first && m_testRun) {
1786 cout <<
"Material tensor: " << endl;
1787 m_log <<
"Material tensor: " << endl;
1788 for(
MInt dirA = 0; dirA < m_noStrains; dirA++) {
1789 for(
MInt dirB = 0; dirB < m_noStrains; dirB++) {
1790 cout << C(dirA, dirB) <<
"\t\t\t";
1791 m_log << C(dirA, dirB) <<
"\t\t\t";
1803 std::array<MFloat, nDim> coordA{};
1804 getCoordinatesOfNode(node, pCellId, coordA.data());
1805 const MInt nodeIdA = a_nodeIdsLocal(pCellId, node);
1807 for(
MInt nodeB = node + 1; nodeB < a_noNodes(pCellId); nodeB++) {
1808 const MInt nodeIdB = a_nodeIdsLocal(pCellId, nodeB);
1811 std::array<MFloat, nDim> coordB{};
1812 getCoordinatesOfNode(nodeB, pCellId, coordB.data());
1813 std::array<MFloat, nDim> diff{};
1814 for(
MInt d = 0; d < nDim; d++) {
1815 diff[d] = coordB[d] - coordA[d];
1817 const MFloat LSq = std::inner_product(&diff[0], &diff[nDim], &diff[0], .0);
1818 const MFloat L = sqrt(LSq);
1819 const MFloat pre = E * A / (L * L * L);
1820 std::array<MFloat, 2 * nDim> c{};
1821 std::array<MInt, 2 * nDim> gGlobal{};
1822 std::array<MInt, 2 * nDim> gLocal{};
1823 std::array<MFloat, 2 * nDim> sign{};
1824 for(
MInt d = 0; d < nDim; d++) {
1825 gGlobal[d] = nodeIdA * nDim + d;
1826 gLocal[d] = node * nDim + d;
1830 for(
MInt d = nDim; d < 2 * nDim; d++) {
1831 gGlobal[d] = nodeIdB * nDim + (d - nDim);
1832 gLocal[d] = nodeB * nDim + (d - nDim);
1833 c[d] = diff[d - nDim];
1836 for(
MInt n1 = 0; n1 < m_noStrains; n1++) {
1837 for(
MInt n2 = 0; n2 < m_noStrains; n2++) {
1838 const MFloat disA = m_totalNodalDisplacements[gGlobal[n1]];
1839 const MFloat disB = m_totalNodalDisplacements[gGlobal[n2]];
1840 const MInt nA = gLocal[n1];
1841 const MInt nB = gLocal[n2];
1842 C(nA, nB) += pre * (F1 + F1B2 * (disA - disB)) * c[n1] * c[n2] * sign[n1] * sign[n2];
1849 stringstream errorMessage;
1850 errorMessage <<
"Error!!! Solver method not implemented." << endl;
1851 mTerm(1, AT_, errorMessage.str());
1867 const MInt subCellLevel) {
1870 for(
MInt d1 = 0; d1 < nDim * a_noNodes(pCellId); d1++) {
1871 for(
MInt d2 = 0; d2 < nDim * a_noNodes(pCellId); d2++) {
1876 if(solverMethod() ==
"MAIA_NONLINEAR_BAR") {
1877 getMaterialTensor(Ke, pCellId, node);
1881 MFloatScratchSpace BeT_mul_C(nDim * a_noNodes(pCellId), m_noStrains, AT_,
"BeT_mul_C");
1885 getMaterialTensor(C, pCellId, node);
1888 getStrainInterpolationMatrix(Be, pCellId, z);
1889 for(
MInt d = 0; d < m_noStrains; d++) {
1890 for(
MInt e = 0; e < a_noNodes(pCellId) * nDim; e++) {
1891 BeT(e, d) = Be(d, e);
1897 for(
MInt d = 0; d < nDim; d++) {
1898 weight *= m_gaussWeights[a_pRfnmnt(pCellId)][nodePos[d]];
1905 for(
MInt d1 = 0; d1 < m_noStrains; d1++) {
1906 for(
MInt d2 = 0; d2 < m_noStrains; d2++) {
1911 if(m_testRun && subCellLevel < 1) {
1912 cout <<
"Strain-Interpolation-Matrix B^T_e at this point:" << endl;
1913 for(
MInt e = 0; e < a_noNodes(pCellId) * nDim; e++) {
1914 for(
MInt d = 0; d < m_noStrains; d++) {
1915 cout << BeT(e, d) <<
" ";
1920 cout <<
"Material tensor multiplied with the determinant " <<
determinant <<
" and the integration weights w "
1921 << weight <<
" and alpha " << alpha <<
":" << endl;
1922 for(
MInt d1 = 0; d1 < m_noStrains; d1++) {
1923 for(
MInt d2 = 0; d2 < m_noStrains; d2++) {
1924 cout << C(d1, d2) <<
" ";
1929 cout <<
"Strain-Interpolation-Matrix B_e at this point:" << endl;
1930 for(
MInt d = 0; d < m_noStrains; d++) {
1931 for(
MInt e = 0; e < a_noNodes(pCellId) * nDim; e++) {
1932 cout << Be(d, e) <<
" ";
1943 nDim * a_noNodes(pCellId));
1945 if(m_testRun && subCellLevel < 1) {
1946 cout <<
"Intermediate result, B^T_e * C * B_e * det(X_,z) * w:" << endl;
1947 for(
MInt d = 0; d < a_noNodes(pCellId) * nDim; d++) {
1948 for(
MInt e = 0; e < a_noNodes(pCellId) * nDim; e++) {
1949 cout << Ke(d, e) <<
" ";
1954 cout <<
"---------------------------------------" << endl;
1968 const MInt subCellLevel,
const MFloat* subCellCoord) {
1971 MInt nodePos[nDim] = {0};
1974 for(
MInt d = 0; d < nDim; d++) {
1978 if(subCellLevel < 1 && m_testRun) {
1980 cout <<
"The Element-Stiffness-Matrix is calculated " << endl;
1981 cout <<
"by adding together the resulting matrices of the product " << endl;
1983 cout <<
"B^T_e(z) * C(z) * B_e(z) * det(X_,z(z))" << endl;
1985 cout <<
"calculated at each of the following integration points z:" << endl;
1987 cout <<
"---------------------------------------" << endl;
1991 for(
MInt node = 0; node < a_noNodes(node); node++) {
1992 MFloatScratchSpace Mat_part(a_noNodes(pCellId) * nDim, a_noNodes(pCellId) * nDim, AT_,
"Mat_part");
1994 const MInt nodesPerDir = a_pRfnmnt(pCellId) + 2;
1995 Fd::nodePosition(node, nodesPerDir, nodePos);
1997 for(
MInt d = 0; d < nDim; d++) {
1998 z[d] = m_gaussPoints[a_pRfnmnt(pCellId)][nodePos[d]];
2001 if(subCellLevel > 0) {
2002 std::array<MFloat, nDim> point{};
2003 interpolateSubCellGeometry(pCellId, z, point.data(), subCellLevel, subCellCoord);
2004 MBool outside = m_geometry->pointIsInside2(point.data());
2008 transformToLocal(pCellId, point.data(), z);
2013 if(subCellLevel < 1) {
2014 cout <<
"Integration points used: ";
2015 for(
MInt d = 0; d < nDim; d++) {
2016 if(subCellLevel < 1) {
2017 cout << z[d] <<
" ";
2024 for(
MInt d1 = 0; d1 < nDim; d1++) {
2025 for(
MInt d2 = 0; d2 < nDim; d2++) {
2029 lagrangianPointsJacobi(pCellId, z, x);
2030 std::array<std::array<MFloat, nDim>, nDim> x_{};
2031 for(
MInt d1 = 0; d1 < nDim; d1++) {
2032 for(
MInt d2 = 0; d2 < nDim; d2++) {
2033 x_[d1][d2] = x(d1, d2);
2037 for(
MInt d = 0; d < nDim; d++) {
2038 determinantDebug *=
FFPOW2(subCellLevel);
2040 if(!
approx(determinantDebug, determinant, m_eps)) {
2041 stringstream errorMessage;
2042 errorMessage <<
"Error in calculating the determinant of the jaconbian matrix" <<
determinant <<
" "
2043 << determinantDebug << endl;
2044 mTerm(1, AT_, errorMessage.str());
2046 if(subCellLevel < 1) {
2047 cout <<
"determinant at this point: " <<
determinant << endl;
2051 getNodalStiffnessMatrix(pCellId, node, Mat_part, nodePos, z, determinant, alpha, subCellLevel);
2052 for(
MInt m1 = 0; m1 < a_noNodes(pCellId) * nDim; m1++) {
2053 for(
MInt m2 = 0; m2 < a_noNodes(pCellId) * nDim; m2++) {
2054 Ke(m1, m2) += Mat_part(m1, m2);
2064 for(
MInt cell = 0; cell < a_noCells(); cell++) {
2065 if(!a_isActive(cell))
continue;
2067 MInt nodePos[nDim] = {0};
2070 for(
MInt d = 0; d < nDim; d++) {
2074 for(
MInt node = 0; node < a_noNodes(cell); node++) {
2075 const MInt nodesPerDir = a_pRfnmnt(cell) + 2;
2076 Fd::nodePosition(node, nodesPerDir, nodePos);
2078 for(
MInt d = 0; d < nDim; d++) {
2079 z[d] = m_gaussPoints[a_pRfnmnt(cell)][nodePos[d]];
2083 for(
MInt d = 0; d < nDim; d++) {
2084 weight *= m_gaussWeights[a_pRfnmnt(cell)][nodePos[d]];
2091 getStrainInterpolationMatrix(Be, cell, z);
2093 std::array<MFloat, m_noStrains> stresses{};
2095 getStressesAtPoint(cell, z, m_totalNodalDisplacements, stresses.data());
2097 for(
MInt d = 0; d < m_noStrains; d++) {
2098 stresses[d] = a_nodalStresses(cell, node, d);
2103 for(
MInt n = 0; n < a_noNodes(cell); n++) {
2104 for(
MInt dim = 0; dim < nDim; dim++) {
2105 MInt nodeId = a_nodeIdsLocal(cell, n);
2107 for(
MInt d = 0; d < m_noStrains; d++) {
2108 MFloat BeT = Be(d, n * nDim + dim);
2109 load += BeT * stresses[d];
2111 m_internalLoadVector[nodeId * nDim + dim] += load * weight;
2122 m_bndryCnd->calcReactionForces();
2143 m_bndryCnd->updateForceVector();
2163 m_globalBndryMatrix.clear();
2166 m_bndryCnd->updateSystemMatrix();
2189 NEW_TIMER_GROUP(tg_solver,
"FC Solver (solverId=" + std::to_string(m_solverId) +
")");
2190 NEW_TIMER_NOCREATE(m_t.solver,
"complete solver", tg_solver);
2192 NEW_SUB_TIMER_NOCREATE(m_t.initSolver,
"init solver", m_t.solver);
2193 NEW_SUB_TIMER_NOCREATE(m_t.calcStiffMat,
"calc Siffness Matrix per Level", m_t.initSolver);
2194 NEW_SUB_TIMER_NOCREATE(m_t.solutionStep,
"SolutionStep", m_t.solver);
2195 NEW_SUB_TIMER_NOCREATE(m_t.subCellInt,
"subcell Integration", m_t.solutionStep);
2196 NEW_SUB_TIMER_NOCREATE(m_t.forceBC,
"boundary forces", m_t.solutionStep);
2197 NEW_SUB_TIMER_NOCREATE(m_t.displacementBC,
"boundary displacement", m_t.solutionStep);
2198 NEW_SUB_TIMER_NOCREATE(m_t.solving,
"Solution of System of Equations", m_t.solutionStep);
2199 NEW_SUB_TIMER_NOCREATE(m_t.exchange,
"Exchange", m_t.solutionStep);
2209 if(!grid().isActive())
return;
2211 std::vector<MInt> timerIds_;
2212 timerIds_.reserve(17);
2213 timerIds_.emplace_back(m_t.solver);
2214 timerIds_.emplace_back(m_t.initSolver);
2215 timerIds_.emplace_back(m_t.calcStiffMat);
2216 timerIds_.emplace_back(m_t.solutionStep);
2217 timerIds_.emplace_back(m_t.subCellInt);
2218 timerIds_.emplace_back(m_t.forceBC);
2219 timerIds_.emplace_back(m_t.displacementBC);
2220 timerIds_.emplace_back(m_t.solving);
2221 timerIds_.emplace_back(m_t.exchange);
2222 const MInt noTimers = timerIds_.size();
2224 std::vector<MFloat> timerValues_;
2225 timerValues_.reserve(noTimers);
2226 for(
MInt i = 0; i < noTimers; i++) {
2227 timerValues_.emplace_back(RETURN_TIMER_TIME(timerIds_[i]));
2231 AT_,
"MPI_IN_PLACE",
"timerValues_");
2233 const MInt noDomains_ = noDomains();
2234 for(
MInt i = 0; i < noTimers; i++) {
2235 const MFloat meanValue = timerValues_[i] / noDomains_;
2236 SET_RECORD(timerIds_[i], meanValue);
2267 fillDisplacementVectorWithCoords();
2268 calcElementDisplacements();
2269 for(
MInt i = 0; i < a_noCells(); i++) {
2270 if(!a_isActive(i))
continue;
2271 for(
MInt d = 0; d < nDim; d++) {
2272 if(!
approx(c_coordinate(i, d), a_elementDispl(i, d), 1e-14)) {
2273 stringstream errorMessage;
2274 errorMessage <<
"Error in interpolating the strains " << c_coordinate(i, d) <<
" " << a_elementDispl(i, d)
2276 mTerm(1, AT_, errorMessage.str());
2280 resetDisplacements();
2286 resetDisplacements(0);
2291 calculateStiffnessMatrix();
2294 assembleFinalMatrix();
2295 createCompressedMatrix();
2299 getInternalLoadsFromStresses();
2300 getReactionForces();
2304 solveSystemOfEquations();
2307 m_bndryCnd->writeOutModifiedBoundaries();
2308 calcElementDisplacements();
2309 calcElementStrains();
2310 calcElementStresses();
2316 resetLoadVector(-1);
2319 for(
MInt step = 0; step < m_noLoadSteps; step++) {
2321 resetDisplacements(0);
2325 updateLoadVector(lambda);
2330 while(error > 1e-8 && k < 5) {
2332 calculateStiffnessMatrix();
2334 assembleFinalMatrix();
2335 createCompressedMatrix();
2338 solveSystemOfEquations();
2344 calculateStiffnessMatrix();
2345 m_globalBndryMatrix.clear();
2346 assembleFinalMatrix();
2347 createCompressedMatrix();
2349 const MInt n = m_finalGlobalMatrix.size();
2350 const MInt m = (m_totalNoNodes * nDim);
2352 m_totalNodalDisplacements);
2354 for(
MInt i = 0; i < m_totalNoNodes; i++) {
2355 cout <<
"Displacements (node " << i <<
")";
2356 for(
MInt d = 0; d < nDim; d++) {
2357 cout << std::setprecision(8) <<
" " << m_totalNodalDisplacements[i * nDim + d];
2363 for(
MInt i = 0; i < m_totalNoNodes; i++) {
2364 cout <<
"External forces (node " << i <<
")";
2365 for(
MInt d = 0; d < nDim; d++) {
2366 cout << std::setprecision(8) <<
" " << m_nodalLoadVector[i * nDim + d];
2372 for(
MInt i = 0; i < m_totalNoNodes; i++) {
2373 cout <<
"Internal forces (node " << i <<
")";
2374 for(
MInt d = 0; d < nDim; d++) {
2375 cout << std::setprecision(8) <<
" " << m_internalLoadVector[i * nDim + d];
2381 getReactionForces();
2382 for(
MInt i = 0; i < m_totalNoNodes; i++) {
2383 cout <<
"Reaction forces (node " << i <<
")";
2384 for(
MInt d = 0; d < nDim; d++) {
2385 cout << std::setprecision(8) <<
" " << m_reactionForceVector[i * nDim + d];
2391 updateLoadVector(lambda);
2397 error = (fabs(norm2Int) > m_eps) ? norm2Res / (norm2Int) : norm2Res;
2399 cout << fixed << setprecision(15) << endl;
2400 cout <<
"Error in step " << step <<
" and iteration " << k <<
" is: " << error << endl;
2401 cout <<
"Lambda in step " << step <<
" and iteration " << k <<
" is: " << lambda << endl;
2402 cout <<
"Residual in step " << step <<
" and iteration " << k <<
" is: " << norm2Res << endl;
2403 cout <<
"IntForce vector in step " << step <<
" and iteration " << k <<
" is: " << norm2Int << endl;
2404 cout <<
"ReacForce vector in step " << step <<
" and iteration " << k <<
" is: " << norm2Reac << endl;
2405 cout << fixed << setprecision(5) << endl;
2413 stringstream errorMessage;
2414 errorMessage <<
"Error!!! Solver method not implemented." << endl;
2415 mTerm(1, AT_, errorMessage.str());
2426 std::ignore = forceOutput;
2427 std::ignore = finalTimeStep;
2444 writeGridRestart =
false;
2446 if(((
globalTimeStep % m_restartInterval) == 0) || writeRestart) {
2447 writeRestart =
true;
2449 if(m_adaptationSinceLastRestart) {
2450 writeGridRestart =
true;
2454 return writeRestart;
2463 MInt* recalcIdTree) {
2465 std::ignore = writeBackup;
2468 stringstream fileName;
2469 fileName << outputDir() <<
"restart_" <<
globalTimeStep << ParallelIo::fileExt();
2471 if(m_recalcIds !=
nullptr) {
2479 MInt recalcCounter = 0;
2480 for(
MInt cell = 0; cell < grid().raw().m_noInternalCells; cell++) {
2482 if(grid().raw().a_hasProperty(cell, Cell::IsHalo)) {
2485 MInt sId = grid().tree().grid2solver(m_recalcIds[cell]);
2487 recalcIdsSolver[recalcCounter] = sId;
2491 ASSERT(recalcCounter == grid().noInternalCells(),
"recalc ids size is wrong");
2493 saveRestartStrainsOnly(fileName.str().c_str(), gridFileName.c_str(), recalcIdsSolver.getPointer());
2494 cerr <<
"RecalcIds" << endl;
2496 saveRestartStrainsOnly(fileName.str().c_str(), gridFileName.c_str(), m_recalcIds);
2497 cerr <<
"No RecalcIds" << endl;
2516 if(nDim != 2 && nDim != 3) {
2517 cerr <<
" In global function saveRestartStrainsOnly: wrong number of dimensions !" << endl;
2522 cerr <<
"Writing solution to file" << endl;
2524 ParallelIo parallelIo(fileName, PIO_REPLACE, mpiComm());
2525 parallelIo.defineScalar(PIO_INT,
"noCells");
2528 const MInt totalNoCells = domainOffset(noDomains());
2529 cerr <<
"totalNoCells " << totalNoCells << endl;
2532 auto defFloatArray = [&](
const MString arrayName,
const MString varName,
const MInt length) {
2533 parallelIo.defineArray(PIO_FLOAT, arrayName, length);
2534 parallelIo.setAttribute(varName,
"name", arrayName);
2537 auto defineMacroscopicVariables = [&](
const MString name,
const MString prefix) {
2539 MInt noIds = (m_testRun) ?
IPOW2(nDim) + 1 : 0;
2540 const MInt noOutputVar = (nDim == 2) ? (6 + nDim + noIds) : (12 + nDim + noIds);
2543 velNames[0] =
"Epsilon_x";
2544 velNames[1] =
"Epsilon_y";
2545 velNames[2] =
"Epsilon_xy";
2546 velNames[3] =
"Stress_x";
2547 velNames[4] =
"Stress_y";
2548 velNames[5] =
"Stress_xy";
2549 velNames[6] =
"Displacement_x";
2550 velNames[7] =
"Displacement_y";
2552 velNames[5] =
"GlobalNodeId0";
2553 velNames[6] =
"GlobalNodeId1";
2554 velNames[7] =
"GlobalNodeId2";
2555 velNames[8] =
"GlobalNodeId3";
2556 velNames[9] =
"DomainId";
2559 velNames[0] =
"Epsilon_x";
2560 velNames[1] =
"Epsilon_y";
2561 velNames[2] =
"Epsilon_z";
2562 velNames[3] =
"Epsilon_xy";
2563 velNames[4] =
"Epsilon_yz";
2564 velNames[5] =
"Epsilon_xz";
2565 velNames[6] =
"Stress_x";
2566 velNames[7] =
"Stress_y";
2567 velNames[8] =
"Stress_z";
2568 velNames[9] =
"Stress_xy";
2569 velNames[10] =
"Stress_yz";
2570 velNames[11] =
"Stress_xz";
2571 velNames[12] =
"Displacement_x";
2572 velNames[13] =
"Displacement_y";
2573 velNames[14] =
"Displacement_z";
2575 velNames[15] =
"GlobalNodeId0";
2576 velNames[16] =
"GlobalNodeId1";
2577 velNames[17] =
"GlobalNodeId2";
2578 velNames[18] =
"GlobalNodeId3";
2579 velNames[19] =
"GlobalNodeId4";
2580 velNames[20] =
"GlobalNodeId5";
2581 velNames[21] =
"GlobalNodeId6";
2582 velNames[22] =
"GlobalNodeId7";
2583 velNames[23] =
"DomainId";
2587 for(
MInt d = 0; d != noOutputVar; d++) {
2588 defFloatArray(name + std::to_string(d), prefix + velNames[d], totalNoCells);
2592 auto writeMacroscopicStrain = [&](
const MInt index) {
2594 for(
MInt i = 0; i < noInternalCells(); ++i) {
2595 tmp[i] = a_elementStrains(recalcIdTree !=
nullptr ? recalcIdTree[i] : i, index);
2597 parallelIo.writeArray(tmp.getPointer(),
"strain" + std::to_string(index));
2600 auto writeMacroscopicStress = [&](
const MInt d,
const MInt index) {
2602 for(
MInt i = 0; i < noInternalCells(); ++i) {
2603 tmp[i] = a_elementStresses(recalcIdTree !=
nullptr ? recalcIdTree[i] : i, d);
2605 parallelIo.writeArray(tmp.getPointer(),
"strain" + std::to_string(index));
2608 auto writeMacroscopicDisplacement = [&](
const MInt d,
const MInt index) {
2610 for(
MInt i = 0; i < noInternalCells(); ++i) {
2611 tmp[i] = a_elementDispl(recalcIdTree !=
nullptr ? recalcIdTree[i] : i, d);
2613 parallelIo.writeArray(tmp.getPointer(),
"strain" + std::to_string(index));
2616 auto writeGlobalNodeIds = [&](
const MInt d,
const MInt index) {
2618 for(
MInt i = 0; i < noInternalCells(); ++i) {
2619 tmp[i] = a_nodeIdsGlobal(recalcIdTree !=
nullptr ? recalcIdTree[i] : i, d);
2621 parallelIo.writeArray(tmp.getPointer(),
"strain" + std::to_string(index));
2627 for(
MInt i = 0; i < noInternalCells(); ++i) {
2628 tmp[i] = (
MFloat)domainId();
2630 parallelIo.writeArray(tmp.getPointer(),
"strain" + std::to_string(index));
2633 defineMacroscopicVariables(
"strain",
"");
2636 parallelIo.setAttribute(solverId(),
"solverId");
2637 parallelIo.setAttribute(gridInputFileName,
"gridFile",
"");
2639 parallelIo.setAttribute(totalNoCells,
"noCells");
2643 const MPI_Offset firstGlobalId = domainOffset(domainId());
2644 const MPI_Offset localNoCells = noInternalCells();
2645 parallelIo.setOffset(localNoCells, firstGlobalId);
2647 cerr <<
"InternalCells " << localNoCells << endl;
2648 cerr <<
"Write out element strains" << endl;
2650 writeMacroscopicStrain(index);
2652 cerr <<
"Write out element stresses" << endl;
2654 writeMacroscopicStress(index, index + m_noStrains);
2656 cerr <<
"Write out element displacements" << endl;
2657 for(
MInt d = 0; d < nDim; d++) {
2658 writeMacroscopicDisplacement(d, d + 2 * m_noStrains);
2661 cerr <<
"Write out global node Ids" << endl;
2663 writeGlobalNodeIds(d, d + nDim + 2 * m_noStrains);
2665 writeDomainId(0,
IPOW2(nDim) + nDim + 2 * m_noStrains);
2678 m_adaptationSinceLastRestart =
false;
2689 const MInt noCellsGrid = grid().raw().treeb().size();
2690 const MInt offset = noCellsGrid * solverId();
2693 const MInt gridCellId = grid().tree().solver2grid(cellId);
2694 const MInt id = gridCellId + offset;
2695 solverCellWeight[
id] = F1;
2711 for(
MInt m1 = 0; m1 < a_noNodes(pCellId); m1++) {
2712 for(
MInt d1 = 0; d1 < nDim; d1++) {
2713 for(
MInt m2 = 0; m2 < a_noNodes(pCellId); m2++) {
2714 for(
MInt d2 = 0; d2 < nDim; d2++) {
2716 MInt nodeIdA = a_nodeIdsLocal(pCellId, m1);
2717 MInt nodeIdB = a_nodeIdsLocal(pCellId, m2);
2718 MInt rowPosCell = m1 * nDim + d1;
2719 MInt colPosCell = m2 * nDim + d2;
2720 MInt rowPosRank = nodeIdA * nDim + d1;
2721 MInt colPosRank = nodeIdB * nDim + d2;
2725 if(!
approx(Ke(rowPosCell, colPosCell), F0, m_eps)) {
2727 auto pos = std::make_pair(rowPosRank, colPosRank);
2728 auto iter = m_globalStiffnessMatrix.find(pos);
2730 if(iter != m_globalStiffnessMatrix.end()) {
2731 iter->second += Ke(rowPosCell, colPosCell);
2736 MFloat value = Ke(rowPosCell, colPosCell);
2737 m_globalStiffnessMatrix.insert({pos, value});
2758 for(
MInt m1 = 0; m1 < a_noNodes(pCellId); m1++) {
2759 for(
MInt d1 = 0; d1 < nDim; d1++) {
2760 for(
MInt m2 = 0; m2 < a_noNodes(pCellId); m2++) {
2761 for(
MInt d2 = 0; d2 < nDim; d2++) {
2763 MInt nodeIdA = a_nodeIdsLocal(pCellId, m1);
2764 MInt nodeIdB = a_nodeIdsLocal(pCellId, m2);
2765 MInt rowPosCell = m1 * nDim + d1;
2766 MInt colPosCell = m2 * nDim + d2;
2767 MInt rowPosRank = nodeIdA * nDim + d1;
2768 MInt colPosRank = nodeIdB * nDim + d2;
2772 if(!
approx(Bndry(rowPosCell, colPosCell), F0, m_eps)) {
2774 auto pos = std::make_pair(rowPosRank, colPosRank);
2775 auto iter = m_globalBndryMatrix.find(pos);
2777 if(iter != m_globalBndryMatrix.end()) {
2778 if(m_addingPenalties) {
2779 iter->second += Bndry(rowPosCell, colPosCell);
2785 MFloat value = Bndry(rowPosCell, colPosCell);
2786 m_globalBndryMatrix.insert({pos, value});
2807 m_finalGlobalMatrix.clear();
2809 auto iterMat = m_globalStiffnessMatrix.begin();
2810 while(iterMat != m_globalStiffnessMatrix.end()) {
2811 auto pos = iterMat->first;
2812 auto value = iterMat->second;
2813 m_finalGlobalMatrix.insert({pos, value});
2817 iterMat = m_globalBndryMatrix.begin();
2818 while(iterMat != m_globalBndryMatrix.end()) {
2819 auto pos = iterMat->first;
2820 auto value = iterMat->second;
2821 auto iter = m_finalGlobalMatrix.find(pos);
2823 if(iter != m_finalGlobalMatrix.end()) {
2824 iter->second += value;
2829 m_finalGlobalMatrix.insert({pos, value});
2842 m_globalStiffnessMatrix.clear();
2845 for(
MInt cell = 0; cell < a_noCells(); cell++) {
2847 if(!a_isActive(cell))
continue;
2850 cout <<
"///////////////////////////////////////////////////////////////" << endl;
2851 cout <<
"///////////////////////////////////////////////////////////////" << endl;
2853 cout <<
"CellId " << cell << endl;
2854 cout <<
"Cell center: ";
2855 for(
MInt d = 0; d < nDim; d++) {
2856 cout << c_coordinate(cell, d) <<
" ";
2860 cout <<
"Nodes of cell " << cell << endl;
2861 std::array<MInt, nDim> nodePos{};
2862 for(
MInt p = 0;
p < a_noNodes(cell);
p++) {
2863 cout <<
"Global coordinates of Point " <<
p <<
" (localId = " << a_nodeIdsLocal(cell, p)
2864 <<
", globalId = " << a_nodeIdsGlobal(cell, p) <<
"): ";
2865 for(
MInt d = 0; d < nDim; d++) {
2866 cout << m_nodalDisplacements[a_nodeIdsLocal(cell, p) * nDim + d] <<
" ";
2869 cout <<
"Local coordinates of Point " <<
p <<
" (localId = " << a_nodeIdsLocal(cell, p)
2870 <<
", globalId = " << a_nodeIdsGlobal(cell, p) <<
"): ";
2871 for(
MInt d = 0; d < nDim; d++) {
2872 cout << a_nodePosition(cell, nodePos[d]) <<
" (" << nodePos[d] <<
") ";
2876 if((nodePos[nDim - 1] + 1) < (a_pRfnmnt(cell) + 2)) {
2877 nodePos[nDim - 1]++;
2879 nodePos[nDim - 1] = 0;
2880 if((nodePos[nDim - 2] + 1) < (a_pRfnmnt(cell) + 2)) {
2881 nodePos[nDim - 2]++;
2883 nodePos[nDim - 2] = 0;
2893 mAlloc(eigenValues, a_noNodes(cell) * nDim,
"eigenValues", F0, AT_);
2894 mAlloc(Ke_final, a_noNodes(cell) * nDim, a_noNodes(cell) * nDim,
"Ke_final", F0, AT_);
2899 for(
MInt m1 = 0; m1 < a_noNodes(cell) * nDim; m1++) {
2900 for(
MInt m2 = 0; m2 < a_noNodes(cell) * nDim; m2++) {
2902 Ke_final[m1][m2] = F0;
2904 eigenValues[m1] = F0;
2910 std::array<MFloat, nDim> z{};
2911 for(
MInt d = 0; d < nDim; d++) {
2912 z[d] = (
static_cast<MFloat>(rand()) /
static_cast<MFloat>(RAND_MAX)) * F2 - F1;
2914 std::array<MFloat, nDim> x1{};
2915 std::array<MFloat, nDim> x2{};
2916 interpolateGeometryDebug(cell, z.data(), x1.data());
2917 interpolateGeometry(cell, z.data(), x2.data());
2918 for(
MInt d = 0; d < nDim; d++) {
2919 if(!
approx(x1[d], x2[d], 1e-10)) {
2920 stringstream errorMessage;
2921 errorMessage <<
"Error in interpolating the geometry " << x1[d] <<
" " << x2[d] << endl;
2922 mTerm(1, AT_, errorMessage.str());
2928 const MFloat alpha = (a_maxSubCellLvl(cell) < 1) ? F1 : m_alpha;
2929 const MInt subCellLevel = 0;
2930 getElementMatrix(Ke, cell, alpha, subCellLevel);
2931 for(
MInt m1 = 0; m1 < a_noNodes(cell) * nDim; m1++) {
2932 for(
MInt m2 = 0; m2 < a_noNodes(cell) * nDim; m2++) {
2933 Ke_final[m1][m2] = Ke(m1, m2);
2937 std::array<MFloat, nDim> coords{};
2938 for(
MInt d = 0; d < nDim; d++) {
2939 coords[d] = c_coordinate(cell, d);
2941 for(
MInt child = 0; child <
IPOW2(nDim); child++) {
2942 const MInt childLvl = subCellLevel + 1;
2943 m_bndryCnd->subCellIntegration(childLvl, coords.data(), child, cell, Ke_final);
2945 for(
MInt m1 = 0; m1 < a_noNodes(cell) * nDim; m1++) {
2946 for(
MInt m2 = 0; m2 < a_noNodes(cell) * nDim; m2++) {
2947 Ke(m1, m2) = Ke_final[m1][m2];
2952 cout <<
"Element-Stiffness-Matrix of Cell :" << cell << endl;
2953 cout <<
"SubCellTree depth " << a_maxSubCellLvl(cell) << endl;
2954 cout <<
"Volume is " << m_volume << endl;
2955 for(
MInt m1 = 0; m1 < a_noNodes(cell) * nDim; m1++) {
2956 for(
MInt m2 = 0; m2 < a_noNodes(cell) * nDim; m2++) {
2957 cout << Ke_final[m1][m2] <<
" ";
2964 for(
MInt m1 = 0; m1 < a_noNodes(cell) * nDim; m1++) {
2965 cout << m1 + 1 <<
". Eigen value = " << setprecision(12) << eigenValues[m1] << endl;
2968 if(m_printEigenValues) {
2969 ofstream eigenOutput;
2970 eigenOutput.open(
"eigenValues.txt", ofstream::app);
2971 for(
MInt m1 = 0; m1 < a_noNodes(cell) * nDim; m1++) {
2972 eigenOutput << m1 + 1 <<
". Eigen value = " << setprecision(12) << eigenValues[m1] << endl;
2974 eigenOutput << endl;
2978 computeAssembledSystemMatrix(Ke, cell);
2989 for(
MInt i = 0; i < m_totalNoNodes; i++) {
2990 for(
MInt d = 0; d < nDim; d++) {
2991 m_totalNodalDisplacements[i * nDim + d] += m_nodalDisplacements[i * nDim + d];
3002 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3003 for(
MInt d = 0; d < nDim; d++) {
3004 m_totalNodalDisplacements[i * nDim + d] = F0;
3005 m_nodalDisplacements[i * nDim + d] = F0;
3011 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3012 for(
MInt d = 0; d < nDim; d++) {
3013 m_nodalDisplacements[i * nDim + d] = F0;
3019 TERMM(1,
"Not implemented for this method (resetDisplacements).");
3031 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3032 for(
MInt d = 0; d < nDim; d++) {
3033 m_externalLoadVector[i * nDim + d] = F0;
3034 m_internalLoadVector[i * nDim + d] = F0;
3035 m_reactionForceVector[i * nDim + d] = F0;
3036 m_nodalLoadVector[i * nDim + d] = F0;
3043 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3044 for(
MInt d = 0; d < nDim; d++) {
3045 m_externalLoadVector[i * nDim + d] = F0;
3046 m_internalLoadVector[i * nDim + d] = F0;
3047 m_reactionForceVector[i * nDim + d] = F0;
3054 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3055 for(
MInt d = 0; d < nDim; d++) {
3056 m_internalLoadVector[i * nDim + d] = F0;
3057 m_reactionForceVector[i * nDim + d] = F0;
3064 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3065 for(
MInt d = 0; d < nDim; d++) {
3066 m_externalLoadVector[i * nDim + d] = F0;
3072 TERMM(1,
"Not implemented for this method (resetLoadVector).");
3081 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3082 for(
MInt d = 0; d < nDim; d++) {
3083 const MFloat extLoad = m_externalLoadVector[i * nDim + d] * lambda;
3084 const MFloat intLoad = m_internalLoadVector[i * nDim + d];
3085 const MFloat reacForce = m_reactionForceVector[i * nDim + d];
3086 m_nodalLoadVector[i * nDim + d] = extLoad - (intLoad - reacForce);
3095 MInt length = m_finalGlobalMatrix.size();
3097 if(m_sysMatCompressed !=
nullptr) {
3098 cerr <<
"Deallocate m_sysMatCompressed" << endl;
3101 if(m_compressionIndexSys !=
nullptr) {
3102 cerr <<
"Deallocate m_compressionIndexSys" << endl;
3106 mAlloc(m_sysMatCompressed, length,
"m_sysMatCompressed", F0, AT_);
3108 mAlloc(m_compressionIndexSys, length, 2,
"m_compressionIndexSys", 0, AT_);
3111 auto iterMat = m_finalGlobalMatrix.begin();
3112 while(iterMat != m_finalGlobalMatrix.end()) {
3114 if(
approx(iterMat->second, F0, m_eps)) {
3115 m_sysMatCompressed[cnt] = F0;
3117 m_sysMatCompressed[cnt] = iterMat->second;
3119 m_compressionIndexSys[cnt][0] = iterMat->first.first;
3120 m_compressionIndexSys[cnt][1] = iterMat->first.second;
3140 cout <<
"///////////////////////////////////////////////////////////////" << endl;
3141 cout <<
"///////////////////////////////////////////////////////////////" << endl;
3143 cout <<
"SOLUTION STEP STARTS:" << endl;
3145 cout << fixed << setprecision(12) << endl;
3146 cout <<
"FORCE VECTOR (sorted by the global point Id): " << endl;
3147 for(
MInt dom = 0; dom < noDomains(); dom++) {
3149 if(domainId() != dom)
continue;
3150 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3151 cout <<
"Node Id " << i <<
" ";
3152 for(
MInt d = 0; d < nDim; d++) {
3153 cout << m_nodalLoadVector[i * nDim + d] <<
" ";
3158 cout << fixed << setprecision(5) << endl;
3161 const MInt n = m_finalGlobalMatrix.size();
3162 MInt const m = (m_totalNoNodes * nDim);
3163 if(!m_solveSoEIteratively) {
3165 m_nodalDisplacements);
3169 m_nodalDisplacements);
3171 solveMatrixIterativelyPreCon(m_sysMatCompressed, m_compressionIndexSys, n, m, m_nodalLoadVector,
3172 m_nodalDisplacements);
3177 updateDisplacements();
3181 cout << fixed << setprecision(12) << endl;
3182 cout <<
"DISPLACEMENT VECTOR (sorted by the global point Id): " << endl;
3183 for(
MInt dom = 0; dom < noDomains(); dom++) {
3185 if(domainId() != dom)
continue;
3186 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3187 cout <<
"Node Id " << i <<
" ";
3188 for(
MInt d = 0; d < nDim; d++) {
3189 cout << m_totalNodalDisplacements[i * nDim + d] <<
" ";
3196 for(
MInt i = 0; i < m_totalNoNodes; i++) {
3198 for(
MInt d = 0; d < nDim; d++) {
3199 multi += F1B2 * (m_totalNodalDisplacements[i * nDim + d] * m_nodalLoadVector[i * nDim + d]);
3203 if(noDomains() > 1) {
3204 MPI_Allreduce(MPI_IN_PLACE, &sum, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"sum");
3206 MFloat res = sqrt(fabs(m_analyticSolution + sum) / fabs(m_analyticSolution));
3207 cout <<
"SUM " << -sum <<
" " << res << endl;
3208 cout << fixed << setprecision(5) << endl;
3217 MInt noEdges = (nDim == 2) ? 0 : 12;
3218 MInt noSurfaces = (nDim == 2) ? 4 : 6;
3220 MFloat cellHalfLen = F1B2 * c_cellLengthAtCell(cell);
3222 if(node < noVertices) {
3223 for(
MInt d = 0; d < nDim; d++) {
3224 MFloat coord = c_coordinate(cell, d);
3225 MFloat nodeCoord = coord + cellHalfLen * Fd::vertexPosition(node, d);
3226 coordinates[d] = nodeCoord;
3228 }
else if(node < noVertices + noEdges * a_pRfnmnt(cell)) {
3229 MInt edge = (
MInt)floor((node - noVertices) / a_pRfnmnt(cell));
3230 MInt l = (node - noVertices) % a_pRfnmnt(cell);
3231 for(
MInt d = 0; d < nDim; d++) {
3233 MFloat coord = c_coordinate(cell, d);
3234 if(
approx(Fd::edgePosition(edge, d), F0, 0.0000001)) {
3235 nodeCoord = coord + cellHalfLen * a_nodePosition(cell, l + 1);
3237 nodeCoord = coord + cellHalfLen * Fd::edgePosition(edge, d);
3239 coordinates[d] = nodeCoord;
3241 }
else if(node < noVertices + noEdges * a_pRfnmnt(cell) + noSurfaces * a_pRfnmnt(cell) * a_pRfnmnt(cell)) {
3242 MInt surface = (
MInt)floor((node - noVertices - noEdges * a_pRfnmnt(cell)) / (a_pRfnmnt(cell) * a_pRfnmnt(cell)));
3244 l[1] = (node - noVertices - noEdges * a_pRfnmnt(cell)) % (a_pRfnmnt(cell) * a_pRfnmnt(cell));
3245 while(l[1] >= a_pRfnmnt(cell)) {
3247 l[1] -= a_pRfnmnt(cell);
3250 for(
MInt d = 0; d < nDim; d++) {
3252 MFloat coord = c_coordinate(cell, d);
3253 if(
approx(Fd::surfacePosition(surface, d), F0, 0.0000001)) {
3254 nodeCoord = coord + cellHalfLen * a_nodePosition(cell, l[counter] + 1);
3257 nodeCoord = coord + cellHalfLen * Fd::surfacePosition(surface, d);
3259 coordinates[d] = nodeCoord;
3263 l[2] = node - noVertices - noEdges * a_pRfnmnt(cell) - noSurfaces * a_pRfnmnt(cell) * a_pRfnmnt(cell);
3264 while(l[2] >= (a_pRfnmnt(cell) * a_pRfnmnt(cell))) {
3266 l[2] -= (a_pRfnmnt(cell) * a_pRfnmnt(cell));
3268 while(l[2] >= a_pRfnmnt(cell)) {
3270 l[2] -= a_pRfnmnt(cell);
3273 for(
MInt d = 0; d < nDim; d++) {
3274 MFloat coord = c_coordinate(cell, d);
3275 MFloat nodeCoord = coord + cellHalfLen * a_nodePosition(cell, l[counter] + 1);
3277 coordinates[d] = nodeCoord;
3314 for(
MInt i = 0; i < m_totalNoNodes * nDim; i++) {
3315 r0[i] = m_nodalLoadVector[i];
3317 p[i] = m_nodalLoadVector[i];
3319 for(
MInt i = 0; i < m_noInternalNodes * nDim; i++) {
3320 rho += (r0[i] * r0[i]);
3321 b += (m_nodalLoadVector[i] * m_nodalLoadVector[i]);
3323 cout << setprecision(12) << endl;
3324 MPI_Allreduce(MPI_IN_PLACE, &rho, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"rho");
3325 MPI_Allreduce(MPI_IN_PLACE, &
b, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"b");
3327 for(
MInt j = 0; j < m_maxNoIterations; j++) {
3329 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3332 for(
MInt k = 0; k < n; k++) {
3333 nu[pos[k][0]] += A_coeff[k] *
p[pos[k][1]];
3338 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3339 dotProduct += (nu[k] * r0[k]);
3341 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3342 alpha = rho / dotProduct;
3345 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3346 s[k] = r[k] - alpha * nu[k];
3350 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3353 for(
MInt k = 0; k < n; k++) {
3354 t[pos[k][0]] += A_coeff[k] * s[pos[k][1]];
3359 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3360 dotProduct += (t[k] * s[k]);
3362 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3365 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3366 dotProduct += (t[k] * t[k]);
3368 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3369 omega /= dotProduct;
3373 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3374 m_nodalDisplacements[k] += alpha *
p[k] + omega * s[k];
3378 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3381 for(
MInt k = 0; k < n; k++) {
3382 b_calc[pos[k][0]] += A_coeff[k] * m_nodalDisplacements[pos[k][1]];
3385 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3386 dotProduct += ((m_nodalLoadVector[k] - b_calc[k]) * (m_nodalLoadVector[k] - b_calc[k]));
3388 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3389 MFloat convergence = dotProduct /
b;
3390 cout <<
"Convergence of iteration " << j <<
" is " << convergence << endl;
3391 if(convergence < m_eps) {
3392 cout <<
"REACHED CONVERGENCY" << endl;
3397 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3398 r[k] = s[k] - omega * t[k];
3406 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3407 dotProduct += (r[k] * r0[k]);
3409 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3413 beta *= rho * alpha / omega;
3416 for(
MInt k = 0; k < m_totalNoNodes * nDim; k++) {
3417 p[k] = r[k] + beta * (
p[k] - omega * nu[k]);
3420 cout << setprecision(5) << endl;
3454 bestSolution.fill(F0);
3468 MFloat minConvergence = std::numeric_limits<MFloat>::max();
3469 MFloat currentConvergence = F0;
3470 MFloat previousConvergence = std::numeric_limits<MFloat>::max();
3478 for(
MInt i = 0; i < m; i++) {
3483 for(
MInt i = 0; i < m_noInternalNodes * nDim; i++) {
3484 rho += (r0[i] * r0[i]);
3485 b_mag += (
b[i] *
b[i]);
3489 for(
MInt k = 0; k < n; k++) {
3490 if(pos[k][0] == pos[k][1]) {
3491 M_inv[pos[k][0]] = F1 / A_coeff[k];
3494 exchangeVector(M_inv.data());
3496 for(
MInt i = 0; i < m; i++) {
3497 z[i] = M_inv[i] * r0[i];
3501 cout << setprecision(12) << endl;
3502 MPI_Allreduce(MPI_IN_PLACE, &rho, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"rho");
3503 MPI_Allreduce(MPI_IN_PLACE, &b_mag, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"b_mag");
3505 if(b_mag < m_eps)
return;
3507 while(j < m_maxNoIterations
3508 || ((currentConvergence > minConvergence) && !
approx(currentConvergence, previousConvergence, m_eps))) {
3510 for(
MInt k = 0; k < m; k++) {
3513 for(
MInt k = 0; k < n; k++) {
3514 nu[pos[k][0]] += A_coeff[k] * nuHat[pos[k][1]];
3516 exchangeVector(nu.data());
3520 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3521 dotProduct += (nu[k] * r0[k]);
3523 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3524 alpha = rho / dotProduct;
3527 for(
MInt k = 0; k < m; k++) {
3528 s[k] = M_inv[k] * nu[k];
3532 for(
MInt k = 0; k < m; k++) {
3534 tHat[k] = z[k] - alpha * s[k];
3536 for(
MInt k = 0; k < n; k++) {
3537 t[pos[k][0]] += (A_coeff[k] * tHat[pos[k][1]]);
3539 exchangeVector(t.data());
3543 for(
MInt k = 0; k < m; k++) {
3544 x[k] += alpha * nuHat[k];
3548 for(
MInt k = 0; k < m; k++) {
3551 for(
MInt k = 0; k < n; k++) {
3552 b_calc[pos[k][0]] += (A_coeff[k] * x[pos[k][1]]);
3555 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3556 dotProduct += ((
b[k] - b_calc[k]) * (
b[k] - b_calc[k]));
3558 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3559 MFloat convergence = dotProduct / b_mag;
3560 previousConvergence = currentConvergence;
3561 currentConvergence = convergence;
3562 if(convergence < minConvergence) {
3563 minConvergence = convergence;
3564 for(
MInt k = 0; k < m; k++) {
3565 bestSolution[k] = x[k];
3568 if(convergence < m_eps) {
3573 for(
MInt k = 0; k < m; k++) {
3574 r[k] = r[k] - alpha * nu[k];
3579 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3580 dotProduct += (t[k] * r[k]);
3582 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3587 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3588 dotProduct += (t[k] * t[k]);
3590 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3595 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3596 dotProduct += (t[k] * r0[k]);
3598 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3602 for(
MInt k = 0; k < m; k++) {
3603 z[k] = M_inv[k] * t[k];
3607 omega = theta / phi;
3611 for(
MInt k = 0; k < m; k++) {
3612 x[k] += omega * tHat[k];
3616 for(
MInt k = 0; k < m; k++) {
3619 for(
MInt k = 0; k < n; k++) {
3620 b_calc[pos[k][0]] += A_coeff[k] * x[pos[k][1]];
3623 for(
MInt k = 0; k < m_noInternalNodes * nDim; k++) {
3624 dotProduct += ((
b[k] - b_calc[k]) * (
b[k] - b_calc[k]));
3626 MPI_Allreduce(MPI_IN_PLACE, &dotProduct, 1, MPI_DOUBLE, MPI_SUM, mpiComm(), AT_,
"MPI_IN_PLACE",
"dotProduct");
3627 convergence = dotProduct / b_mag;
3628 previousConvergence = currentConvergence;
3629 currentConvergence = convergence;
3630 if(convergence < minConvergence) {
3631 minConvergence = convergence;
3632 for(
MInt k = 0; k < m; k++) {
3633 bestSolution[k] = x[k];
3636 if(convergence < m_eps) {
3641 for(
MInt k = 0; k < m; k++) {
3642 r[k] = r[k] - omega * t[k];
3652 for(
MInt k = 0; k < m; k++) {
3653 z[k] = tHat[k] - omega * z[k];
3657 beta *= rho * alpha / omega;
3660 for(
MInt k = 0; k < m; k++) {
3661 nuHat[k] = z[k] + beta * (nuHat[k] - omega * s[k]);
3664 cout << j <<
" " << minConvergence <<
" " << currentConvergence <<
" " << previousConvergence << endl;
3667 for(
MInt k = 0; k < m; k++) {
3668 x[k] = bestSolution[k];
3670 cout <<
"Solved SOE with " << j <<
" iterations and min convergence " << minConvergence <<
" and current convergence "
3671 << currentConvergence << endl;
3672 m_log <<
"Solved SOE with " << j <<
" iterations and min convergence " << minConvergence
3673 <<
" and current convergence " << currentConvergence << endl;
3674 cout << setprecision(5) << endl;
3687 if(noNeighborDomains() < 1)
return;
3690 MIntScratchSpace windowDataPerRank(noNeighborDomains(),
"windowDataPerRank", AT_);
3691 MIntScratchSpace haloDataPerRank(noNeighborDomains(),
"haloDataPerRank", AT_);
3692 MIntScratchSpace windowDataOffsets(noNeighborDomains() + 1,
"windowDataOffsets", AT_);
3693 MIntScratchSpace haloDataOffsets(noNeighborDomains() + 1,
"haloDataOffsets", AT_);
3694 windowDataPerRank.fill(0);
3695 haloDataPerRank.fill(0);
3696 windowDataOffsets.fill(0);
3697 haloDataOffsets.fill(0);
3700 MInt totalCounterWindow = 0;
3701 MInt totalCounterHalo = 0;
3702 for(
MInt n = 0; n < noNeighborDomains(); n++) {
3703 MInt dataCounterWindow = 0;
3704 MInt dataCounterHalo = 0;
3705 for(
MInt w = 0; w < noWindowCells(n); w++) {
3706 if(!a_isActive(windowCell(n, w)))
continue;
3707 for(
MInt node = 0; node < a_noNodes(windowCell(n, w)); node++) {
3708 for(
MInt dim = 0; dim < nDim; dim++) {
3709 dataCounterWindow++;
3713 for(
MInt h = 0; h < noHaloCells(n); h++) {
3714 if(!a_isActive(haloCell(n, h)))
continue;
3715 for(
MInt node = 0; node < a_noNodes(haloCell(n, h)); node++) {
3716 for(
MInt dim = 0; dim < nDim; dim++) {
3721 windowDataPerRank(n) = dataCounterWindow;
3722 haloDataPerRank(n) = dataCounterHalo;
3723 totalCounterWindow += dataCounterWindow;
3724 totalCounterHalo += dataCounterHalo;
3725 windowDataOffsets(n + 1) = totalCounterWindow;
3726 haloDataOffsets(n + 1) = totalCounterHalo;
3731 MFloat* receiveBuffers{};
3732 MPI_Request* mpi_request{};
3733 mAlloc(sendBuffers, totalCounterWindow,
"sendBuffers", F0, AT_);
3734 mAlloc(receiveBuffers, totalCounterHalo,
"receiveBuffers", F0, AT_);
3735 mAlloc(mpi_request, noNeighborDomains(),
"mpi_request", AT_);
3738 for(
MInt n = 0; n < noNeighborDomains(); n++) {
3740 for(
MInt j = 0; j < noWindowCells(n); j++) {
3741 if(!a_isActive(windowCell(n, j)))
continue;
3742 for(
MInt node = 0; node < a_noNodes(windowCell(n, j)); node++) {
3743 MInt nodeIdLocal = a_nodeIdsLocal(windowCell(n, j), node);
3744 for(
MInt dim = 0; dim < nDim; dim++) {
3745 sendBuffers[windowDataOffsets(n) + cnt] = vector[nodeIdLocal * nDim + dim];
3753 for(
MInt n = 0; n < noNeighborDomains(); n++) {
3754 MPI_Issend(&sendBuffers[windowDataOffsets(n)], windowDataPerRank(n), MPI_DOUBLE, neighborDomain(n), 0, mpiComm(),
3755 &mpi_request[n], AT_,
"sendBuffers[n]");
3760 for(
MInt n = 0; n < noNeighborDomains(); n++) {
3761 MPI_Recv(&receiveBuffers[haloDataOffsets(n)], haloDataPerRank(n), MPI_DOUBLE, neighborDomain(n), 0, mpiComm(),
3762 &status, AT_,
"receiveBuffers[n]");
3764 for(
MInt n = 0; n < noNeighborDomains(); n++) {
3765 MPI_Wait(&mpi_request[n], &status, AT_);
3769 for(
MInt n = 0; n < noNeighborDomains(); n++) {
3771 for(
MInt j = 0; j < noHaloCells(n); j++) {
3772 if(!a_isActive(haloCell(n, j)))
continue;
3773 for(
MInt node = 0; node < a_noNodes(haloCell(n, j)); node++) {
3774 MInt nodeIdLocal = a_nodeIdsLocal(haloCell(n, j), node);
3775 for(
MInt dim = 0; dim < nDim; dim++) {
3776 vector[nodeIdLocal * nDim + dim] = receiveBuffers[haloDataOffsets(n) + cnt];
3815 const MInt p = a_pRfnmnt(pCellId);
3820 getDisplacementInterpolationMatrix(pCellId, z, L_coef);
3822 if(m_testRun && m_polyDeg < 1) getDisplacementInterpolationMatrixDebug(pCellId, z, L_coef);
3827 MInt noEdges = (nDim == 2) ? 0 : 12;
3828 MInt noSurfaces = (nDim == 2) ? 4 : 6;
3833 MFloat coord[nDim] = {F0};
3834 MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(pCellId);
3836 for(
MInt d = 0; d < nDim; d++)
3837 coord[d] = c_coordinate(pCellId, d);
3839 for(
MInt d = 0; d < nDim; d++) {
3840 X(d, 0) = coord[d] - cellHalfLength;
3841 X(d, p + 1) = coord[d] + cellHalfLength;
3844 for(
MInt d = 0; d < nDim; d++) {
3845 for(
MInt i = 1; i <
p + 1; i++) {
3846 X(d, i) = coord[d] + Fd::nodePosLobattoPoints(p, i - 1) * cellHalfLength;
3856 for(
MInt node = 0; node < a_noNodes(pCellId); node++) {
3857 if(node < noVertices) {
3858 for(
MInt d = 0; d < nDim; d++) {
3860 if(Fd::vertexPosition(node, d) < F0) {
3865 MFloat L = L_coef(d, node * nDim + d);
3866 x[d] += L * X(d, pos);
3868 }
else if(node < noVertices + noEdges * p) {
3869 MInt edge = (
MInt)floor((node - noVertices) /
p);
3870 MInt l = node - noVertices - edge *
p;
3871 for(
MInt d = 0; d < nDim; d++) {
3873 if(Fd::edgePosition(edge, d) < F0) {
3875 }
else if(Fd::edgePosition(edge, d) > F0) {
3880 MFloat L = L_coef(d, node * nDim + d);
3881 x[d] += L * X(d, pos);
3883 }
else if(node < noVertices + noEdges * p + noSurfaces * p * p) {
3884 MInt surface = (
MInt)floor((node - noVertices - noEdges * p) / (
p *
p));
3886 l[1] = (node - noVertices - noEdges *
p) % (p * p);
3892 for(
MInt d = 0; d < nDim; d++) {
3894 if(Fd::surfacePosition(surface, d) < F0) {
3896 }
else if(Fd::surfacePosition(surface, d) > F0) {
3899 pos = l[counter] + 1;
3902 MFloat L = L_coef(d, node * nDim + d);
3903 x[d] += L * X(d, pos);
3907 l[2] = node - noVertices - noEdges *
p - noSurfaces *
p *
p;
3908 while(l[2] >= (p * p)) {
3917 for(
MInt d = 0; d < nDim; d++) {
3918 MInt pos = l[counter] + 1;
3920 MFloat L = L_coef(d, node * nDim + d);
3921 x[d] += L * X(d, pos);
3942 for(
MInt cell = 0; cell < a_noCells(); cell++) {
3943 if(!a_isActive(cell))
continue;
3944 for(
MInt node = 0; node < a_noNodes(cell); node++) {
3945 MInt nodeId = a_nodeIdsLocal(cell, node);
3946 for(
MInt d = 0; d < nDim; d++) {
3947 m_nodalDisplacements[nodeId * nDim + d] = 10000.0;
3952 for(
MInt cell = 0; cell < a_noCells(); cell++) {
3953 if(!a_isActive(cell))
continue;
3955 for(
MInt node = 0; node < a_noNodes(cell); node++) {
3957 MInt nodeId = a_nodeIdsLocal(cell, node);
3958 getCoordinatesOfNode(node, cell, nodalCoord);
3959 for(
MInt d = 0; d < nDim; d++) {
3960 if(m_nodalDisplacements[nodeId * nDim + d] < 10000.0) {
3961 if(!
approx(m_nodalDisplacements[nodeId * nDim + d], nodalCoord[d], m_eps)) {
3962 stringstream errorMessage;
3963 errorMessage <<
"ERROR in node coordinates" << m_nodalDisplacements[nodeId * nDim + d] <<
" "
3964 << nodalCoord[d] <<
" " << c_coordinate(cell, d) << endl;
3965 mTerm(1, AT_, errorMessage.str());
3968 m_nodalDisplacements[nodeId * nDim + d] = nodalCoord[d];
3973 updateDisplacements();
3991 const MInt p = a_pRfnmnt(pCellId);
3995 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
3996 for(
MInt d = 0; d < nDim; d++) {
4000 getDerivativeOfDisplacementInterpolationMatrix(pCellId, z, L_prime);
4003 MInt noEdges = (nDim == 2) ? 0 : 12;
4004 MInt noSurfaces = (nDim == 2) ? 4 : 6;
4006 MFloat coord[nDim] = {F0};
4007 MFloat cellHalfLength = F1B2 * c_cellLengthAtCell(pCellId);
4009 for(
MInt d = 0; d < nDim; d++)
4010 coord[d] = c_coordinate(pCellId, d);
4012 for(
MInt d = 0; d < nDim; d++) {
4013 X(d, 0) = coord[d] - cellHalfLength;
4014 X(d, p + 1) = coord[d] + cellHalfLength;
4017 for(
MInt d = 0; d < nDim; d++) {
4018 for(
MInt i = 1; i <
p + 1; i++) {
4019 X(d, i) = coord[d] + Fd::nodePosLobattoPoints(p, i - 1) * cellHalfLength;
4023 for(
MInt node = 0; node < a_noNodes(pCellId); node++) {
4024 if(node < noVertices) {
4025 for(
MInt dir = 0; dir < nDim; dir++) {
4026 for(
MInt d = 0; d < nDim; d++) {
4028 if(Fd::vertexPosition(node, d) < F0) {
4033 x_prime(d, dir) += L_prime(node, dir) * X(d, pos);
4036 }
else if(node < noVertices + noEdges * p) {
4037 MInt edge = (
MInt)floor((node - noVertices) /
p);
4038 MInt l = node - noVertices - edge *
p;
4039 for(
MInt dir = 0; dir < nDim; dir++) {
4040 for(
MInt d = 0; d < nDim; d++) {
4042 if(Fd::edgePosition(edge, d) < F0) {
4044 }
else if(Fd::edgePosition(edge, d) > F0) {
4049 x_prime(d, dir) += L_prime(node, dir) * X(d, pos);
4052 }
else if(node < noVertices + noEdges * p + noSurfaces * p * p) {
4053 MInt surface = (
MInt)floor((node - noVertices - noEdges * p) / (
p *
p));
4055 l[1] = (node - noVertices - noEdges *
p) % (p * p);
4060 for(
MInt dir = 0; dir < nDim; dir++) {
4062 for(
MInt d = 0; d < nDim; d++) {
4064 if(Fd::surfacePosition(surface, d) < F0) {
4066 }
else if(Fd::surfacePosition(surface, d) > F0) {
4069 pos = l[counter] + 1;
4072 x_prime(d, dir) += L_prime(node, dir) * X(d, pos);
4077 l[2] = node - noVertices - noEdges *
p - noSurfaces *
p *
p;
4078 while(l[2] >= (p * p)) {
4086 for(
MInt dir = 0; dir < nDim; dir++) {
4088 for(
MInt d = 0; d < nDim; d++) {
4089 MInt pos = l[counter] + 1;
4091 x_prime(d, dir) += L_prime(node, dir) * X(d, pos);
4105 if(a_noNodes(pCellId) !=
IPOW2(nDim)) TERMM(1,
"Not implemented for solver.");
4106 if(a_pRfnmnt(pCellId) != 0) TERMM(1,
"Not implemented for solver.");
4108 for(
MInt dim = 0; dim < nDim; dim++) {
4110 L_coef(i) =
FFPOW2(nDim);
4111 for(
MInt d = 0; d < nDim; d++) {
4112 L_coef(i) *= (F1 + Fd::vertexPosition(i, d) * z[d]);
4114 for(
MInt d = 0; d < nDim; d++) {
4115 MFloat L = L_coef_lagrange(dim, i * nDim + d);
4117 if(!
approx(L_coef(i), L, 1e-14)) {
4118 stringstream errorMessage;
4119 errorMessage <<
"ERROR!! Displacement Interpolation for x " << i <<
" is: " << L_coef(i) <<
" and " << L
4121 mTerm(1, AT_, errorMessage.str());
4124 if(!
approx(F0, L, 1e-14)) {
4125 stringstream errorMessage;
4126 errorMessage <<
"ERROR!! Displacement Interpolation for x " << i <<
" is: " << F0 <<
" and " << L << endl;
4127 mTerm(1, AT_, errorMessage.str());
4141 if(a_noNodes(pCellId) !=
IPOW2(nDim)) TERMM(1,
"Not implemented for solver.");
4142 if(a_pRfnmnt(pCellId) != 0) TERMM(1,
"Not implemented for solver.");
4144 MFloat halfLength = c_cellLengthAtCell(pCellId) * F1B2;
4145 for(
MInt d1 = 0; d1 < nDim; d1++) {
4146 for(
MInt d2 = 0; d2 < nDim; d2++) {
4147 jacobi(d1 * nDim + d2) = F0;
4149 MFloat cCoord = c_coordinate(pCellId, d1) + Fd::vertexPosition(n, d1) * halfLength;
4151 for(
MInt d = 0; d < nDim; d++) {
4153 jac *= Fd::vertexPosition(n, d);
4155 jac *= (F1 + Fd::vertexPosition(n, d) * z[d]);
4158 jacobi(d1 * nDim + d2) += jac;
4162 for(
MInt d1 = 0; d1 < nDim; d1++) {
4163 for(
MInt d2 = 0; d2 < nDim; d2++) {
4164 if(!
approx(jacobi(d1 * nDim + d2), F0, 1e-10)) {
4165 MFloat inv = F1 / jacobi(d1 * nDim + d2);
4166 if(!
approx(inv, jacobi_lagrange(d1 * nDim + d2), 1e-10)) {
4167 stringstream errorMessage;
4168 errorMessage <<
"ERROR!! Jacobi for x" << d1 <<
" and z" << d2 <<
" is: " << jacobi(d1 * nDim + d2) <<
" and "
4169 << F1 / jacobi_lagrange(d1 * nDim + d2) << endl;
4170 mTerm(1, AT_, errorMessage.str());
4186 MFloatScratchSpace L_prime_mul_inv_jac(a_noNodes(pCellId), nDim, AT_,
"L_prime_mul_inv_jac");
4190 if(a_noNodes(pCellId) !=
IPOW2(nDim)) TERMM(1,
"Not implemented for solver.");
4191 if(a_pRfnmnt(pCellId) != 0) TERMM(1,
"Not implemented for solver.");
4193 MFloat halfLength = c_cellLengthAtCell(pCellId) * F1B2;
4194 for(
MInt d1 = 0; d1 < nDim; d1++) {
4195 for(
MInt d2 = 0; d2 < nDim; d2++) {
4196 jacobi(d1 * nDim + d2) = F0;
4198 MFloat cCoord = c_coordinate(pCellId, d1) + Fd::vertexPosition(n, d1) * halfLength;
4200 for(
MInt d = 0; d < nDim; d++) {
4202 jac *= Fd::vertexPosition(n, d);
4204 jac *= (F1 + Fd::vertexPosition(n, d) * z[d]);
4207 jacobi(d1 * nDim + d2) += jac;
4213 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
4214 for(
MInt d1 = 0; d1 < nDim; d1++) {
4216 for(
MInt d2 = 0; d2 < nDim; d2++) {
4218 derivative *= Fd::vertexPosition(n, d2);
4220 derivative *= (F1 + Fd::vertexPosition(n, d2) * z[d2]);
4223 L_prime(n, d1) = derivative;
4227 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
4228 for(
MInt d1 = 0; d1 < nDim; d1++) {
4229 L_prime_mul_inv_jac(n, d1) = F0;
4230 for(
MInt d2 = 0; d2 < nDim; d2++) {
4231 L_prime_mul_inv_jac(n, d1) += (L_prime(n, d2) * jacobi(d2 * nDim + d1));
4236 for(
MInt s = 0; s < nDim; s++) {
4237 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
4238 for(
MInt d = 0; d < nDim; d++) {
4240 strain(s, n * nDim + d) = L_prime_mul_inv_jac(n, d);
4245 for(
MInt s = 0; s < m_noStrains - nDim; s++) {
4246 for(
MInt n = 0; n < a_noNodes(pCellId); n++) {
4247 for(
MInt d = 0; d < nDim; d++) {
4249 if((d + 1) < nDim) {
4250 strain(s + nDim, n * nDim + d) = L_prime_mul_inv_jac(n, d + 1);
4251 strain(s + nDim, n * nDim + d + 1) = L_prime_mul_inv_jac(n, d);
4253 strain(s + nDim, n * nDim + d) = L_prime_mul_inv_jac(n, 0);
4254 strain(s + nDim, n * nDim + 0) = L_prime_mul_inv_jac(n, d);
4260 for(
MInt s = 0; s < m_noStrains; s++) {
4261 for(
MInt n = 0; n < a_noNodes(pCellId) * nDim; n++) {
4262 if(!
approx(strain(s, n), strain_lagrange(s, n), m_eps)) {
4263 stringstream errorMessage;
4264 errorMessage <<
"ERROR!! Strain Interpolation for s " << s <<
" and x " << n <<
" is: " << strain(s, n)
4265 <<
" and " << strain_lagrange(s, n) << endl;
4266 mTerm(1, AT_, errorMessage.str());
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'
This class represents a structure solver using the Finite Cell Method.
void allocateNodeVectors()
void solveSystemOfEquations()
void solveMatrixIteratively(MFloat *A_coeff, MInt **pos, const MInt n)
void updateCellCollectorFromGrid()
void postTimeStep() override
void setCellWeights(MFloat *solverCellWeight) override
Set cell weights.
void fillDisplacementVectorWithCoords()
void reIntAfterRestart(MBool doneRestart)
void saveRestartStrainsOnly(const MChar *fileName, const MChar *gridInputFileName, MInt *recalcIdTree=nullptr)
void getMaterialTensor(MFloatScratchSpace &C, const MInt pCellId, const MInt node=-1)
void initJacobianMatrix()
void getStrainInterpolationMatrix(MFloatScratchSpace &Be, const MInt pCellId, const MFloat *z)
void saveSolverSolution(MBool forceOutput, const MBool finalTimeStep) override
void createCompressedMatrix()
void computeAssembledSystemMatrix(MFloatScratchSpace &Ke, const MInt pCellId)
void createElementToNodeMappingGlobal()
void createElementToNodeMapping()
void exchangeVector(MFloat *vector)
void calcElementDisplacements()
void getInternalLoadsFromStresses()
FcSolver(MInt id, GridProxy &gridProxy_, Geometry< nDim > &geometry_, const MPI_Comm comm)
void getStressesAtPoint(const MInt cellId, const MFloat *z, const MFloat *displ, MFloat *stresses)
void getDisplacementInterpolationMatrix(const MInt pCellId, const MFloat *z, MFloatScratchSpace &x)
void getNodalStiffnessMatrix(const MInt pCellId, const MInt node, MFloatScratchSpace &Ke, MInt *nodePos, MFloat *z, MFloat determinant, const MFloat alpha, const MInt subCellLevel)
void resetDisplacements(const MInt mode=-1)
void calculateStiffnessMatrix()
void getCoordinatesOfNode(MInt node, MInt cell, MFloat *coordinates)
void resetLoadVector(const MInt mode=-1)
void interpolateGeometry(const MInt pCellId, const MFloat *x, MFloat *z)
void getStrainsAtPoint(const MInt cellId, const MFloat *z, const MFloat *displ, MFloat *strains)
void transformToLocal(const MInt pCellId, const MFloat *z, MFloat *x)
void reorderLocalNodeIds()
void exchangeNodeIds(MInt currentDomain)
void updateLoadVector(const MFloat lambda=F1)
void computeAssembledBndryMatrix(MFloatScratchSpace &Bndry, const MInt pCellId)
void finalizeInitSolver() override
void interpolateSubCellGeometry(const MInt pCellId, const MFloat *z, MFloat *x, const MInt subCellLevel, const MFloat *subCellCoord)
void updateDisplacements()
void writeRestartFile(const MBool writeRestart, const MBool writeBackup, const MString gridFileName, MInt *recalcIdTree) override
void getDerivativeOfDisplacementInterpolationMatrix(const MInt pCellId, const MFloat *z, MFloatScratchSpace &x)
void calcElementStrains()
void getElementMatrix(MFloatScratchSpace &Ke, const MInt pCellId, const MFloat alpha, const MInt subCellLevel, const MFloat *subCellCoord=nullptr)
void preTimeStep() override
void interpolateGeometryDebug(const MInt pCellId, const MFloat *z, MFloat *x)
void setIntegrationWeights()
void getStrainInterpolationMatrixDebug(const MInt pCellId, const MFloat *z, MFloatScratchSpace &strain_lagrange)
void lagrangianPointsJacobi(const MInt pCellId, const MFloat *z, MFloatScratchSpace &x)
void getDisplacementInterpolationMatrixDebug(const MInt pCellId, const MFloat *z, MFloatScratchSpace &L_coef_lagrange)
void getDisplacementsAtPoint(const MInt cellId, const MFloat *z, const MFloat *displ, MFloat *result)
void calcElementStresses()
void solveMatrixIterativelyPreCon(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
void getJacobiMatrixDebug(const MInt pCellId, const MFloat *z, MFloatScratchSpace &jacobi_lagrange)
MBool prepareRestart(MBool writeRestart, MBool &writeGridRestart) override
Prepare the solvers for a grid-restart.
void assembleFinalMatrix()
This class is a ScratchSpace.
void fill(T val)
fill the scratch with a given value
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
@ EQUIDIST_LAGRANGE_INTERP
@ EQUIDIST_LEGENDRE_INTERP
void mTerm(const MInt errorCode, const MString &location, const MString &message)
MBool approx(const T &, const U &, const T)
constexpr MLong IPOW2(MInt x)
constexpr MFloat FFPOW2(MInt x)
std::basic_string< char > MString
int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status, const MString &name, const MString &varname)
same as MPI_Recv
int MPI_Barrier(MPI_Comm comm, const MString &name)
same as MPI_Barrier
int MPI_Issend(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request, const MString &name, const MString &varname)
same as MPI_Issend
int MPI_Wait(MPI_Request *request, MPI_Status *status, const MString &name)
same as MPI_Wait
int MPI_Allreduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm, const MString &name, const MString &sndvarname, const MString &rcvvarname)
same as MPI_Allreduce
constexpr std::underlying_type< FcCell >::type p(const FcCell property)
Converts property name to underlying integer value.
IdType index(const FloatType *const x, const IdType level)
Return Hilbert index for given location and level in 2D or 3D.
MFloat determinant(std::array< T, N > &m)
void multiplySparseMatrixVector(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
void invert(MFloat *A, const MInt m, const MInt n)
void solveSparseMatrix(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
void solveSparseMatrixIterative(MFloat *A_coeff, MInt **pos, const MInt n, const MInt m, MFloat *b, MFloat *x)
MFloat norm(const std::array< T, N > &u)
void multiplyMatrices(MFloatScratchSpace &m1, MFloatScratchSpace &m2, MFloatScratchSpace &result, MInt m1_n, MInt m1_m, MInt m2_n, MInt m2_m)
void calcEigenValues(MFloat A[3][3], MFloat w[3])
void exchangeData(const MInt noNghbrDomains, const MInt *const nghbrDomains, const MInt *const noHaloCells, const MInt **const, const MInt *const noWindowCells, const MInt **const windowCells, const MPI_Comm comm, const U *const data, U *const haloBuffer, const MInt noDat=1)
Generic exchange of data.
Namespace for auxiliary functions/classes.
PARALLELIO_DEFAULT_BACKEND ParallelIo