diff --git a/src/core_landice/Registry.xml b/src/core_landice/Registry.xml
index 7062959278..c534626142 100644
--- a/src/core_landice/Registry.xml
+++ b/src/core_landice/Registry.xml
@@ -931,7 +931,7 @@ is the value of that variable from the *previous* time level!
-
+
+
diff --git a/src/core_landice/analysis_members/mpas_li_global_stats.F b/src/core_landice/analysis_members/mpas_li_global_stats.F
index 41ddc9aebd..b367875979 100644
--- a/src/core_landice/analysis_members/mpas_li_global_stats.F
+++ b/src/core_landice/analysis_members/mpas_li_global_stats.F
@@ -283,7 +283,7 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err)
call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel=1)
call mpas_pool_get_array(geometryPool, 'sfcMassBalApplied', sfcMassBalApplied)
call mpas_pool_get_array(geometryPool, 'groundedSfcMassBalApplied', groundedSfcMassBalApplied)
call mpas_pool_get_array(geometryPool, 'basalMassBal', basalMassBal)
diff --git a/src/core_landice/analysis_members/mpas_li_regional_stats.F b/src/core_landice/analysis_members/mpas_li_regional_stats.F
index 0e0543df57..4c6df7def9 100644
--- a/src/core_landice/analysis_members/mpas_li_regional_stats.F
+++ b/src/core_landice/analysis_members/mpas_li_regional_stats.F
@@ -275,7 +275,7 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err)
call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel=1)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
call mpas_pool_get_array(geometryPool, 'sfcMassBalApplied', sfcMassBalApplied)
call mpas_pool_get_array(geometryPool, 'groundedSfcMassBalApplied', groundedSfcMassBalApplied)
diff --git a/src/core_landice/mode_forward/Interface_velocity_solver.cpp b/src/core_landice/mode_forward/Interface_velocity_solver.cpp
index 6612b7bba0..671ed32bcd 100644
--- a/src/core_landice/mode_forward/Interface_velocity_solver.cpp
+++ b/src/core_landice/mode_forward/Interface_velocity_solver.cpp
@@ -14,31 +14,29 @@ distributed with this code, or at http://mpas-dev.github.com/license.html
#include
#include
#include
+#include
+#include
#include "Interface_velocity_solver.hpp"
-//#include
-//#include
-//#include
// ===================================================
//! Namespaces
// ===================================================
-//typedef std::list exchangeList_Type;
+#define changeTrianglesOwnership
+
// ice_problem pointer
int Ordering = 0; //ordering ==0 means that the mesh is extruded layerwise, whereas ordering==1 means that the mesh is extruded columnwise.
MPI_Comm comm, reducedComm;
bool isDomainEmpty = true;
-bool initialize_velocity = true;
bool first_time_step = true;
int nCells_F, nEdges_F, nVertices_F;
int nCellsSolve_F, nEdgesSolve_F, nVerticesSolve_F;
-int nVertices, nEdges, nTriangles, nGlobalVertices, nGlobalEdges,
- nGlobalTriangles;
+int nVertices, nEdges, nTriangles, globalVertexStride, globalEdgeStride,globalTriangleStride;
int maxNEdgesOnCell_F;
int const *cellsOnEdge_F, *cellsOnVertex_F, *verticesOnCell_F,
- *verticesOnEdge_F, *edgesOnCell_F, *indexToCellID_F, *nEdgesOnCells_F,
+ *verticesOnEdge_F, *edgesOnCell_F, *indexToCellID_F, *indexToEdgeID_F, *indexToVertexID_F, *nEdgesOnCells_F,
*verticesMask_F, *cellsMask_F, *dirichletCellsMask_F, *floatingEdgesMask_F;
std::vector layersRatio, levelsNormalizedThickness;
int nLayers;
@@ -63,13 +61,13 @@ int original_stderr; // the location of stderr before we captured it
int Interface_stdout; // the location of stdout as we use it here
//void *phgGrid = 0;
-std::vector edgesToReceive, fCellsToReceive, indexToTriangleID,
- verticesOnTria, trianglesOnEdge, trianglesPositionsOnEdge, verticesOnEdge,
- trianglesProcIds, reduced_ranks;
-std::vector indexToVertexID, vertexToFCell, triangleToFVertex, indexToEdgeID, edgeToFEdge,
- mask, fVertexToTriangleID, fCellToVertex, floatingEdgesIds, dirichletNodesIDs;
-std::vector temperatureOnTetra, dissipationHeatOnTetra, velocityOnVertices, velocityOnCells,
- elevationData, thicknessData, betaData, bedTopographyData, stiffnessFactorData, effecPressData, temperatureData, smbData, thicknessOnCells;
+std::vector indexToTriangleID,
+ verticesOnTria, trianglesOnEdge, verticesOnEdge,
+ trianglesProcIds, reduced_ranks;
+std::vector indexToVertexID, vertexToFCell, vertexProcIDs, triangleToFVertex, indexToEdgeID, edgeToFEdge,
+ fVertexToTriangleID, fCellToVertex, floatingEdgesIds, dirichletNodesIDs;
+std::vector dissipationHeatOnPrisms, velocityOnVertices, velocityOnCells,
+ elevationData, thicknessData, betaData, bedTopographyData, stiffnessFactorData, effecPressData, temperatureDataOnPrisms, smbData, thicknessOnCells;
std::vector isVertexBoundary, isBoundaryEdge;
// only needed for creating ASCII mesh
@@ -86,8 +84,8 @@ double radius;
exchangeList_Type const *sendCellsList_F = 0, *recvCellsList_F = 0;
exchangeList_Type const *sendEdgesList_F = 0, *recvEdgesList_F = 0;
exchangeList_Type const *sendVerticesList_F = 0, *recvVerticesList_F = 0;
-exchangeList_Type sendCellsListReversed, recvCellsListReversed,
- sendEdgesListReversed, recvEdgesListReversed;
+exchangeList_Type sendVerticesListReversed, recvVerticesListReversed,
+ sendCellsListReversed, recvCellsListReversed;
exchange::exchange(int _procID, int const* vec_first, int const* vec_last,
int fieldDim) :
@@ -106,7 +104,7 @@ int velocity_solver_init_mpi(int* fComm) {
// get MPI_Comm from Fortran
comm = MPI_Comm_f2c(*fComm);
reducedComm = MPI_COMM_NULL; // initialize to null so we can check if set
- return velocity_solver_init_mpi__(fComm);
+ return velocity_solver_init_mpi__(comm);
}
@@ -131,11 +129,6 @@ void velocity_solver_export_2d_data(double const* lowerSurface_F,
double const* thickness_F, double const* beta_F) {
if (isDomainEmpty)
return;
-#ifdef LIFEV
- import2DFields(lowerSurface_F, thickness_F, beta_F, minThickneess);
- velocity_solver_export_2d_data__(reducedComm, elevationData, thicknessData,
- betaData, indexToVertexID);
-#endif
}
void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
@@ -146,6 +139,8 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
int const* _verticesOnCell_F, int const* _verticesOnEdge_F,
int const* _edgesOnCell_F, int const* _nEdgesOnCells_F,
int const* _indexToCellID_F,
+ int const* _indexToEdgeID_F,
+ int const* _indexToVertexID_F,
double const* _xCell_F, double const* _yCell_F, double const* _zCell_F,
double const* _xVertex_F, double const* _yVertex_F, double const* _zVertex_F,
double const* _areaTriangle_F,
@@ -168,7 +163,9 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
verticesOnEdge_F = _verticesOnEdge_F;
edgesOnCell_F = _edgesOnCell_F;
nEdgesOnCells_F = _nEdgesOnCells_F;
+ indexToEdgeID_F = _indexToEdgeID_F;
indexToCellID_F = _indexToCellID_F;
+ indexToVertexID_F = _indexToVertexID_F;
xCell_F = _xCell_F;
yCell_F = _yCell_F;
zCell_F = _zCell_F;
@@ -176,7 +173,6 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
yVertex_F = _yVertex_F;
zVertex_F = _zVertex_F;
areaTriangle_F = _areaTriangle_F;
- mask.resize(nVertices_F);
thicknessOnCells.resize(nCellsSolve_F);
@@ -189,9 +185,6 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
recvVerticesList_F = new exchangeList_Type(
unpackMpiArray(recvVerticesArray_F));
- trianglesProcIds.resize(nVertices_F);
- getProcIds(trianglesProcIds, recvVerticesList_F);
-
if (radius > 10) {
xCellProjected.resize(nCells_F);
yCellProjected.resize(nCells_F);
@@ -210,23 +203,6 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
}
void velocity_solver_init_l1l2(double const* levelsRatio_F) {
-#ifdef LIFEV
- velocityOnVertices.resize(2 * nVertices * (nLayers + 1), 0.);
- velocityOnCells.resize(2 * nCells_F * (nLayers + 1), 0.);
-
- if (isDomainEmpty)
- return;
-
- layersRatio.resize(nLayers);
- // !!Indexing of layers is reversed
- for (int i = 0; i < nLayers; i++)
- layersRatio[i] = levelsRatio_F[nLayers - 1 - i];
- //std::copy(levelsRatio_F, levelsRatio_F+nLayers, layersRatio.begin());
- mapCellsToVertices(velocityOnCells, velocityOnVertices, 2, nLayers, Ordering);
-
- velocity_solver_init_l1l2__(layersRatio, velocityOnVertices, initialize_velocity);
- initialize_velocity = false;
-#endif
}
@@ -236,82 +212,9 @@ void velocity_solver_solve_l1l2(double const* lowerSurface_F,
double const* thickness_F, double const* beta_F, double const* temperature_F,
double* const dirichletVelocityXValue, double* const dirichletVelocitYValue,
double* u_normal_F, double* xVelocityOnCell, double* yVelocityOnCell) {
-
-#ifdef LIFEV
-
- std::fill(u_normal_F, u_normal_F + nEdges_F * (nLayers+1), 0.);
-
- double localSum(0), sum(0);
-
- for (int i = 0; i < nCellsSolve_F; i++) {
- localSum = std::max(localSum,
- std::fabs(thickness_F[i] - thicknessOnCells[i]));
- }
-
- MPI_Allreduce(&localSum, &sum, 1, MPI_DOUBLE, MPI_MAX, comm);
-
- std::cout << "Thickness change: " << sum << std::endl;
- std::copy(thickness_F, thickness_F + nCellsSolve_F, &thicknessOnCells[0]);
-
- if (!isDomainEmpty) {
- std::vector temperatureData(nLayers * nVertices);
-
- import2DFields(lowerSurface_F, thickness_F, beta_F, minThickness);
-
- for (int index = 0; index < nVertices; index++) {
- int iCell = vertexToFCell[index];
- for (int il = 0; il < nLayers; il++) {
- temperatureData[index + il * nVertices] = temperature_F[iCell * nLayers
- + (nLayers - il - 1)];
- }
- }
-
-
- velocity_solver_solve_l1l2__(elevationData, thicknessData, betaData,
- temperatureData, indexToVertexID, velocityOnVertices);
- }
-
-
- mapVerticesToCells (velocityOnVertices, &velocityOnCells[0], 2, nLayers, Ordering);
-
- //computing x, yVelocityOnCell
- int sizeVelOnCell = nCells_F * (nLayers + 1);
- for(int iCell=0; iCell regulThk(thicknessData);
- for (int index = 0; index < nVertices; index++)
- regulThk[index] = std::max(1e-4, thicknessData[index]);
-
- std::vector mpasIndexToVertexID(nVertices);
- for (int i = 0; i < nVertices; i++) {
- mpasIndexToVertexID[i] = indexToCellID_F[vertexToFCell[i]];
- }
-#ifdef LIFEV
- velocity_solver_export_l1l2_velocity__(layersRatio, elevationData, regulThk, mpasIndexToVertexID, reducedComm);
-#endif
-}
+void velocity_solver_export_l1l2_velocity() {}
void velocity_solver_init_fo(double const *levelsRatio_F) {
@@ -325,16 +228,8 @@ void velocity_solver_init_fo(double const *levelsRatio_F) {
// !!Indexing of layers is reversed
for (int i = 0; i < nLayers; i++)
layersRatio[i] = levelsRatio_F[nLayers - 1 - i];
- //std::copy(levelsRatio_F, levelsRatio_F+nLayers, layersRatio.begin());
-
mapCellsToVertices(velocityOnCells, velocityOnVertices, 2, nLayers, Ordering);
-
-#ifdef LIFEV
- velocity_solver_init_fo__(layersRatio, velocityOnVertices, indexToVertexID, initialize_velocity);
-#endif
- // iceProblemPtr->initializeSolverFO(layersRatio, velocityOnVertices, thicknessData, elevationData, indexToVertexID, initialize_velocity);
- initialize_velocity = false;
}
void velocity_solver_solve_fo(double const* bedTopography_F, double const* lowerSurface_F,
@@ -368,53 +263,30 @@ void velocity_solver_solve_fo(double const* bedTopography_F, double const* lower
if (!isDomainEmpty) {
-#ifdef LIFEV
- double localSum(0), sum(0);
-
- for (int i = 0; i < nCellsSolve_F; i++) {
- localSum = std::max(localSum,
- std::fabs(thickness_F[i] - thicknessOnCells[i]));
- }
-
- MPI_Allreduce(&localSum, &sum, 1, MPI_DOUBLE, MPI_MAX, comm);
-
- std::cout << "Thickness change: " << sum << std::endl;
- std::copy(thickness_F, thickness_F + nCellsSolve_F, &thicknessOnCells[0]);
-#endif
-
-
-
std::map bdExtensionMap;
- import2DFields(bdExtensionMap, bedTopography_F, lowerSurface_F, thickness_F, beta_F, stiffnessFactor_F, effecPress_F, temperature_F, smb_F, minThickness);
+ importFields(bdExtensionMap, bedTopography_F, lowerSurface_F, thickness_F, beta_F, stiffnessFactor_F, effecPress_F, temperature_F, smb_F, minThickness);
std::vector regulThk(thicknessData);
for (int index = 0; index < nVertices; index++)
regulThk[index] = std::max(1e-4, thicknessData[index]);
- importP0Temperature();
-
- dissipationHeatOnTetra.resize(3 * nLayers * indexToTriangleID.size());
+ dissipationHeatOnPrisms.resize(nLayers * indexToTriangleID.size());
std::cout << "\n\nTimeStep: "<< *deltat << "\n\n"<< std::endl;
double dt = (*deltat)/secondsInAYear;
int albany_error;
- velocity_solver_solve_fo__(nLayers, nGlobalVertices, nGlobalTriangles,
+ velocity_solver_solve_fo__(nLayers, globalVertexStride, globalTriangleStride,
Ordering, first_time_step, indexToVertexID, indexToTriangleID, minBeta,
regulThk, levelsNormalizedThickness, elevationData, thicknessData,
betaData, bedTopographyData, smbData,
stiffnessFactorData, effecPressData,
- temperatureOnTetra, dissipationHeatOnTetra, velocityOnVertices,
+ temperatureDataOnPrisms, dissipationHeatOnPrisms, velocityOnVertices,
albany_error, dt);
*error=albany_error;
}
-
- exportDissipationHeat(dissipation_heat_F);
- std::vector mpasIndexToVertexID(nVertices);
- for (int i = 0; i < nVertices; i++) {
- mpasIndexToVertexID[i] = indexToCellID_F[vertexToFCell[i]];
- }
+ exportDissipationHeat(dissipation_heat_F);
mapVerticesToCells(velocityOnVertices, &velocityOnCells[0], 2, nLayers,
Ordering);
@@ -428,81 +300,15 @@ void velocity_solver_solve_fo(double const* bedTopography_F, double const* lower
xVelocityOnCell[indexReversed] = velocityOnCells[index];
yVelocityOnCell[indexReversed] = velocityOnCells[index+sizeVelOnCell];
}
-
- if (!isDomainEmpty)
get_prism_velocity_on_FEdges(u_normal_F, velocityOnCells, edgeToFEdge);
-
+ allToAll(u_normal_F, sendEdgesList_F, recvEdgesList_F, nLayers+1);
std::vector velOnEdges(nEdges * (nLayers+1));
for (int i = 0; i < nEdges; i++) {
for (int il = 0; il < nLayers+1; il++) {
velOnEdges[i * (nLayers+1) + il] = u_normal_F[edgeToFEdge[i] * (nLayers+1) + il];
}
}
-
- allToAll(u_normal_F, &sendEdgesListReversed, &recvEdgesListReversed, nLayers+1);
-
- allToAll(u_normal_F, sendEdgesList_F, recvEdgesList_F, nLayers+1);
-
first_time_step = false;
-
-#ifdef LIFEV
-
- std::vector edgesProcId(nEdges_F), trianglesProcIds(nVertices_F);
- getProcIds(edgesProcId, recvEdgesList_F);
- getProcIds(trianglesProcIds, recvVerticesList_F);
-
- int localSumInt(0), sumInt(0);
-
- for (int i = 0; i < nEdges; i++) {
- for (int il = 0; il < 1; il++) {
- if (std::fabs(
- velOnEdges[i * (nLayers+1) + il]
- - u_normal_F[edgeToFEdge[i] * nLayers + il]) > 1e-9)
- // if(edgeToFEdge[i]>nEdgesSolve_F)
- {
- localSumInt++;
- int edge = edgeToFEdge[i];
- int gEdge = indexToEdgeID[i];
- ID fVertex0 = verticesOnEdge_F[2 * edge] - 1;
- ID fVertex1 = verticesOnEdge_F[2 * edge + 1] - 1;
- ID triaId0 = fVertexToTriangleID[fVertex0];
- ID triaId1 = fVertexToTriangleID[fVertex1];
- ID procTria0 = trianglesProcIds[fVertex0];
- ID procTria1 = trianglesProcIds[fVertex1];
- std::cout << "vs( " << velOnEdges[i * (nLayers+1) + il] << ", "
- << u_normal_F[edgeToFEdge[i] * nLayers + il] << ") ";
- std::cout << "edge: " << edge << ", gEdge: " << gEdge << ", on proc: "
- << edgesProcId[edgeToFEdge[i]];
- if (triaId0 != NotAnId) {
- std::cout << ". first tria0: " << triaId0 << " on proc: "
- << procTria0;
- }
- if (triaId1 != NotAnId) {
- std::cout << ".. second tria0:" << std::endl;
- }
- if ((triaId0 == NotAnId) || (triaId1 == NotAnId)) {
- std::cout << ". and to Tria: " << triaId1 << " on proc: " << procTria1
- << std::endl;
- }
-
- }
-
- //localSum = std::max(localSum, std::fabs(velOnEdges[i*nLayers+il] - u_normal_F[edgeToFEdge[i]*nLayers+il]));
- }
- }
-
- MPI_Allreduce(&localSumInt, &sumInt, 1, MPI_INT, MPI_SUM, comm);
-
- int localNum(sendEdgesListReversed.size()), num(0);
-
- MPI_Allreduce(&localNum, &num, 1, MPI_INT, MPI_SUM, comm);
-
- std::cout << "Edges change: " << sumInt << " " << num << std::endl;
-
-#endif
-
-
-
}
@@ -526,7 +332,7 @@ void velocity_solver_finalize() {
/*duality:
*
- * mpas(F) | lifev
+ * mpas(F) | Albany LandIce (C++)
* ---------|---------
* cell | vertex
* vertex | triangle
@@ -536,7 +342,6 @@ void velocity_solver_finalize() {
void velocity_solver_compute_2d_grid(int const* _verticesMask_F, int const* _cellsMask_F, int const* _dirichletCellsMask_F, int const* _floatingEdgesMask_F) {
int numProcs, me;
-
verticesMask_F = _verticesMask_F;
cellsMask_F = _cellsMask_F;
verticesMask_F = _verticesMask_F;
@@ -549,88 +354,156 @@ void velocity_solver_compute_2d_grid(int const* _verticesMask_F, int const* _cel
numProcs + 1), globalOffsetVertices(numProcs + 1), globalOffsetEdge(
numProcs + 1);
+
+ // First, we compute the FE triangles belonging to this processor.
+ // If changeTrianglesOwnership is not define, the triangles belonging to this
+ // processor will be the subset of the triangles (MPAS vertices) owned by this proc
+ // that contain dynamic ice.
+ // If changeTrianglesOwnership is define, we rearrange the ownership of the triangles
+ // to improve the quality of the FE mesh and avoid corner cases (see below).
+
triangleToFVertex.clear();
triangleToFVertex.reserve(nVertices_F);
std::vector fVertexToTriangle(nVertices_F, NotAnId);
- bool changed = false;
- for (int i(0); i < nVerticesSolve_F; i++) {
- if ((verticesMask_F[i] & dynamic_ice_bit_value) && !isGhostTriangle(i)) {
- fVertexToTriangle[i] = triangleToFVertex.size();
- triangleToFVertex.push_back(i);
- }
- changed = changed || (verticesMask_F[i] != mask[i]);
- }
- for (int i(0); i < nVertices_F; i++)
- mask[i] = verticesMask_F[i];
+ //vector containing proc ranks for owned and shared FE triangles
+ trianglesProcIds.assign(nVertices_F,NotAnId);
+
+ //vector containing proc ranks for owned and shared MPAS cells
+ std::vector fCellsProcIds(nCells_F);
+ getProcIds(fCellsProcIds, recvCellsList_F);
+#ifdef changeTrianglesOwnership
+ std::vector fVerticesProcIds(nVertices_F);
+ getProcIds(fVerticesProcIds, recvVerticesList_F);
+ for (int i(0); i < nVertices_F; i++) {
+ int cellWithMinID=nCellsSolve_F;
+ if ((verticesMask_F[i] & dynamic_ice_bit_value)) {
+ int minCellId = std::numeric_limits::max();
+ int minCellIdProc(0);
+
+ int cellProc[3];
+ bool invalidCell=false;
+ for (int j = 0; j < 3; j++) {
+ int iCell = cellsOnVertex_F[3 * i + j] - 1;
+ if(iCell >= nCells_F) {
+ invalidCell = true;
+ break;
+ }
+ int cellID = indexToCellID_F[iCell];
+ cellProc[j] = fCellsProcIds[iCell];
+ if(cellID < minCellId) {
+ minCellId = cellID;
+ cellWithMinID = iCell;
+ minCellIdProc = cellProc[j];
+ }
+ }
+
+ if(invalidCell) continue;
+
+ // the proc that owns at least 2 nodes of the triangle i. If all nodes belong to different procs, procOwns2Nodes is set to -1
+ int procOwns2Nodes = ((cellProc[0] == cellProc[1]) || (cellProc[0] == cellProc[2])) ? cellProc[0] :
+ (cellProc[1] == cellProc[2]) ? cellProc[1] : -1;
- if (changed)
- std::cout << "mask changed!!" << std::endl;
+ int vertexProc = fVerticesProcIds[i];
+ bool triangleOwnsANode = (cellProc[0] == vertexProc) || (cellProc[1] == vertexProc) || (cellProc[2] == vertexProc);
- if ((me == 0) && (triangleToFVertex.size() == 0))
- for (int i(0); i < nVerticesSolve_F; i++) {
- if (!isGhostTriangle(i)) {
+ //A triangle will be owned by a proc if:
+ // 1. the proc owns at least 2 nodes of the triangle associated to that vertex, OR
+ // 2. all the nodes of the triangle belong to three different procs, and the proc owns the fortran vertex and a node OR
+ // 3. the three nodes of the triangle and the fortran vertex belong to four different procs, and the proc owns the node with the minimum ID
+
+ trianglesProcIds[i] = (procOwns2Nodes != -1) ? procOwns2Nodes :
+ triangleOwnsANode ? vertexProc :
+ minCellIdProc;
+
+ if (trianglesProcIds[i] == me) {
fVertexToTriangle[i] = triangleToFVertex.size();
triangleToFVertex.push_back(i);
- break;
- }
+ }
}
+ }
+#else
+ //in this case we just set the proc ranks for owned and shared FE triangles to the be the same as MPAS owned and shared vertices
+ getProcIds(trianglesProcIds, recvVerticesList_F);
+ for (int i(0); i < nVerticesSolve_F; i++) {
+ if (verticesMask_F[i] & dynamic_ice_bit_value) {
+ fVertexToTriangle[i] = triangleToFVertex.size();
+ triangleToFVertex.push_back(i);
+ }
+ }
+#endif
nTriangles = triangleToFVertex.size();
+ //Initialize the ice sheet problem with the number of FE triangles on this prov
initialize_iceProblem(nTriangles);
- //Compute the global number of triangles, and the localOffset on the local processor, such that a globalID = localOffset + index
- int localOffset(0);
- nGlobalTriangles = 0;
- computeLocalOffset(nTriangles, localOffset, nGlobalTriangles);
-
- //Communicate the globalIDs, computed locally, to the other processors.
- indexToTriangleID.resize(nTriangles);
-
- //To make local, not used
+ //Create a list of global IDs for FE triangles, using MPAS vertices IDs
fVertexToTriangleID.assign(nVertices_F, NotAnId);
- // std::vector fVertexToTriangleID(nVertices_F, NotAnId);
- for (int index(0); index < nTriangles; index++)
- fVertexToTriangleID[triangleToFVertex[index]] = index + localOffset;
-
+ for (int index(0); index < nTriangles; index++) {
+ fVertexToTriangleID[triangleToFVertex[index]] = indexToVertexID_F[triangleToFVertex[index]];
+ }
+
+#ifdef changeTrianglesOwnership
+ // because we change the ownership of some triangles, we need to first communicate back to the processors that used to own those triangles
+ // the data of the newly owned triangles. We do this by defining "reversed" send and receive lists, communicate back using those lists, and
+ // then communicate "forward" using the usual send and receive lists.
+ // We could join these two step in one communication, but for the moment we do that separately
+ createReverseExchangeLists(sendVerticesListReversed, recvVerticesListReversed, trianglesProcIds, indexToVertexID_F, recvVerticesList_F);
+ allToAll(fVertexToTriangleID, &sendVerticesListReversed, &recvVerticesListReversed);
+ allToAll(fVertexToTriangle, &sendVerticesListReversed, &recvVerticesListReversed);
+ allToAll(trianglesProcIds, sendVerticesList_F, recvVerticesList_F);
+#endif
allToAll(fVertexToTriangleID, sendVerticesList_F, recvVerticesList_F);
+ allToAll(fVertexToTriangle, sendVerticesList_F, recvVerticesList_F);
- for (int index(0); index < nTriangles; index++)
+ //we define the vector of global triangles Ids and compute the stride between the largest and the smallest Id globally
+ //This will be needed by the velocity solver to create the 3D FE mesh.
+ indexToTriangleID.resize(nTriangles);
+ int maxTriangleID=std::numeric_limits::min(), minTriangleID=std::numeric_limits::max(), maxGlobalTriangleID, minGlobalTriangleID;
+ for (int index(0); index < nTriangles; index++) {
indexToTriangleID[index] = fVertexToTriangleID[triangleToFVertex[index]];
+ maxTriangleID = (indexToTriangleID[index] > maxTriangleID) ? indexToTriangleID[index] : maxTriangleID;
+ minTriangleID = (indexToTriangleID[index] < minTriangleID) ? indexToTriangleID[index] : minTriangleID;
+ }
- //Compute triangle edges
- std::vector fEdgeToEdge(nEdges_F), edgesToSend, trianglesProcIds(
- nVertices_F);
- getProcIds(trianglesProcIds, recvVerticesList_F);
+ MPI_Allreduce(&maxTriangleID, &maxGlobalTriangleID, 1, MPI_INT, MPI_MAX, comm);
+ MPI_Allreduce(&minTriangleID, &minGlobalTriangleID, 1, MPI_INT, MPI_MIN, comm);
+ globalTriangleStride = maxGlobalTriangleID - minGlobalTriangleID +1;
- int interfaceSize(0);
+ // Second, we compute the FE edges belonging to the FE triangles owned by this processor.
+ // We first compute boundary edges, and then all the other edges.
+ std::vector fEdgeToEdge(nEdges_F);
std::vector fEdgeToEdgeID(nEdges_F, NotAnId);
- edgesToReceive.clear();
edgeToFEdge.clear();
isBoundaryEdge.clear();
trianglesOnEdge.clear();
- edgesToReceive.reserve(nEdges_F - nEdgesSolve_F);
edgeToFEdge.reserve(nEdges_F);
trianglesOnEdge.reserve(nEdges_F * 2);
- edgesToSend.reserve(nEdgesSolve_F);
isBoundaryEdge.reserve(nEdges_F);
- //first, we compute boundary edges (boundary edges must be the first edges)
+ //we compute boundary edges (boundary edges must be the first edges)
for (int i = 0; i < nEdges_F; i++) {
ID fVertex1(verticesOnEdge_F[2 * i] - 1), fVertex2(
verticesOnEdge_F[2 * i + 1] - 1);
+
+ // skip the (shared) edge when the associated MPAS vertices are not valid
+ if((fVertex1>=nVertices_F) || (fVertex2>=nVertices_F))
+ continue;
+
ID triaId_1 = fVertexToTriangleID[fVertex1];
ID triaId_2 = fVertexToTriangleID[fVertex2];
bool isboundary = (triaId_1 == NotAnId) || (triaId_2 == NotAnId);
ID iTria1 = fVertexToTriangle[fVertex1];
ID iTria2 = fVertexToTriangle[fVertex2];
- if (iTria1 == NotAnId)
+ if (trianglesProcIds[fVertex1] != me) {
+ std::swap(fVertex1, fVertex2);
std::swap(iTria1, iTria2);
- bool belongsToLocalTriangle = (iTria1 != NotAnId) || (iTria2 != NotAnId);
+ }
+ bool belongsToLocalTriangle = (trianglesProcIds[fVertex1] == me);
if (belongsToLocalTriangle) {
if (isboundary) {
@@ -639,36 +512,36 @@ void velocity_solver_compute_2d_grid(int const* _verticesMask_F, int const* _cel
trianglesOnEdge.push_back(iTria1);
trianglesOnEdge.push_back(iTria2);
isBoundaryEdge.push_back(true);
- } else
- interfaceSize += (iTria2 == NotAnId);
+ }
}
}
numBoundaryEdges = edgeToFEdge.size();
- //procOnInterfaceEdge contains the pairs .
- std::vector < std::pair > procOnInterfaceEdge;
- procOnInterfaceEdge.reserve(interfaceSize);
-
//then, we compute the other edges
for (int i = 0; i < nEdges_F; i++) {
ID fVertex1(verticesOnEdge_F[2 * i] - 1), fVertex2(
verticesOnEdge_F[2 * i + 1] - 1);
+
+ // skip the (shared) edge when the associated MPAS vertices are not valid
+ if((fVertex1>=nVertices_F) || (fVertex2>=nVertices_F))
+ continue;
+
ID iTria1 = fVertexToTriangle[fVertex1];
ID iTria2 = fVertexToTriangle[fVertex2];
ID triaId_1 = fVertexToTriangleID[fVertex1]; //global Triangle
ID triaId_2 = fVertexToTriangleID[fVertex2]; //global Triangle
- if (iTria1 == NotAnId) {
- std::swap(iTria1, iTria2);
+ if (trianglesProcIds[fVertex1] != me) {
std::swap(fVertex1, fVertex2);
+ std::swap(iTria1, iTria2);
}
bool belongsToAnyTriangle = (triaId_1 != NotAnId) || (triaId_2 != NotAnId);
bool isboundary = (triaId_1 == NotAnId) || (triaId_2 == NotAnId);
- bool belongsToLocalTriangle = (iTria1 != NotAnId);
+ bool belongsToLocalTriangle = (trianglesProcIds[fVertex1] == me);
bool isMine = i < nEdgesSolve_F;
if (belongsToLocalTriangle && !isboundary) {
@@ -677,42 +550,33 @@ void velocity_solver_compute_2d_grid(int const* _verticesMask_F, int const* _cel
trianglesOnEdge.push_back(iTria1);
trianglesOnEdge.push_back(iTria2);
isBoundaryEdge.push_back(false);
- if (iTria2 == NotAnId)
- procOnInterfaceEdge.push_back(
- std::make_pair(fEdgeToEdge[i], trianglesProcIds[fVertex2]));
- }
-
- if (belongsToAnyTriangle && isMine) {
- edgesToSend.push_back(i);
- if (!belongsToLocalTriangle)
- edgesToReceive.push_back(i);
}
-
}
- //Compute the global number of edges, and the localOffset on the local processor, such that a globalID = localOffset + index
- computeLocalOffset(edgesToSend.size(), localOffset, nGlobalEdges);
-
- //Communicate the globalIDs, computed locally, to the other processors.
- for (ID index = 0; index < edgesToSend.size(); index++)
- fEdgeToEdgeID[edgesToSend[index]] = index + localOffset;
-
- allToAll(fEdgeToEdgeID, sendEdgesList_F, recvEdgesList_F);
+ for (int fEdge = 0; fEdge < nEdges_F; fEdge++)
+ fEdgeToEdgeID[fEdge] = indexToEdgeID_F[fEdge];
nEdges = edgeToFEdge.size();
indexToEdgeID.resize(nEdges);
floatingEdgesIds.clear();
floatingEdgesIds.reserve(nEdges);
+ int maxEdgeID=std::numeric_limits::min(), minEdgeID=std::numeric_limits::max(), maxGlobalEdgeID, minGlobalEdgeID;
for (int index = 0; index < nEdges; index++) {
int fEdge = edgeToFEdge[index];
indexToEdgeID[index] = fEdgeToEdgeID[fEdge];
+ maxEdgeID = (indexToEdgeID[index] > maxEdgeID) ? indexToEdgeID[index] : maxEdgeID;
+ minEdgeID = (indexToEdgeID[index] < minEdgeID) ? indexToEdgeID[index] : minEdgeID;
if((floatingEdgesMask_F[fEdge]!=0)&&(index fCellsToSend;
- fCellsToSend.reserve(nCellsSolve_F);
+ MPI_Allreduce(&maxEdgeID, &maxGlobalEdgeID, 1, MPI_INT, MPI_MAX, comm);
+ MPI_Allreduce(&minEdgeID, &minGlobalEdgeID, 1, MPI_INT, MPI_MIN, comm);
+ globalEdgeStride = maxGlobalEdgeID - minGlobalEdgeID + 1;
+
+ // Third, we compute the FE vertices belonging to the FE triangles owned by this processor.
+ // We need to make sure that an FE vertex is owned by a proc that owns a FE triangle that contain that vertex
+ // Otherwise we might end up with weird situation where a vertex could belong to a process with no associated triangle.
vertexToFCell.clear();
vertexToFCell.reserve(nCells_F);
@@ -720,70 +584,97 @@ void velocity_solver_compute_2d_grid(int const* _verticesMask_F, int const* _cel
fCellToVertex.assign(nCells_F, NotAnId);
std::vector fCellToVertexID(nCells_F, NotAnId);
- fCellsToReceive.clear();
+ vertexProcIDs.clear();
+
+ std::vector verticesProcIds(nCells_F, NotAnId);
- // if(! isDomainEmpty)
- // {
- fCellsToReceive.reserve(nCells_F - nCellsSolve_F);
+ vertexProcIDs.reserve(nCells_F);
for (int i = 0; i < nCells_F; i++) {
bool isMine = i < nCellsSolve_F;
bool belongsToLocalTriangle = false;
bool belongsToAnyTriangle = false;
int nEdg = nEdgesOnCells_F[i];
+ bool invalidVertex = false;
+ int minTriangleProcId = std::numeric_limits::max();
+ bool nodeOwnedByATriaProc = false;
for (int j = 0; j < nEdg; j++) {
ID fVertex(verticesOnCell_F[maxNEdgesOnCell_F * i + j] - 1);
- ID iTria = fVertexToTriangle[fVertex];
+ if(fVertex >= nVertices_F) {
+ invalidVertex = true;
+ break;
+ }
+
ID triaId = fVertexToTriangleID[fVertex];
- belongsToLocalTriangle = belongsToLocalTriangle || (iTria != NotAnId);
+ belongsToLocalTriangle = belongsToLocalTriangle || (trianglesProcIds[fVertex] == me);
belongsToAnyTriangle = belongsToAnyTriangle || (triaId != NotAnId);
- }
- if (belongsToAnyTriangle && isMine) {
- fCellsToSend.push_back(i);
- if (!belongsToLocalTriangle)
- fCellsToReceive.push_back(i);
+ if(triaId != NotAnId) {
+ nodeOwnedByATriaProc = nodeOwnedByATriaProc || (trianglesProcIds[fVertex] == fCellsProcIds[i]);
+ minTriangleProcId = (trianglesProcIds[fVertex] < minTriangleProcId) ? trianglesProcIds[fVertex] : minTriangleProcId;
+ }
}
+ if(invalidVertex) continue;
+
+ if(belongsToAnyTriangle)
+ verticesProcIds[i] = nodeOwnedByATriaProc ? fCellsProcIds[i] : minTriangleProcId;
+
if (belongsToLocalTriangle) {
fCellToVertex[i] = vertexToFCell.size();
vertexToFCell.push_back(i);
+ vertexProcIDs.push_back(reduced_ranks[verticesProcIds[i]]);
}
}
- // }
-
- //Compute the global number of vertices, and the localOffset on the local processor, such that a globalID = localOffset + index
- computeLocalOffset(fCellsToSend.size(), localOffset, nGlobalVertices);
-
- //Communicate the globalIDs, computed locally, to the other processors.
- for (int index = 0; index < int(fCellsToSend.size()); index++)
- fCellToVertexID[fCellsToSend[index]] = index + localOffset;
+ nVertices = vertexToFCell.size();
- allToAll(fCellToVertexID, sendCellsList_F, recvCellsList_F);
+ for (int fcell = 0; fcell < nCells_F; fcell++)
+ fCellToVertexID[fcell] = indexToCellID_F[fcell];
- nVertices = vertexToFCell.size();
- int vertexColumnShift = (Ordering == 1) ? 1 : nGlobalVertices;
- int vertexLayerShift = (Ordering == 0) ? 1 : nLayers + 1;
+ int maxVertexID=std::numeric_limits::min(), minVertexID=std::numeric_limits::max(), maxGlobalVertexID, minGlobalVertexID;
+ indexToVertexID.resize(nVertices);
+ for (int index = 0; index < nVertices; index++) {
+ int fCell = vertexToFCell[index];
+ indexToVertexID[index] = fCellToVertexID[fCell];
+ maxVertexID = (indexToVertexID[index] > maxVertexID) ? indexToVertexID[index] : maxVertexID;
+ minVertexID = (indexToVertexID[index] < minVertexID) ? indexToVertexID[index] : minVertexID;
+ }
+ MPI_Allreduce(&maxVertexID, &maxGlobalVertexID, 1, MPI_INT, MPI_MAX, comm);
+ MPI_Allreduce(&minVertexID, &minGlobalVertexID, 1, MPI_INT, MPI_MIN, comm);
+ globalVertexStride = maxGlobalVertexID - minGlobalVertexID + 1;
- std::cout << "\n nvertices: " << nVertices << " " << nGlobalVertices << "\n"
- << std::endl;
- indexToVertexID.resize(nVertices);
+ int vertexColumnShift = (Ordering == 1) ? 1 : globalVertexStride;
+ int vertexLayerShift = (Ordering == 0) ? 1 : nLayers + 1;
dirichletNodesIDs.clear();
dirichletNodesIDs.reserve(nVertices); //need to improve storage efficiency
+ isVertexBoundary.assign(nVertices, false);
for (int index = 0; index < nVertices; index++) {
int fCell = vertexToFCell[index];
- indexToVertexID[index] = fCellToVertexID[fCell];
for(int il=0; il< nLayers+1; ++il)
{
int imask_F = il+(nLayers+1)*fCell;
if(dirichletCellsMask_F[imask_F]!=0)
dirichletNodesIDs.push_back((nLayers-il)*vertexColumnShift+indexToVertexID[index]*vertexLayerShift);
}
+
+ int nEdg = nEdgesOnCells_F[fCell];
+ int j = 0;
+ bool isBoundary;
+ do {
+ int fVertex = verticesOnCell_F[maxNEdgesOnCell_F * fCell + j++] - 1;
+ isBoundary = !(verticesMask_F[fVertex] & dynamic_ice_bit_value);
+ } while ((j < nEdg) && (!isBoundary));
+ isVertexBoundary[index] = isBoundary;
}
- createReverseCellsExchangeLists(sendCellsListReversed, recvCellsListReversed,
- fVertexToTriangleID, fCellToVertexID);
+ // because we change the ownership of some vertices, we need to first communicate back to the processors that used to own those vertices
+ // the data of the newly owned vertices. We do this by defining "reversed" send and receive lists, communicate back using that list, and
+ // then communicate forward with the usual send and receive lists.
+ // We could join these two step in one communication, but for the moment we do that separately.
+ // We need to communicate info about the vertices when we get the ice velocity on vertices form the velocity solver/
+
+ createReverseExchangeLists(sendCellsListReversed, recvCellsListReversed, verticesProcIds, indexToCellID_F, recvCellsList_F);
//construct the local vector vertices on triangles making sure the area is positive
verticesOnTria.resize(nTriangles * 3);
@@ -802,132 +693,24 @@ void velocity_solver_compute_2d_grid(int const* _verticesMask_F, int const* _cel
std::swap(verticesOnTria[3 * index + 1], verticesOnTria[3 * index + 2]);
}
- //construct the local vector vertices on edges
- trianglesPositionsOnEdge.resize(2 * nEdges);
- isVertexBoundary.assign(nVertices, false);
-
verticesOnEdge.resize(2 * nEdges);
-
- //contains the local id of a triangle and the global id of the edges of the triangle.
- //dataForGhostTria[4*i] contains the triangle id
- //dataForGhostTria[4*i+1+k] contains the global id of the edge (at position k = 0,1,2) of the triangle.
- //Possible Optimization: for our purposes it would be enough to store two of the three edges of a triangle.
- std::vector dataForGhostTria(nVertices_F * 4, NotAnId);
-
- //*
- for (int iV = 0; iV < nVertices; iV++) {
- int fCell = vertexToFCell[iV];
- int nEdg = nEdgesOnCells_F[fCell];
- int j = 0;
- bool isBoundary;
- do {
- int fVertex = verticesOnCell_F[maxNEdgesOnCell_F * fCell + j++] - 1;
- isBoundary = !(verticesMask_F[fVertex] & dynamic_ice_bit_value);
- } while ((j < nEdg) && (!isBoundary));
- isVertexBoundary[iV] = isBoundary;
- }
- /*/
- for(int index=0; index verticesCoords(3 * nVertices);
-
- for (int index = 0; index < nVertices; index++) {
- int iCell = vertexToFCell[index];
- verticesCoords[index * 3] = xCell_F[iCell] / unit_length;
- verticesCoords[index * 3 + 1] = yCell_F[iCell] / unit_length;
- verticesCoords[index * 3 + 2] = zCell_F[iCell] / unit_length;
- }
-
- velocity_solver_compute_2d_grid__(nGlobalTriangles,
- nGlobalVertices, nGlobalEdges, indexToVertexID, verticesCoords,
- isVertexBoundary, verticesOnTria,isBoundaryEdge, trianglesOnEdge,
- trianglesPositionsOnEdge, verticesOnEdge, indexToEdgeID,
- indexToTriangleID, procOnInterfaceEdge );
-#else
- velocity_solver_compute_2d_grid__(reducedComm);
-#endif
-
- /*
-
- //initialize the mesh
- iceProblemPtr->mesh2DPtr.reset (new RegionMesh() );
-
- //construct the mesh nodes
- constructNodes ( * (iceProblemPtr->mesh2DPtr), indexToVertexID, verticesCoords, isVertexBoundary, nGlobalVertices, 3);
-
- //construct the mesh elements
- constructElements ( * (iceProblemPtr->mesh2DPtr), indexToTriangleID, verticesOnTria, nGlobalTriangles);
-
- //construct the mesh facets
- constructFacets ( * (iceProblemPtr->mesh2DPtr), isBoundaryEdge, trianglesOnEdge, trianglesPositionsOnEdge, verticesOnEdge, indexToEdgeID, procOnInterfaceEdge, nGlobalEdges, 3);
-
- Switch sw;
- std::vector elSign;
- checkVolumes ( * (iceProblemPtr->mesh2DPtr), elSign, sw );
- */
+ velocity_solver_compute_2d_grid__(reducedComm);
}
-void velocity_solver_extrude_3d_grid(double const* levelsRatio_F,
- double const* lowerSurface_F, double const* thickness_F) {
+void velocity_solver_extrude_3d_grid(double const* levelsRatio_F) {
if (isDomainEmpty)
return;
@@ -936,7 +719,6 @@ void velocity_solver_extrude_3d_grid(double const* levelsRatio_F,
// !!Indexing of layers is reversed
for (int i = 0; i < nLayers; i++)
layersRatio[i] = levelsRatio_F[nLayers - 1 - i];
- //std::copy(levelsRatio_F, levelsRatio_F+nLayers, layersRatio.begin());
levelsNormalizedThickness.resize(nLayers + 1);
@@ -945,10 +727,6 @@ void velocity_solver_extrude_3d_grid(double const* levelsRatio_F,
levelsNormalizedThickness[i + 1] = levelsNormalizedThickness[i]
+ layersRatio[i];
- std::vector mpasIndexToVertexID(nVertices);
- for (int i = 0; i < nVertices; i++)
- mpasIndexToVertexID[i] = indexToCellID_F[vertexToFCell[i]];
-
//construct the local vector of coordinates
std::vector verticesCoords(3 * nVertices);
@@ -959,10 +737,14 @@ void velocity_solver_extrude_3d_grid(double const* levelsRatio_F,
verticesCoords[index * 3 + 2] = zCell_F[iCell] / unit_length;
}
- velocity_solver_extrude_3d_grid__(nLayers, nGlobalTriangles, nGlobalVertices,
- nGlobalEdges, Ordering, reducedComm, indexToVertexID, mpasIndexToVertexID,
- verticesCoords, isVertexBoundary, verticesOnTria, isBoundaryEdge,
- trianglesOnEdge, trianglesPositionsOnEdge, verticesOnEdge, indexToEdgeID,
+ std::vector> procsSharingVertices(nVertices);
+ for(int i=0; i< nVertices; i++)
+ procsSharingVertex(i, procsSharingVertices[i]);
+
+ velocity_solver_extrude_3d_grid__(nLayers, globalTriangleStride, globalVertexStride,
+ globalEdgeStride, Ordering, reducedComm, indexToVertexID, vertexProcIDs,
+ verticesCoords, verticesOnTria, procsSharingVertices, isBoundaryEdge,
+ trianglesOnEdge, verticesOnEdge, indexToEdgeID,
indexToTriangleID, dirichletNodesIDs, floatingEdgesIds);
}
@@ -1004,11 +786,7 @@ void interface_init_log(){
}
strcat(oformat, ".out");
- if (me == 0) {
- sprintf(albany_log_filename, oformat, me);
- } else {
- strcpy(albany_log_filename, "/dev/null");
- }
+ sprintf(albany_log_filename, oformat, me);
Interface_stdout = open(albany_log_filename, O_CREAT|O_WRONLY|O_TRUNC,0644);
if(Interface_stdout >= 0) {
@@ -1070,14 +848,9 @@ void get_prism_velocity_on_FEdges(double * uNormal,
UInt nPoints3D = nCells_F * (nLayers + 1);
- // Loop over all edges of the triangulation - MPAS will decide which edges it should use.
- for (int i = 0; i < nEdges; i++) {
-
- //identifying vertices on the edge
- ID lId0 = verticesOnEdge[2 * i];
- ID lId1 = verticesOnEdge[2 * i + 1];
- int iCell0 = vertexToFCell[lId0];
- int iCell1 = vertexToFCell[lId1];
+ for (int iEdge = 0; iEdge < nEdgesSolve_F; iEdge++) {
+ int iCell0 = cellsOnEdge_F[2 * iEdge] - 1;
+ int iCell1 = cellsOnEdge_F[2 * iEdge + 1] - 1;
//computing normal to the cell edge (dual of triangular edge)
double nx = xCell_F[iCell1] - xCell_F[iCell0];
@@ -1087,9 +860,14 @@ void get_prism_velocity_on_FEdges(double * uNormal,
ny /= n;
//identifying triangles that shares the edge
- ID iEdge = edgeToFEdge[i];
ID fVertex0 = verticesOnEdge_F[2 * iEdge] - 1;
ID fVertex1 = verticesOnEdge_F[2 * iEdge + 1] - 1;
+
+
+ int iTria0 = fVertexToTriangleID[fVertex0];
+ int iTria1 = fVertexToTriangleID[fVertex1];
+ if((iTria0 == NotAnId) && (iTria1 == NotAnId)) continue;
+
double t0[2*3], t1[2*3]; //t0[0] contains the x-coords of vertices of triangle 0 and t0[1] its y-coords.
for (int j = 0; j < 3; j++) {
int iCell = cellsOnVertex_F[3 * fVertex0 + j] - 1;
@@ -1120,11 +898,11 @@ void get_prism_velocity_on_FEdges(double * uNormal,
for (int j = 0; j < 3; j++)
iCells[j] = cellsOnVertex_F[3 * fVertex1 + j] - 1;
}
- else if(i& velocityOnVertices,
}
}
-void createReverseCellsExchangeLists(exchangeList_Type& sendListReverse_F,
- exchangeList_Type& receiveListReverse_F,
- const std::vector& fVertexToTriangleID,
- const std::vector& fCellToVertexID) {
- sendListReverse_F.clear();
- receiveListReverse_F.clear();
- //std::map > sendMap;
- std::map > sendMap, receiveMap;
- std::vector cellsProcId(nCells_F), trianglesProcIds(nVertices_F);
- getProcIds(cellsProcId, recvCellsList_F);
- getProcIds(trianglesProcIds, recvVerticesList_F);
-
- //std::cout << "SendList " ;
- for (int i = 0; i < nVertices; i++) {
- int iCell = vertexToFCell[i];
- if (iCell < nCellsSolve_F)
- continue;
- bool belongToTriaOnSameProc = false;
- int j(0);
- int nEdg = nEdgesOnCells_F[iCell];
- do {
- ID fVertex(verticesOnCell_F[maxNEdgesOnCell_F * iCell + j] - 1);
- ID triaId = fVertexToTriangleID[fVertex];
- belongToTriaOnSameProc = (triaId != NotAnId)
- && (trianglesProcIds[fVertex] == cellsProcId[iCell]);
- } while ((belongToTriaOnSameProc == false) && (++j < nEdg));
- if (!belongToTriaOnSameProc) {
- sendMap[cellsProcId[iCell]].insert(
- std::make_pair(fCellToVertexID[iCell], iCell));
- // std::cout<< "(" << cellsProcId[iCell] << "," << iCell << ") ";
- }
-
- }
- //std::cout < >::const_iterator it = sendMap.begin();
- it != sendMap.end(); it++) {
- std::vector sendVec(it->second.size());
- int i = 0;
- for (std::map::const_iterator iter = it->second.begin();
- iter != it->second.end(); iter++)
- sendVec[i++] = iter->second;
- sendListReverse_F.push_back(
- exchange(it->first, &sendVec[0], &sendVec[0] + sendVec.size()));
- }
-
- //std::cout << "ReceiveList " ;
- for (UInt i = 0; i < fCellsToReceive.size(); i++) {
- int iCell = fCellsToReceive[i];
- int nEdg = nEdgesOnCells_F[iCell];
- for (int j = 0; j < nEdg; j++) {
- ID fVertex(verticesOnCell_F[maxNEdgesOnCell_F * iCell + j] - 1);
- ID triaId = fVertexToTriangleID[fVertex];
- if (triaId != NotAnId) {
- receiveMap[trianglesProcIds[fVertex]].insert(
- std::make_pair(fCellToVertexID[iCell], iCell));
- // std::cout<< "(" << trianglesProcIds[fVertex] << "," << iCell << ") ";
- }
- }
- }
- //std::cout < >::const_iterator it =
- receiveMap.begin(); it != receiveMap.end(); it++) {
- std::vector receiveVec(it->second.size());
- int i = 0;
- for (std::map::const_iterator iter = it->second.begin();
- iter != it->second.end(); iter++)
- receiveVec[i++] = iter->second;
- receiveListReverse_F.push_back(
- exchange(it->first, &receiveVec[0],
- &receiveVec[0] + receiveVec.size()));
- }
-}
-
-void createReverseEdgesExchangeLists(exchangeList_Type& sendListReverse_F,
+void createReverseExchangeLists(exchangeList_Type& sendListReverse_F,
exchangeList_Type& receiveListReverse_F,
- const std::vector& fVertexToTriangleID,
- const std::vector& fEdgeToEdgeID) {
+ const std::vector& newProcIds, const int* indexToID_F, exchangeList_Type const * recvList_F) {
sendListReverse_F.clear();
receiveListReverse_F.clear();
- //std::map > sendMap;
std::map > sendMap, receiveMap;
- std::vector edgesProcId(nEdges_F), trianglesProcIds(nVertices_F);
- getProcIds(edgesProcId, recvEdgesList_F);
- getProcIds(trianglesProcIds, recvVerticesList_F);
-
- //std::cout << "EdgesSendList " ;
- for (int i = 0; i < nEdges; i++) {
- int iEdge = edgeToFEdge[i];
- if (iEdge < nEdgesSolve_F)
- continue;
- bool belongToTriaOnSameProc = false;
- int j(0);
- do {
- ID fVertex(verticesOnEdge_F[2 * iEdge + j] - 1);
- ID triaId = fVertexToTriangleID[fVertex];
- belongToTriaOnSameProc = (triaId != NotAnId)
- && (trianglesProcIds[fVertex] == edgesProcId[iEdge]);
- } while ((belongToTriaOnSameProc == false) && (++j < 2));
- if (!belongToTriaOnSameProc) {
- sendMap[edgesProcId[iEdge]].insert(
- std::make_pair(fEdgeToEdgeID[iEdge], iEdge));
- //std::cout<< "(" << edgesProcId[iEdge] << "," << iEdge << ") ";
+ int nFEntities = newProcIds.size();
+ std::vector procIds(nFEntities);
+ getProcIds(procIds, recvList_F);
+ int me;
+ MPI_Comm_rank(comm, &me);
+ for (int fEntity = 0; fEntity < nFEntities; fEntity++) {
+ if ((procIds[fEntity] != me) && (newProcIds[fEntity] == me)) {
+ sendMap[procIds[fEntity]].insert(
+ std::make_pair(indexToID_F[fEntity], fEntity));
}
}
- //std::cout < >::const_iterator it = sendMap.begin();
it != sendMap.end(); it++) {
@@ -1329,20 +1017,12 @@ void createReverseEdgesExchangeLists(exchangeList_Type& sendListReverse_F,
exchange(it->first, &sendVec[0], &sendVec[0] + sendVec.size()));
}
- //std::cout << "EdgesReceiveList " ;
- for (UInt i = 0; i < edgesToReceive.size(); i++) {
- int iEdge = edgesToReceive[i];
- for (int j = 0; j < 2; j++) {
- ID fVertex(verticesOnEdge_F[2 * iEdge + j] - 1);
- ID triaId = fVertexToTriangleID[fVertex];
- if (triaId != NotAnId) {
- receiveMap[trianglesProcIds[fVertex]].insert(
- std::make_pair(fEdgeToEdgeID[iEdge], iEdge));
- // std::cout<< "(" << trianglesProcIds[fVertex] << "," << iEdge << ") ";
- }
+ for (int fEntity = 0; fEntity < nFEntities; fEntity++) {
+ if((procIds[fEntity] == me) && (newProcIds[fEntity] != NotAnId) && (newProcIds[fEntity] != me)) {
+ receiveMap[newProcIds[fEntity]].insert(
+ std::make_pair(indexToID_F[fEntity], fEntity));
}
}
- // std::cout < >::const_iterator it =
receiveMap.begin(); it != receiveMap.end(); it++) {
@@ -1381,19 +1061,6 @@ void mapCellsToVertices(const std::vector& velocityOnCells,
}
}
-bool isGhostTriangle(int i, double relTol) {
- double x[3], y[3], area;
-
- for (int j = 0; j < 3; j++) {
- int iCell = cellsOnVertex_F[3 * i + j] - 1;
- x[j] = xCell_F[iCell];
- y[j] = yCell_F[iCell];
- }
-
- area = std::fabs(signedTriangleArea(x, y));
- return false; //(std::fabs(areaTriangle_F[i]-area)/areaTriangle_F[i] > relTol);
-}
-
double signedTriangleArea(const double* x, const double* y) {
double u[2] = { x[1] - x[0], y[1] - y[0] };
double v[2] = { x[2] - x[0], y[2] - y[0] };
@@ -1417,27 +1084,8 @@ double signedTriangleAreaOnSphere(const double* x, const double* y,
> 0) ? area : -area;
}
-//TO BE FIXED, Access To verticesOnCell_F is not correct
-void extendMaskByOneLayer(int const* verticesMask_F,
- std::vector& extendedFVerticesMask) {
- extendedFVerticesMask.resize(nVertices_F);
- extendedFVerticesMask.assign(&verticesMask_F[0],
- &verticesMask_F[0] + nVertices_F);
- for (int i = 0; i < nCells_F; i++) {
- bool belongsToMarkedTriangle = false;
- int nEdg = nEdgesOnCells_F[i];
- for (UInt k = 0; k < nEdg && !belongsToMarkedTriangle; k++)
- belongsToMarkedTriangle = belongsToMarkedTriangle
- || verticesMask_F[verticesOnCell_F[maxNEdgesOnCell_F * i + k] - 1];
- if (belongsToMarkedTriangle)
- for (UInt k = 0; k < nEdg; k++) {
- ID fVertex(verticesOnCell_F[maxNEdgesOnCell_F * i + k] - 1);
- extendedFVerticesMask[fVertex] = !isGhostTriangle(fVertex);
- }
- }
-}
-void import2DFields(std::map bdExtensionMap, double const* bedTopography_F, double const * lowerSurface_F, double const * thickness_F,
+void importFields(std::map bdExtensionMap, double const* bedTopography_F, double const * lowerSurface_F, double const * thickness_F,
double const * beta_F, double const* stiffnessFactor_F, double const* effecPress_F,
double const * temperature_F, double const * smb_F, double eps) {
@@ -1452,7 +1100,7 @@ void import2DFields(std::map bdExtensionMap, double const* bedTopograp
if (effecPress_F != 0)
effecPressData.assign(nVertices, 1e10);
if(temperature_F != 0)
- temperatureData.assign(nLayers * nTriangles, 1e10);
+ temperatureDataOnPrisms.assign(nLayers * nTriangles, 1e10);
if (smb_F != 0)
smbData.assign(nVertices, 1e10);
@@ -1473,6 +1121,8 @@ void import2DFields(std::map bdExtensionMap, double const* bedTopograp
effecPressData[index] = effecPress_F[iCell] / unit_length;
}
+ int lElemColumnShift = (Ordering == 1) ? 1 : nTriangles;
+ int elemLayerShift = (Ordering == 0) ? 1 : nLayers;
if(temperature_F != 0) {
for (int index = 0; index < nTriangles; index++) {
for (int il = 0; il < nLayers; il++) {
@@ -1482,21 +1132,20 @@ void import2DFields(std::map bdExtensionMap, double const* bedTopograp
for (int iVertex = 0; iVertex < 3; iVertex++) {
int v = verticesOnTria[iVertex + 3 * index];
int iCell = vertexToFCell[v];
- //compute temperature by averaging tmeperature values of triangles vertices where ice is present
- if (cellsMask_F[iCell] & ice_present_bit_value) {
+ //compute temperature by averaging temperature values of triangles vertices where ice is present
+ if (cellsMask_F[iCell] & ice_present_bit_value) {
temperature += temperature_F[iCell * nLayers + ilReversed];
nPoints++;
}
}
if (nPoints == 0) //if triangle is in an ice-free area, set the temperature to T0
- temperatureData[index+il*nTriangles] = T0;
+ temperatureDataOnPrisms[index*elemLayerShift + il*lElemColumnShift] = T0;
else
- temperatureData[index+il*nTriangles] = temperature / nPoints;
+ temperatureDataOnPrisms[index*elemLayerShift + il*lElemColumnShift] = temperature / nPoints;
}
}
}
-
//extend thickness elevation and basal friction data to the border for floating vertices
std::set::const_iterator iter;
@@ -1519,18 +1168,11 @@ void import2DFields(std::map bdExtensionMap, double const* bedTopograp
bool foundNeighbor = false;
for (int j = 0; j < nEdg; j++) {
int fEdge = edgesOnCell_F[maxNEdgesOnCell_F * fCell + j] - 1;
- //bool keep = (mask[verticesOnEdge_F[2 * fEdge] - 1] & dynamic_ice_bit_value)
- // && (mask[verticesOnEdge_F[2 * fEdge + 1] - 1] & dynamic_ice_bit_value);
- //if (!keep)
- // continue;
-
int c0 = cellsOnEdge_F[2 * fEdge] - 1;
int c1 = cellsOnEdge_F[2 * fEdge + 1] - 1;
c = (fCellToVertex[c0] == iV) ? c1 : c0;
- //if(!(cellsMask_F[c] & ice_present_bit_value)) continue;
if((cellsMask_F[c] & dynamic_ice_bit_value)) {
double elev = thickness_F[c] + lowerSurface_F[c]; // - 1e-8*std::sqrt(pow(xCell_F[c0],2)+std::pow(yCell_F[c0],2));
- //std::cout << " elev="< bdExtensionMap, double const* bedTopograp
// Check that this margin location is not below sea level!
if (bedTopographyData[iV] < 0.0) { // This check is probably redundant...
thicknessData[iV] = eps*3.0; // insert special value here to make identifying these points easier in exo output
- elevationData[iV] = (rho_ocean / rho_ice - 1.0) * thicknessData[iV]; // floating surface
+ elevationData[iV] = (1.0 - rho_ice / rho_ocean) * thicknessData[iV]; // floating surface
}
}
} else {
@@ -1554,14 +1196,10 @@ void import2DFields(std::map bdExtensionMap, double const* bedTopograp
// Otherwise, it will have a surface elevation below sea level,
// which is unphysical and can cause large slopes and other issues.
if (bedTopographyData[iV] < 0.0) {
- //std::cout<<"non-floating boundary below sea level at iV="< v2;
-
- for (int iTetra = 0; iTetra < 3; iTetra++)
- for (int iVertex = 0; iVertex < 4; iVertex++)
- {
- tetrasIdsOnPrism[iTetra][iVertex] = prismVertexGIds[tetraOfPrism[prismType][iTetra][iVertex]];
- }
-
- // return;
-
- int reorderedPrismLIds[6];
-
- for (int ii = 0; ii < 6; ii++)
- {
- reorderedPrismLIds[ii] = prismVertexGIds[PrismVerticesMap[minIndex][ii]];
- }
-
- for (int iTetra = 0; iTetra < 3; iTetra++)
- for (int iVertex = 0; iVertex < 4; iVertex++)
- {
- tetrasIdsOnPrism[iTetra][iVertex] = reorderedPrismLIds[tetraOfPrism[prismType][iTetra][iVertex]];
- }
- }
-
-
-
-
- void setBdFacesOnPrism (const std::vector > >& prismStruct, const std::vector& prismFaceIds, std::vector& tetraPos, std::vector& facePos)
- {
- int numTriaFaces = prismFaceIds.size() - 2;
- tetraPos.assign(numTriaFaces,-1);
- facePos.assign(numTriaFaces,-1);
-
-
- for (int iTetra (0), k (0); (iTetra < 3 && k < numTriaFaces); iTetra++)
- {
- bool found;
- for (int jFaceLocalId = 0; jFaceLocalId < 4; jFaceLocalId++ )
- {
- found = true;
- for (int ip (0); ip < 3 && found; ip++)
- {
- int localId = prismStruct[iTetra][jFaceLocalId][ip];
- int j = 0;
- found = false;
- while ( (j < prismFaceIds.size()) && !found )
- {
- found = (localId == prismFaceIds[j]);
- j++;
- }
- }
- if (found)
- {
- tetraPos[k] = iTetra;
- facePos[k] = jFaceLocalId;
- k += found;
- break;
- }
- }
- }
- }
-
void procsSharingVertex(const int vertex, std::vector& procIds) {
int fCell = vertexToFCell[vertex];
procIds.clear();
int nEdg = nEdgesOnCells_F[fCell];
int me;
MPI_Comm_rank(comm, &me);
- procIds.reserve(nEdg);
for(int i=0; i regulThk(thicknessData);
-// for (int index = 0; index < nVertices; index++)
-// regulThk[index] = std::max(1e-4, thicknessData[index]); //TODO Make limit a parameter
-//
-// importP0Temperature(temperature_F);
-//
-// std::cout << "\n\nTimeStep: "<< *deltat << "\n\n"<< std::endl;
-//
-// std::vector mpasIndexToVertexID(nVertices);
-// for (int i = 0; i < nVertices; i++) {
-// mpasIndexToVertexID[i] = indexToCellID_F[vertexToFCell[i]];
-// }
-//
-// mapVerticesToCells(velocityOnVertices, &velocityOnCells[0], 2, nLayers,
-// Ordering);
-
-
// Write out ASCII format
std::cout << "Writing mesh to albany.msh." << std::endl;
// msh file
std::ofstream outfile;
- outfile.open ("albany.msh", std::ios::out | std::ios::trunc);
+ outfile.precision(15);
+ std::stringstream name;
+ int me;
+ MPI_Comm_rank(comm, &me);
+ name << "albany.msh." << me;
+ outfile.open (name.str(), std::ios::out | std::ios::trunc);
if (outfile.is_open()) {
int nVerticesBoundaryEdge = 0;
- for (int index = 0; index < nVertices; index++) {
+ for (int index = 0; index < nEdges; index++) {
if (isBoundaryEdge[index]) nVerticesBoundaryEdge += 1;
}
- std::vector verticesOnBoundaryEdge;
- verticesOnBoundaryEdge.resize(2 * nVerticesBoundaryEdge);
+
+ //creating set from vector so that we can find elements in the set in log time
+ std::set floatingEdgesSet;
+ for (int i = 0; i < floatingEdgesIds.size(); i++)
+ floatingEdgesSet.insert(floatingEdgesIds[i]);
+
+
+ std::vector boundaryEdges; //list of edge vertices and edge label
+ boundaryEdges.resize(3 * nVerticesBoundaryEdge);
int iVerticesBoundaryEdge = 0;
- for (int index = 0; index < nVertices; index++) {
+ for (int index = 0; index < nEdges; index++) {
if (isBoundaryEdge[index]) {
- verticesOnBoundaryEdge[0 + 2 * iVerticesBoundaryEdge] = verticesOnEdge[0 + 2 * index];
- verticesOnBoundaryEdge[1 + 2 * iVerticesBoundaryEdge] = verticesOnEdge[1 + 2 * index];
- iVerticesBoundaryEdge += 1;
+ boundaryEdges[0 + 3 * iVerticesBoundaryEdge] = verticesOnEdge[0 + 2 * index];
+ boundaryEdges[1 + 3 * iVerticesBoundaryEdge] = verticesOnEdge[1 + 2 * index];
+ auto search = floatingEdgesSet.find(indexToEdgeID[index]); //slow but executed only when printing
+ //boundary edges labels: 2 if floating, 1 otherwise
+ boundaryEdges[2 + 3 * iVerticesBoundaryEdge] = (search != floatingEdgesSet.end()) ? 2 : 1;
+ iVerticesBoundaryEdge ++;
}
}
- //std::cout<<"final count: "< bdExtensionMap; // local map to be created by import2DFields
- import2DFields(bdExtensionMap, bedTopography_F, lowerSurface_F, thickness_F, beta_F,
+
+ std::map bdExtensionMap; // local map to be created by importFields
+ importFields(bdExtensionMap, bedTopography_F, lowerSurface_F, thickness_F, beta_F,
stiffnessFactor_F, effecPress_F, temperature_F, smb_F, minThickness);
import2DFieldsObservations(bdExtensionMap,
@@ -2235,20 +1683,23 @@ int prismType(long long int const* prismVertexMpasIds, int& minIndex)
std::cout << "Writing temperature.ascii." << std::endl;
outfile.open ("temperature.ascii", std::ios::out | std::ios::trunc);
if (outfile.is_open()) {
- outfile << nTriangles << " " << nLayers << "\n"; //number of triangles and number of layers on first line
-
- double midLayer = 0;
- for (int il = 0; il < nLayers; il++) { //sigma coordinates for temperature
- midLayer += layersRatio[il]/2.0;
- outfile << midLayer << "\n";
- midLayer += layersRatio[il]/2.0;
- }
-
- for(int il = 0; il
#include
#include
#include
@@ -45,11 +44,6 @@ distributed with this code, or at http://mpas-dev.github.com/license.html
#define write_ascii_mesh write_ascii_mesh_
#endif
-//#include
-//#include
-
-//#include
-
struct exchange {
const int procID;
const std::vector vec;
@@ -112,6 +106,8 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
int const* _verticesOnCell_F, int const* _verticesOnEdge_F,
int const* _edgesOnCell_F, int const* _nEdgesOnCells_F,
int const* _indexToCellID_F,
+ int const* _indexToEdgeID_F,
+ int const* _indexToVertexID_F,
double const* _xCell_F, double const* _yCell_F, double const* _zCell_F,
double const* _xVertex_F, double const* _yVertex_F, double const* _zVertex_F,
double const* _areaTriangle_F,
@@ -119,15 +115,12 @@ void velocity_solver_set_grid_data(int const* _nCells_F, int const* _nEdges_F,
int const* sendEdgesArray_F, int const* recvEdgesArray_F,
int const* sendVerticesArray_F, int const* recvVerticesArray_F);
-void velocity_solver_extrude_3d_grid(double const* levelsRatio_F,
- double const* lowerSurface_F, double const* thickness_F);
+void velocity_solver_extrude_3d_grid(double const* levelsRatio_F);
void velocity_solver_export_l1l2_velocity();
void velocity_solver_export_fo_velocity();
-//void velocity_solver_estimate_SS_SMB (const double* u_normal_F, double* sfcMassBal);
-
void interface_init_log();
void interface_redirect_stdout(int const* iTimestep);
@@ -148,24 +141,9 @@ void write_ascii_mesh(int const* indexToCellID_F,
} // extern "C"
-extern int velocity_solver_init_mpi__(int* fComm);
+extern int velocity_solver_init_mpi__(MPI_Comm comm);
extern void velocity_solver_finalize__();
-#ifdef LIFEV
-extern void velocity_solver_init_l1l2__(const std::vector& layersRatio, const std::vector& velocityOnVertices, bool initialize_velocity);
-
-extern void velocity_solver_solve_l1l2__(const std::vector& elevationData,
- const std::vector& thicknessData, const std::vector& betaData,
- const std::vector& temperatureData, const std::vector& indexToVertexID,
- std::vector& velocityOnVertices);
-
-extern void velocity_solver_init_fo__(const std::vector& layersRatio, const std::vector& velocityOnVertices, const std::vector& indexToVertexID, bool initialize_velocity);
-
-extern void velocity_solver_export_l1l2_velocity__(const std::vector& layersRatio, const std::vector& elevationData, const std::vector& regulThk,
- const std::vector& mpasIndexToVertexID, MPI_Comm reducedComm);
-
-#endif
-
extern void velocity_solver_set_physical_parameters__(double const& gravity, double const& ice_density, double const& ocean_density, double const& sea_level, double const& flowParamA,
double const& flowLawExponent, double const& dynamic_thickness, bool const& useGLP, double const& clausiusClapeyronCoeff);
@@ -182,31 +160,13 @@ extern void velocity_solver_solve_fo__(int nLayers, int nGlobalVertices,
const std::vector& smbData,
const std::vector& stiffnessFactorData,
const std::vector& effecPressData,
- const std::vector& temperatureOnTetra,
- std::vector& dissipationHeatOnTetra,
+ const std::vector& temperatureDataOnPrisms,
+ std::vector& dissipationHeatOnPrisms,
std::vector& velocityOnVertices,
int& error,
const double& deltat = 0.0);
-
-#ifdef LIFEV
-extern void velocity_solver_compute_2d_grid__(int nGlobalTriangles,
- int nGlobalVertices, int nGlobalEdges,
- const std::vector& indexToVertexID,
- const std::vector& verticesCoords,
- const std::vector& isVertexBoundary,
- const std::vector& verticesOnTria,
- const std::vector& isBoundaryEdge,
- const std::vector& trianglesOnEdge,
- const std::vector& trianglesPositionsOnEdge,
- const std::vector& verticesOnEdge,
- const std::vector& indexToEdgeID,
- const std::vector& indexToTriangleID,
- const std::vector < std::pair >& procOnInterfaceEdge);
-
-#else
extern void velocity_solver_compute_2d_grid__(MPI_Comm);
-#endif
extern void velocity_solver_export_2d_data__(MPI_Comm reducedComm,
@@ -215,44 +175,33 @@ extern void velocity_solver_export_2d_data__(MPI_Comm reducedComm,
const std::vector& betaData,
const std::vector& indexToVertexID);
-extern void velocity_solver_extrude_3d_grid__(int nLayers, int nGlobalTriangles,
- int nGlobalVertices, int nGlobalEdges, int Ordering, MPI_Comm reducedComm,
+extern void velocity_solver_extrude_3d_grid__(
+ int nLayers, int globalTriangleStride, int globalVertexStride, int globalEdgeStride,
+ int Ordering, MPI_Comm reducedComm,
const std::vector& indexToVertexID,
- const std::vector& mpasIndexToVertexID,
+ const std::vector& vertexProcIDs,
const std::vector& verticesCoords,
- const std::vector& isVertexBoundary,
const std::vector& verticesOnTria,
+ const std::vector> procsSharingVertices,
const std::vector& isBoundaryEdge,
const std::vector& trianglesOnEdge,
- const std::vector& trianglesPositionsOnEdge,
const std::vector& verticesOnEdge,
const std::vector& indexToEdgeID,
const std::vector& indexToTriangleID,
const std::vector& dirichletNodes,
const std::vector&floatingEdges);
-//extern void velocity_solver_export_l1l2_velocity__();
-
extern void velocity_solver_export_fo_velocity__(MPI_Comm reducedComm);
-
-#ifdef LIFEV
-extern int velocity_solver_initialize_iceProblem__(bool keep_proc, MPI_Comm reducedComm);
-#endif
-
-//extern void velocity_solver_estimate_SS_SMB__ (const double* u_normal_F, double* sfcMassBal);
-
exchangeList_Type unpackMpiArray(int const* array);
-bool isGhostTriangle(int i, double relTol = 1e-1);
-
double signedTriangleArea(const double* x, const double* y);
double signedTriangleArea(const double* x, const double* y, const double* z);
void createReducedMPI(int nLocalEntities, MPI_Comm& reduced_comm_id);
-void import2DFields(std::map bdExtensionMap, double const* bedTopography_F, double const* lowerSurface_F, double const* thickness_F,
+void importFields(std::map bdExtensionMap, double const* bedTopography_F, double const* lowerSurface_F, double const* thickness_F,
double const* beta_F = 0, double const* stiffnessFactor_F = 0, double const* effecPress_F = 0, double const* temperature_F = 0, double const* smb_F = 0, double eps = 0);
void import2DFieldsObservations(std::map bdExtensionMap,
@@ -271,11 +220,6 @@ void write_ascii_mesh_field_int(std::vector fieldData, std::string filename
std::vector extendMaskByOneLayer(int const* verticesMask_F);
-void extendMaskByOneLayer(int const* verticesMask_F,
- std::vector& extendedFVerticesMask);
-
-void importP0Temperature();
-
void exportDissipationHeat(double * dissipationHeat_F);
void get_prism_velocity_on_FEdges(double* uNormal,
@@ -284,15 +228,9 @@ void get_prism_velocity_on_FEdges(double* uNormal,
int initialize_iceProblem(int nTriangles);
-void createReverseCellsExchangeLists(exchangeList_Type& sendListReverse_F,
- exchangeList_Type& receiveListReverse_F,
- const std::vector& fVertexToTriangleID,
- const std::vector& fCellToVertexID);
-
-void createReverseEdgesExchangeLists(exchangeList_Type& sendListReverse_F,
+void createReverseExchangeLists(exchangeList_Type& sendListReverse_F,
exchangeList_Type& receiveListReverse_F,
- const std::vector& fVertexToTriangleID,
- const std::vector& fEdgeToEdgeID);
+ const std::vector& newProcIds, const int* indexToID_F, exchangeList_Type const * recvList_F);
void mapCellsToVertices(const std::vector& velocityOnCells,
std::vector& velocityOnVertices, int fieldDim, int numLayers,
@@ -301,9 +239,6 @@ void mapCellsToVertices(const std::vector& velocityOnCells,
void mapVerticesToCells(const std::vector& velocityOnVertices,
double* velocityOnCells, int fieldDim, int numLayers, int ordering);
-void computeLocalOffset(int nLocalEntities, int& localOffset,
- int& nGlobalEntities);
-
void getProcIds(std::vector& field, int const* recvArray);
void getProcIds(std::vector& field, exchangeList_Type const* recvList);
@@ -317,12 +252,6 @@ void allToAll(std::vector& field, exchangeList_Type const* sendList,
void allToAll(double* field, exchangeList_Type const* sendList,
exchangeList_Type const* recvList, int fieldDim = 1);
-int prismType(long long int const* prismVertexMpasIds, int& minIndex);
-void tetrasFromPrismStructured (long long int const* prismVertexMpasIds, long long int const* prismVertexGIds, long long int tetrasIdsOnPrism[][4]);
-void computeMap();
-
-void setBdFacesOnPrism (const std::vector > >& prismStruct, const std::vector& prismFaceIds, std::vector& tetraPos, std::vector& facePos);
-void tetrasFromPrismStructured (int const* prismVertexMpasIds, int const* prismVertexGIds, int tetrasIdsOnPrism[][4]);
void procsSharingVertex(const int vertex, std::vector& procIds);
bool belongToTria(double const* x, double const* t, double bcoords[3], double eps = 1e-3);
diff --git a/src/core_landice/mode_forward/mpas_li_advection.F b/src/core_landice/mode_forward/mpas_li_advection.F
index 4b728d3d29..4c0576ab89 100644
--- a/src/core_landice/mode_forward/mpas_li_advection.F
+++ b/src/core_landice/mode_forward/mpas_li_advection.F
@@ -257,7 +257,7 @@ subroutine li_advection_thickness_tracers(&
call mpas_pool_get_array(geometryPool, 'floatingBasalMassBal', floatingBasalMassBal)
call mpas_pool_get_array(geometryPool, 'layerThickness', layerThickness)
call mpas_pool_get_array(geometryPool, 'layerThicknessEdge', layerThicknessEdge)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
call mpas_pool_get_array(geometryPool, 'dynamicThickening', dynamicThickening)
call mpas_pool_get_array(geometryPool, 'groundedToFloatingThickness', groundedToFloatingThickness)
@@ -630,7 +630,7 @@ subroutine li_update_geometry(geometryPool)
call mpas_pool_get_dimension(geometryPool, 'nCells', nCells)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'upperSurface', upperSurface)
call mpas_pool_get_array(geometryPool, 'lowerSurface', lowerSurface)
diff --git a/src/core_landice/mode_forward/mpas_li_calving.F b/src/core_landice/mode_forward/mpas_li_calving.F
index 41e0523d8d..ac7d032ab0 100644
--- a/src/core_landice/mode_forward/mpas_li_calving.F
+++ b/src/core_landice/mode_forward/mpas_li_calving.F
@@ -402,7 +402,7 @@ subroutine li_restore_calving_front(domain, err)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'restoreThickness', restoreThickness)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
! get required fields from the thermal pool
call mpas_pool_get_array(thermalPool, 'temperature', temperature)
@@ -870,7 +870,7 @@ subroutine floating_calving(domain, calvingFraction, err)
call mpas_pool_get_subpool(block % structs, 'mesh', meshPool)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
calvingThickness = 0.0_RKIND
@@ -929,7 +929,7 @@ subroutine remove_small_islands(meshPool, geometryPool)
call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
do iCell = 1, nCellsSolve
@@ -1039,7 +1039,7 @@ subroutine topographic_calving(domain, calvingFraction, err)
call mpas_pool_get_subpool(block % structs, 'mesh', meshPool)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
calvingThickness = 0.0_RKIND
@@ -1152,7 +1152,7 @@ subroutine eigencalving(domain, err)
call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell)
call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
call mpas_pool_get_array(geometryPool, 'eigencalvingParameter', eigencalvingParameter)
@@ -1336,7 +1336,7 @@ subroutine distribute_calving_flux(meshPool, geometryPool, scratchPool, calvingF
! get fields
call mpas_pool_get_dimension(meshPool, 'nCells', nCells)
call mpas_pool_get_array(meshPool, 'deltat', deltat)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'requiredCalvingVolumeRate', requiredCalvingVolumeRate)
@@ -1566,7 +1566,7 @@ subroutine calculate_calving_front_mask(meshPool, geometryPool, calvingFrontMask
call mpas_pool_get_dimension(meshPool, 'nCells', nCells)
call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell)
call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
calvingFrontMask = 0 !initialize
@@ -1656,7 +1656,7 @@ subroutine remove_icebergs(domain)
call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool)
call mpas_pool_get_subpool(block % structs, 'mesh', meshPool)
call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'contiguousDynamicIce', contiguousDynamicIce)
call mpas_pool_get_dimension(meshPool, 'nCells', nCells)
call mpas_pool_get_dimension(geometryPool, 'nCellsSolve', nCellsSolve)
@@ -1710,7 +1710,7 @@ subroutine remove_icebergs(domain)
call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool)
call mpas_pool_get_subpool(block % structs, 'mesh', meshPool)
call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'contiguousDynamicIce', contiguousDynamicIce)
call mpas_pool_get_array(geometryPool, 'contiguousDynamicIceOld', contiguousDynamicIceOld)
call mpas_pool_get_dimension(meshPool, 'nCells', nCells)
@@ -1765,7 +1765,7 @@ subroutine remove_icebergs(domain)
block => domain % blocklist
do while (associated(block))
call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'contiguousDynamicIce', contiguousDynamicIce)
diff --git a/src/core_landice/mode_forward/mpas_li_diagnostic_vars.F b/src/core_landice/mode_forward/mpas_li_diagnostic_vars.F
index ab47f0d226..a8f2664137 100644
--- a/src/core_landice/mode_forward/mpas_li_diagnostic_vars.F
+++ b/src/core_landice/mode_forward/mpas_li_diagnostic_vars.F
@@ -258,10 +258,9 @@ subroutine li_calculate_apparent_diffusivity(meshPool, velocityPool, scratchPool
call mpas_pool_get_array(geometryPool, 'thickness', thickness, timeLevel=1)
call mpas_pool_get_array(geometryPool, 'layerThickness', layerThickness, timeLevel=1)
call mpas_pool_get_array(geometryPool, 'apparentDiffusivity', apparentDiffusivity)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(velocityPool, 'uReconstructZonal', uReconstructAxis1)
call mpas_pool_get_array(velocityPool, 'uReconstructMeridional', uReconstructAxis2)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
call mpas_pool_get_field(scratchPool, 'workCell', slopeReconstructXField)
call mpas_allocate_scratch_field(slopeReconstructXField, .true.)
call mpas_pool_get_field(scratchPool, 'workCell2', slopeReconstructYField)
diff --git a/src/core_landice/mode_forward/mpas_li_iceshelf_melt.F b/src/core_landice/mode_forward/mpas_li_iceshelf_melt.F
index 95f6716fa8..0b99e9d843 100644
--- a/src/core_landice/mode_forward/mpas_li_iceshelf_melt.F
+++ b/src/core_landice/mode_forward/mpas_li_iceshelf_melt.F
@@ -247,7 +247,7 @@ subroutine li_basal_melt_floating_ice(domain, err)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'lowerSurface', lowerSurface)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'floatingBasalMassBal', floatingBasalMassBal)
! get fields from the scratch pool
@@ -853,7 +853,7 @@ subroutine calc_iceshelf_draft_info(domain, GLdepth, CFdepth, err)
call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool)
call mpas_pool_get_subpool(block % structs, 'mesh', meshPool)
call mpas_pool_get_array(geometryPool, 'lowerSurface', lowerSurface)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell)
call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell)
call mpas_pool_get_array(meshPool, 'areaCell', areaCell)
diff --git a/src/core_landice/mode_forward/mpas_li_sia.F b/src/core_landice/mode_forward/mpas_li_sia.F
index b22001c4f2..d400c12e35 100644
--- a/src/core_landice/mode_forward/mpas_li_sia.F
+++ b/src/core_landice/mode_forward/mpas_li_sia.F
@@ -316,7 +316,7 @@ subroutine li_sia_solve(meshPool, geometryPool, thermalPool, velocityPool, err)
call mpas_pool_get_array(velocityPool, 'flowParamA', flowParamA)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'slopeEdge', slopeEdge)
call mpas_pool_get_array(geometryPool, 'normalSlopeEdge', normalSlopeEdge)
call mpas_pool_get_array(thermalPool, 'temperature', temperature)
diff --git a/src/core_landice/mode_forward/mpas_li_statistics.F b/src/core_landice/mode_forward/mpas_li_statistics.F
index 47a7be44e8..99de7c4939 100644
--- a/src/core_landice/mode_forward/mpas_li_statistics.F
+++ b/src/core_landice/mode_forward/mpas_li_statistics.F
@@ -235,7 +235,7 @@ subroutine li_compute_statistics(domain, itimestep)
! Geometry arrays
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
call mpas_pool_get_array(geometryPool, 'sfcMassBal', sfcMassBal)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
call mpas_pool_get_array(geometryPool, 'thickness', thickness, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'layerThickness', layerThickness, timeLevel = 1)
diff --git a/src/core_landice/mode_forward/mpas_li_subglacial_hydro.F b/src/core_landice/mode_forward/mpas_li_subglacial_hydro.F
index 9e2e4f79ca..596119d01c 100644
--- a/src/core_landice/mode_forward/mpas_li_subglacial_hydro.F
+++ b/src/core_landice/mode_forward/mpas_li_subglacial_hydro.F
@@ -163,7 +163,7 @@ subroutine li_SGH_init(domain, err)
waterPressure = max(0.0_RKIND, waterPressure)
waterPressure = min(waterPressure, rhoi * gravity * thickness)
! set pressure correctly under floating ice and open ocean
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
where ( (li_mask_is_floating_ice(cellMask)) .or. &
( (.not. li_mask_is_ice(cellMask)) .and. (bedTopography < config_sea_level) ) )
@@ -379,7 +379,7 @@ subroutine li_SGH_solve(domain, err)
call mpas_pool_get_array(hydroPool, 'deltatSGH', deltatSGH)
call mpas_pool_get_array(hydroPool, 'basalMeltInput', basalMeltInput)
call mpas_pool_get_array(hydroPool, 'externalWaterInput', externalWaterInput)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
WtillOld = Wtill
Wtill = Wtill + deltatSGH * ( (basalMeltInput + externalWaterInput) / rho_water - Cd)
@@ -420,7 +420,7 @@ subroutine li_SGH_solve(domain, err)
call mpas_pool_get_array(hydroPool, 'waterVelocity', waterVelocity)
call mpas_pool_get_array(hydroPool, 'waterVelocityCellX', waterVelocityCellX)
call mpas_pool_get_array(hydroPool, 'waterVelocityCellY', waterVelocityCellY)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
allocate(cellJunk(nCells+1))
call mpas_reconstruct(meshPool, waterVelocity, waterVelocityCellX, waterVelocityCellY, &
cellJunk, cellJunk, cellJunk)
@@ -476,7 +476,7 @@ subroutine li_SGH_solve(domain, err)
call mpas_pool_get_array(meshPool, 'edgesOnCell', edgesOnCell)
call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge)
call mpas_pool_get_array(meshPool, 'edgeSignOnCell', edgeSignOnCell)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
divergence(:) = 0.0_RKIND ! zero div before starting
! loop over locally owned cells
@@ -551,7 +551,7 @@ subroutine li_SGH_solve(domain, err)
call mpas_pool_get_array(hydroPool, 'divergence', divergence)
call mpas_pool_get_array(hydroPool, 'divergenceChannel', divergenceChannel)
call mpas_pool_get_array(hydroPool, 'channelAreaChangeCell', channelAreaChangeCell)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
waterThicknessOld = waterThickness
waterThickness = waterThicknessOld + deltatSGH * ( (basalMeltInput + externalWaterInput) / rho_water - divergence &
@@ -755,7 +755,7 @@ subroutine calc_edge_quantities(block, err)
call mpas_pool_get_array(hydroPool, 'hydropotentialBaseSlopeNormal', hydropotentialBaseSlopeNormal)
call mpas_pool_get_array(hydroPool, 'waterPressureSlopeNormal', waterPressureSlopeNormal)
call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge)
call mpas_pool_get_array(meshPool, 'edgeSignOnCell', edgeSignOnCell)
call mpas_pool_get_array(hydroPool, 'hydropotentialBaseSlopeTangent', hydropotentialBaseSlopeTangent)
@@ -1217,7 +1217,7 @@ subroutine calc_pressure(block, err)
call mpas_pool_get_array(velocityPool, 'basalSpeed', basalSpeed)
call mpas_pool_get_array(velocityPool, 'flowParamA', flowParamA)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography)
openingRate(:) = bedRough * basalSpeed(:) * (bedRoughMax - waterThickness(:))
@@ -1338,7 +1338,7 @@ subroutine calc_pressure_diag_vars(block, err)
call mpas_pool_get_array(hydroPool, 'hydropotentialBase', hydropotentialBase)
call mpas_pool_get_array(hydroPool, 'waterThickness', waterThickness)
call mpas_pool_get_array(hydroPool, 'hydropotential', hydropotential)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
effectivePressure = rhoi * gravity * thickness - waterPressure
! < this should evalute to 0 for floating ice if Pw set correctly there.
diff --git a/src/core_landice/mode_forward/mpas_li_thermal.F b/src/core_landice/mode_forward/mpas_li_thermal.F
index 383ba22dae..6a4807a1dd 100644
--- a/src/core_landice/mode_forward/mpas_li_thermal.F
+++ b/src/core_landice/mode_forward/mpas_li_thermal.F
@@ -831,7 +831,7 @@ subroutine li_thermal_solver(domain, err)
! get fields from the geometry pool
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'upperSurface', upperSurface)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'groundedBasalMassBal', groundedBasalMassBal)
call mpas_pool_get_array(geometryPool, 'floatingBasalMassBal', floatingBasalMassBal)
call mpas_pool_get_array(geometryPool, 'basalWaterThickness', basalWaterThickness)
diff --git a/src/core_landice/mode_forward/mpas_li_velocity.F b/src/core_landice/mode_forward/mpas_li_velocity.F
index 4f5f6a2820..59a7ed5e2e 100644
--- a/src/core_landice/mode_forward/mpas_li_velocity.F
+++ b/src/core_landice/mode_forward/mpas_li_velocity.F
@@ -268,8 +268,9 @@ subroutine li_velocity_solve(domain, solveVelo, err)
integer, pointer :: nEdges
integer, pointer :: nVertInterfaces
integer, pointer :: nCells
- integer, dimension(:), pointer :: edgeMask, cellMask, vertexMask, vertexMaskOld
+ integer, dimension(:), pointer :: edgeMask, cellMask, cellMaskOld, vertexMask, vertexMaskOld
integer, dimension(:,:), pointer :: dirichletVelocityMaskOld, dirichletVelocityMaskNew
+ integer, dimension(:), pointer :: floatingEdgesOld, floatingEdgesNew
real (kind=RKIND), dimension(:,:), pointer :: normalVelocity, normalVelocityInitial
real (kind=RKIND), dimension(:,:), pointer :: uReconstructX, uReconstructY, uReconstructZ, &
uReconstructZonal, uReconstructMeridional
@@ -287,7 +288,9 @@ subroutine li_velocity_solve(domain, solveVelo, err)
real (kind=RKIND), dimension(:), pointer :: upperSurface
integer, dimension(:), pointer :: indexToEdgeID
integer, pointer :: anyDynamicVertexMaskChanged
+ integer, pointer :: cellIceMaskChanged
integer, pointer :: dirichletMaskChanged
+ integer, pointer :: floatingEdgesChanged
! truly local variables
integer :: cell1, cell2
integer :: cell3, cell4, thisCell
@@ -300,7 +303,9 @@ subroutine li_velocity_solve(domain, solveVelo, err)
real (kind=RKIND) :: maxThicknessOnProc, maxThicknessAllProcs
real (kind=RKIND) :: xVelEdge, yVelEdge
integer :: blockDynamicVertexMaskChanged, procDynamicVertexMaskChanged
+ integer :: blockCellIceMaskChanged, procCellIceMaskChanged
integer :: blockDirichletMaskChanged, procDirichletMaskChanged
+ integer :: blockFloatingEdgesChanged, procFloatingEdgesChanged
call mpas_timer_start("velocity solve")
@@ -385,7 +390,9 @@ subroutine li_velocity_solve(domain, solveVelo, err)
! Don't bother checking this with SIA because it requires an extra global reduce
maxThicknessOnProc = 0.0_RKIND ! initialize to
procDynamicVertexMaskChanged = 0
+ procCellIceMaskChanged = 0
procDirichletMaskChanged = 0
+ procFloatingEdgesChanged = 0
block => domain % blocklist
do while (associated(block))
@@ -397,7 +404,7 @@ subroutine li_velocity_solve(domain, solveVelo, err)
maxThicknessOnProc = max(maxThicknessOnProc, maxval(thickness))
! The interface expects an array where 1's are floating edges and 0's are non-floating edges.
- call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdges)
+ call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdges, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
floatingEdges = li_mask_is_floating_ice_int(edgeMask)
call mpas_pool_get_array(geometryPool, 'vertexMask', vertexMask, timeLevel=1)
@@ -407,7 +414,7 @@ subroutine li_velocity_solve(domain, solveVelo, err)
! TODO: There may be some aspects of the mask that are ok change for external dycores,
! but for now just check the whole thing.
call mpas_pool_get_array(geometryPool, 'vertexMask', vertexMaskOld, timeLevel=2)
- if ( sum(li_mask_is_dynamic_ice_int(vertexMask) - li_mask_is_dynamic_ice_int(vertexMaskOld)) /= 0 ) then
+ if ( sum(abs(li_mask_is_dynamic_ice_int(vertexMask) - li_mask_is_dynamic_ice_int(vertexMaskOld))) /= 0 ) then
blockDynamicVertexMaskChanged = 1
else
blockDynamicVertexMaskChanged = 0
@@ -416,11 +423,26 @@ subroutine li_velocity_solve(domain, solveVelo, err)
! Determine if any blocks on this processor had a change to the vertex mask
procDynamicVertexMaskChanged = max(procDynamicVertexMaskChanged, blockDynamicVertexMaskChanged)
!print *,'procVertexMaskChanged', procVertexMaskChanged
+
+ ! Determine if the cell mask changed during this time step for this block (needed for external dycores)
+ ! TODO: There may be some aspects of the mask that are ok change for external dycores,
+ ! but for now just check the whole thing.
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel=1)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMaskOld, timeLevel=2)
+ if (( sum(abs(li_mask_is_dynamic_ice_int(cellMask) - li_mask_is_dynamic_ice_int(cellMaskOld))) /= 0 ) .or. &
+ ( sum(abs(li_mask_is_ice_int(cellMask) - li_mask_is_ice_int(cellMaskOld))) /= 0 )) then
+ blockCellIceMaskChanged = 1
+ else
+ blockCellIceMaskChanged = 0
+ endif
+
+ ! Determine if any blocks on this processor had a change to the cell mask
+ procCellIceMaskChanged = max(procCellIceMaskChanged, blockCellIceMaskChanged)
- ! Also check to see if the Dirichlet b.c. mask has changed
+ ! Check to see if the Dirichlet b.c. mask has changed
call mpas_pool_get_array(velocityPool, 'dirichletVelocityMask', dirichletVelocityMaskOld, timeLevel=2)
call mpas_pool_get_array(velocityPool, 'dirichletVelocityMask', dirichletVelocityMaskNew, timeLevel=1)
- if ( sum(dirichletVelocityMaskNew - dirichletVelocityMaskOld) /= 0 ) then
+ if ( sum(abs(dirichletVelocityMaskNew - dirichletVelocityMaskOld)) /= 0 ) then
blockDirichletMaskChanged = 1
else
blockDirichletMaskChanged = 0
@@ -428,6 +450,17 @@ subroutine li_velocity_solve(domain, solveVelo, err)
! Determine if any blocks on this processor had a change to the vertex mask
procDirichletMaskChanged = max(procDirichletMaskChanged, blockDirichletMaskChanged)
+ ! Check to see if the Floating Edges Ids have changed
+ call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdgesOld, timeLevel=2)
+ call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdgesNew, timeLevel=1)
+ if ( sum(abs(floatingEdgesNew - floatingEdgesOld)) /= 0 ) then
+ blockFloatingEdgesChanged = 1
+ else
+ blockFloatingEdgesChanged = 0
+ endif
+ ! Determine if any blocks on this processor had a change to the vertex mask
+ procFloatingEdgesChanged = max(procFloatingEdgesChanged, blockFloatingEdgesChanged)
+
! Set beta for solver to use
! (this could potentially be applied to an SIA solver, so it is calculated in this module)
call calculate_beta(block, err_tmp)
@@ -451,10 +484,16 @@ subroutine li_velocity_solve(domain, solveVelo, err)
call mpas_pool_get_array(velocityPool, 'anyDynamicVertexMaskChanged', anyDynamicVertexMaskChanged)
call mpas_dmpar_max_int(domain % dminfo, procDynamicVertexMaskChanged, anyDynamicVertexMaskChanged)
!print *,'anyDynamicVertexMaskChanged', anyDynamicVertexMaskChanged
+ ! Do the same for the cell mask
+ call mpas_pool_get_array(velocityPool, 'cellIceMaskChanged', cellIceMaskChanged)
+ call mpas_dmpar_max_int(domain % dminfo, procCellIceMaskChanged, cellIceMaskChanged)
! Do the same for the Dirichlet b.c. mask
call mpas_pool_get_array(velocityPool, 'dirichletMaskChanged', dirichletMaskChanged)
call mpas_dmpar_max_int(domain % dminfo, procDirichletMaskChanged, dirichletMaskChanged)
- !print *,'dirichletMaskChanged', dirichletMaskChanged
+ ! Do the same for the Floating edges
+ call mpas_pool_get_array(velocityPool, 'floatingEdgesChanged', floatingEdgesChanged)
+ call mpas_dmpar_max_int(domain % dminfo, procFloatingEdgesChanged, floatingEdgesChanged)
+ !print *,'floatingEdgesChanged', floatingEdgesChanged
endif
@@ -478,7 +517,7 @@ subroutine li_velocity_solve(domain, solveVelo, err)
call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge)
call mpas_pool_get_array(meshPool, 'cellsOnVertex', cellsOnVertex)
call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'upperSurface', upperSurface)
@@ -823,7 +862,7 @@ subroutine calculate_beta(block, err)
call mpas_pool_get_array(velocityPool, 'betaSolve', betaSolve)
call mpas_pool_get_array(velocityPool, 'beta', beta)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
betaSolve = beta
@@ -999,7 +1038,7 @@ subroutine remove_fast_ice(meshPool, uReconstructX, uReconstructY, normalVelocit
call mpas_pool_get_dimension(meshPool, 'nCells', nCells)
call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell)
call mpas_pool_get_array(meshPool, 'edgesOnCell', edgesOnCell)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'thickness', thickness)
call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness)
call mpas_pool_get_array(geometryPool, 'upperSurface', upperSurface)
diff --git a/src/core_landice/mode_forward/mpas_li_velocity_external.F b/src/core_landice/mode_forward/mpas_li_velocity_external.F
index a214560efe..f1fa8bd529 100644
--- a/src/core_landice/mode_forward/mpas_li_velocity_external.F
+++ b/src/core_landice/mode_forward/mpas_li_velocity_external.F
@@ -327,7 +327,7 @@ subroutine li_velocity_external_block_init(block, err)
call velocity_solver_set_grid_data(nCells, nEdges, nVertices, nVertInterfaces, &
nCellsSolve, nEdgesSolve, nVerticesSolve, maxNEdgesOnCell, radius, &
cellsOnEdge, cellsOnVertex, verticesOnCell, verticesOnEdge, edgesOnCell, &
- nEdgesOnCell, indexToCellID, &
+ nEdgesOnCell, indexToCellID, indexToEdgeID, indexToVertexID, &
xCell, yCell, zCell, xVertex, yVertex, zVertex, areaTriangle, &
sendCellsArray, recvCellsArray, &
sendEdgesArray, recvEdgesArray, &
@@ -452,7 +452,9 @@ subroutine li_velocity_external_solve(meshPool, geometryPool, thermalPool, hydro
logical, pointer :: config_output_external_velocity_solver_data
real (kind=RKIND), pointer :: config_ice_density
integer, pointer :: anyDynamicVertexMaskChanged
+ integer, pointer :: cellIceMaskChanged
integer, pointer :: dirichletMaskChanged
+ integer, pointer :: floatingEdgesChanged
integer, pointer :: nEdges
integer, pointer :: nVertLevels
integer, pointer :: timestepNumber
@@ -486,7 +488,7 @@ subroutine li_velocity_external_solve(meshPool, geometryPool, thermalPool, hydro
call mpas_pool_get_array(geometryPool, 'lowerSurface', lowerSurface)
call mpas_pool_get_array(geometryPool, 'upperSurface', upperSurface)
call mpas_pool_get_array(geometryPool, 'vertexMask', vertexMask, timeLevel = 1)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
call mpas_pool_get_array(geometryPool, 'sfcMassBal', sfcMassBal)
@@ -501,9 +503,11 @@ subroutine li_velocity_external_solve(meshPool, geometryPool, thermalPool, hydro
call mpas_pool_get_array(velocityPool, 'uReconstructZ', uReconstructZ)
call mpas_pool_get_array(velocityPool, 'betaSolve', betaSolve)
call mpas_pool_get_array(velocityPool, 'anyDynamicVertexMaskChanged', anyDynamicVertexMaskChanged)
+ call mpas_pool_get_array(velocityPool, 'cellIceMaskChanged', cellIceMaskChanged)
call mpas_pool_get_array(velocityPool, 'dirichletMaskChanged', dirichletMaskChanged)
call mpas_pool_get_array(velocityPool, 'dirichletVelocityMask', dirichletVelocityMask, timeLevel = 1)
- call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdges)
+ call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdges, timeLevel = 1)
+ call mpas_pool_get_array(velocityPool, 'floatingEdgesChanged', floatingEdgesChanged)
call mpas_pool_get_array(velocityPool, 'stiffnessFactor', stiffnessFactor)
! Hydro variables
@@ -521,7 +525,7 @@ subroutine li_velocity_external_solve(meshPool, geometryPool, thermalPool, hydro
! Note these functions will always be called on the first solve because we
! initialize vertexMask to garbage which sets anyDynamicVertexMaskChanged to 1.
if ((anyDynamicVertexMaskChanged == 1) .or. (config_always_compute_fem_grid) .or. &
- (dirichletMaskChanged == 1) ) then
+ (dirichletMaskChanged == 1) .or. (floatingEdgesChanged == 1) .or. (cellIceMaskChanged == 1)) then
call mpas_log_write("Generating new external velocity solver FEM grid.", flushNow=.true.)
call generate_fem_grid(config_velocity_solver, vertexMask, cellMask, dirichletVelocityMask, &
floatingEdges, layerThicknessFractions, lowerSurface, thickness, err)
@@ -779,10 +783,6 @@ subroutine li_velocity_external_write_albany_mesh(domain)
call mpas_log_write("config_velocity solver needs to be set to 'FO' for config_write_albany_ascii_mesh to work.", &
MPAS_LOG_CRIT)
endif
- ! check nProcs
- if (domain % dminfo % nProcs /= 1) then
- call mpas_log_write("config_write_albany_ascii_mesh currently only works on 1 processor.", MPAS_LOG_CRIT)
- endif
! check nBlocks
if (domain % dminfo % total_blocks /= 1) then
call mpas_log_write("config_write_albany_ascii_mesh currently only works on 1 block per processor.", MPAS_LOG_CRIT)
@@ -809,13 +809,13 @@ subroutine li_velocity_external_write_albany_mesh(domain)
call mpas_pool_get_array(geometryPool, 'sfcMassBal', sfcMassBal)
call mpas_pool_get_array(geometryPool, 'floatingBasalMassBal', floatingBasalMassBal)
call mpas_pool_get_array(geometryPool, 'vertexMask', vertexMask, timeLevel = 1)
- call mpas_pool_get_array(geometryPool, 'cellMask', cellMask)
+ call mpas_pool_get_array(geometryPool, 'cellMask', cellMask, timeLevel = 1)
call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask)
call mpas_pool_get_array(geometryPool, 'layerThickness', layerThickness)
! Velocity variables
call mpas_pool_get_array(velocityPool, 'beta', beta)
- call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdges)
+ call mpas_pool_get_array(velocityPool, 'floatingEdges', floatingEdges, timeLevel = 1)
call mpas_pool_get_array(velocityPool, 'dirichletVelocityMask', dirichletVelocityMask, timeLevel = 1)
call mpas_pool_get_array(velocityPool, 'stiffnessFactor', stiffnessFactor)
@@ -1022,7 +1022,7 @@ subroutine generate_fem_grid(config_velocity_solver, vertexMask, cellMask, diric
case ('FO') ! ===============================================
#ifdef USE_EXTERNAL_FIRSTORDER
call mpas_timer_start("velocity_solver_extrude_3d_grid")
- call velocity_solver_extrude_3d_grid(layerThicknessFractions, lowerSurface, thickness)
+ call velocity_solver_extrude_3d_grid(layerThicknessFractions)
call mpas_timer_stop("velocity_solver_extrude_3d_grid")
call mpas_timer_start("velocity_solver_init_FO")
call velocity_solver_init_FO(layerThicknessFractions)
diff --git a/testing_and_setup/compass/landice/MISMIP+/albany_input.yaml b/testing_and_setup/compass/landice/MISMIP+/albany_input.yaml
index c89dcb14ce..9676e6bbb9 100644
--- a/testing_and_setup/compass/landice/MISMIP+/albany_input.yaml
+++ b/testing_and_setup/compass/landice/MISMIP+/albany_input.yaml
@@ -35,7 +35,7 @@ ANONYMOUS:
Body Force:
Type: FO INTERP SURF GRAD
Discretization:
- Cubature Degree: 1
+ Element Shape: Prism
Piro:
LOCA:
Bifurcation: { }
diff --git a/testing_and_setup/compass/landice/Thwaites_variability/albany_input.yaml b/testing_and_setup/compass/landice/Thwaites_variability/albany_input.yaml
index af2a6dd48c..a41f919c8d 100644
--- a/testing_and_setup/compass/landice/Thwaites_variability/albany_input.yaml
+++ b/testing_and_setup/compass/landice/Thwaites_variability/albany_input.yaml
@@ -31,8 +31,8 @@ ANONYMOUS:
Type: Lateral
Immersed Ratio: 8.85000000000000009e-01
Discretization:
- Cubature Degree: 11
- Interleaved Ordering: true
+ Element Shape: Tetrahedron
+ #Exodus Output File Name: albany_output.exo
Piro:
LOCA:
Bifurcation: { }
diff --git a/testing_and_setup/compass/landice/circular-shelf/albany_input.yaml b/testing_and_setup/compass/landice/circular-shelf/albany_input.yaml
index 029369ad0c..3ac436fb05 100644
--- a/testing_and_setup/compass/landice/circular-shelf/albany_input.yaml
+++ b/testing_and_setup/compass/landice/circular-shelf/albany_input.yaml
@@ -17,8 +17,6 @@ ANONYMOUS:
Type: FO INTERP SURF GRAD
Discretization:
Exodus Output File Name: albany_output.exo
- Cubature Degree: 1
- Interleaved Ordering: false
Piro:
LOCA:
Bifurcation: { }
diff --git a/testing_and_setup/compass/landice/confined-shelf/albany_input.yaml b/testing_and_setup/compass/landice/confined-shelf/albany_input.yaml
index 52809be2bf..1c75c642b0 100644
--- a/testing_and_setup/compass/landice/confined-shelf/albany_input.yaml
+++ b/testing_and_setup/compass/landice/confined-shelf/albany_input.yaml
@@ -17,8 +17,6 @@ ANONYMOUS:
Type: FO INTERP SURF GRAD
Discretization:
Exodus Output File Name: albany_output.exo
- Cubature Degree: 1
- Interleaved Ordering: false
Piro:
LOCA:
Bifurcation: { }
diff --git a/testing_and_setup/compass/landice/dome/albany_input.yaml b/testing_and_setup/compass/landice/dome/albany_input.yaml
index 01ec65683a..3357ddccc3 100644
--- a/testing_and_setup/compass/landice/dome/albany_input.yaml
+++ b/testing_and_setup/compass/landice/dome/albany_input.yaml
@@ -11,6 +11,7 @@ ANONYMOUS:
'Glen''s Law Homotopy Parameter': 1.0
Discretization:
Exodus Output File Name: albany_output.exo
+ Element Shape: Prism
Piro:
LOCA:
Bifurcation: { }
diff --git a/testing_and_setup/compass/landice/greenland/albany_input.yaml b/testing_and_setup/compass/landice/greenland/albany_input.yaml
index d2fb7eab2a..67b76efabe 100644
--- a/testing_and_setup/compass/landice/greenland/albany_input.yaml
+++ b/testing_and_setup/compass/landice/greenland/albany_input.yaml
@@ -17,8 +17,7 @@ ANONYMOUS:
Type: FO INTERP SURF GRAD
Discretization:
Exodus Output File Name: albany_output.exo
- Cubature Degree: 1
- Interleaved Ordering: false
+ Element Shape: Tetrahedron
Piro:
LOCA:
Bifurcation: { }
diff --git a/testing_and_setup/compass/landice/greenland/albany_schoof_input.yaml b/testing_and_setup/compass/landice/greenland/albany_schoof_input.yaml
index 3e1fa88dc5..045feb0c49 100644
--- a/testing_and_setup/compass/landice/greenland/albany_schoof_input.yaml
+++ b/testing_and_setup/compass/landice/greenland/albany_schoof_input.yaml
@@ -39,8 +39,6 @@ ANONYMOUS:
Immersed Ratio: 8.8521e-01
Discretization:
Exodus Output File Name: albany_output.exo
- Cubature Degree: 1
- Interleaved Ordering: false
Piro:
LOCA:
Bifurcation: { }