Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/pmpo_MPMesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ void MPMesh::reconstructSlices() {
if (reconstructSlice.size() == 0) return;
Kokkos::Timer timer;
calcBasis();
resetPreComputeFlag();
for (auto const& [index, reconstruct] : reconstructSlice) {
if (reconstruct) reconstruct();
}
Expand Down
12 changes: 11 additions & 1 deletion src/pmpo_MPMesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,17 @@ template <> const MaterialPointSlice meshFieldIndexToMPSlice < MeshF_RotLatLonIn
#define maxMPsPerElm 8

class MPMesh{
private:

bool isPreComputed;

public:

MPMesh() : isPreComputed(false){};
void computeMatricesAndSolve();
void resetPreComputeFlag();
Kokkos::View<double*[vec4d_nEntries]> precomputedVtxCoeffs;

Mesh* p_mesh;
MaterialPoints* p_MPs;

Expand Down Expand Up @@ -49,7 +59,7 @@ class MPMesh{
void assemblyElm0();
template <MeshFieldIndex meshFieldIndex>
void assemblyVtx1();

template<MeshFieldIndex meshFieldIndex>
void setReconstructSlice(int order, MeshFieldType type);
void reconstructSlices();
Expand Down
121 changes: 99 additions & 22 deletions src/pmpo_MPMesh_assembly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,73 +98,149 @@ void MPMesh::assemblyElm0() {
pumipic::RecordTime("PolyMPO_Reconstruct_Elm0", timer.seconds());
}

template <MeshFieldIndex meshFieldIndex>
void MPMesh::assemblyVtx1() {

void MPMesh::resetPreComputeFlag(){
isPreComputed = false;
}

void MPMesh::computeMatricesAndSolve(){

//Mesh Information
auto elm2VtxConn = p_mesh->getElm2VtxConn();
int numVtx = p_mesh->getNumVertices();
auto vtxCoords = p_mesh->getMeshField<polyMPO::MeshF_VtxCoords>();

//Mesh Field
constexpr MaterialPointSlice mpfIndex = meshFieldIndexToMPSlice<meshFieldIndex>;
const int numEntries = mpSliceToNumEntries<mpfIndex>();
p_mesh->fillMeshField<meshFieldIndex>(numVtx, numEntries, 0.0);
auto meshField = p_mesh->getMeshField<meshFieldIndex>();
//Dual Element Area for Regularization
auto dual_triangle_area=p_mesh->getMeshField<MeshF_DualTriangleArea>();

//Material Points
auto mpData = p_MPs->getData<mpfIndex>();
auto weight = p_MPs->getData<MPF_Basis_Vals>();
auto mpPositions = p_MPs->getData<MPF_Cur_Pos_XYZ>();

//Matrix for each vertex
Kokkos::View<double*[vec4d_nEntries][vec4d_nEntries]> VtxMatrices("VtxMatrices", p_mesh->getNumVertices());

//Reconstructed values
Kokkos::View<double**> reconVals("meshField", p_mesh->getNumVertices(), numEntries);

//Earth Radius
double radius = 1.0;
if(p_mesh->getGeomType() == geom_spherical_surf)
radius=p_mesh->getSphereRadius();

bool scaling=true;
int reg_method = 2;

//Assemble matrix for each vertex
auto assemble = PS_LAMBDA(const int& elm, const int& mp, const int& mask) {
if(mask) { //if material point is 'active'/'enabled'
int nVtxE = elm2VtxConn(elm,0); //number of vertices bounding the element
for(int i=0; i<nVtxE; i++){
int vID = elm2VtxConn(elm,i+1)-1; //vID = vertex id
double w_vtx=weight(mp,i);

double mScale=1;
if(scaling)
mScale=sqrt(dual_triangle_area(vID,0))/radius;
double CoordDiffs[vec4d_nEntries] = {1, (vtxCoords(vID,0) - mpPositions(mp,0))/radius,
(vtxCoords(vID,1) - mpPositions(mp,1))/radius,
(vtxCoords(vID,2) - mpPositions(mp,2))/radius};
for (int k=0; k<vec4d_nEntries; k++)
for (int l=0; l<vec4d_nEntries; l++)
//All entries except first row and column
for (int k=1; k<vec4d_nEntries; k++)
for (int l=1; l<vec4d_nEntries; l++)
Kokkos::atomic_add(&VtxMatrices(vID,k,l), CoordDiffs[k] * CoordDiffs[l] * w_vtx);
//First entry
Kokkos::atomic_add(&VtxMatrices(vID,0,0), CoordDiffs[0] * CoordDiffs[0] * w_vtx*mScale*mScale);
//First row and column except the first entry
for (int k=1; k<vec4d_nEntries; k++){
Kokkos::atomic_add(&VtxMatrices(vID,0,k), CoordDiffs[0] * CoordDiffs[k] * w_vtx*mScale);
Kokkos::atomic_add(&VtxMatrices(vID,k,0), CoordDiffs[k] * CoordDiffs[0] * w_vtx*mScale);
}
}
}
};
p_MPs->parallel_for(assemble, "assembly");

//Solve Ax=b for each vertex
//Assemble matrix for each vertex and apply regularization
Kokkos::View<double*[vec4d_nEntries]> VtxCoeffs("VtxCoeffs", p_mesh->getNumVertices());

Kokkos::parallel_for("solving Ax=b", numVtx, KOKKOS_LAMBDA(const int vtx){
Vec4d v0 = {VtxMatrices(vtx,0,0), VtxMatrices(vtx,0,1), VtxMatrices(vtx,0,2), VtxMatrices(vtx,0,3)};
Vec4d v1 = {VtxMatrices(vtx,1,0), VtxMatrices(vtx,1,1), VtxMatrices(vtx,1,2), VtxMatrices(vtx,1,3)};
Vec4d v2 = {VtxMatrices(vtx,2,0), VtxMatrices(vtx,2,1), VtxMatrices(vtx,2,2), VtxMatrices(vtx,2,3)};
Vec4d v3 = {VtxMatrices(vtx,3,0), VtxMatrices(vtx,3,1), VtxMatrices(vtx,3,2), VtxMatrices(vtx,3,3)};

Matrix4d A = {v0,v1,v2,v3};
double A_trace = A.trace();
//Define the matrices
Matrix4d A = {v0,v1,v2,v3};
Matrix4d A_regularized = {v0, v1, v2, v3};
A_regularized.addToDiag(A_trace*1e-8);

//Regularization
switch(reg_method){
case 0:{
break;
}
case 1:{
double A_trace = A.trace();
A_regularized.addToDiag(A_trace*1e-8);
break;
}
case 2:{
double regParam=sqrt(EPSILON)*(VtxMatrices(vtx,0,0)+VtxMatrices(vtx,1,1)+
VtxMatrices(vtx,2,2)+VtxMatrices(vtx,3,3));
A_regularized.addToDiag(regParam);
break;
}
default:{
printf("Invalid regularization method \n");
break;
}
}
//Solve Ax=b
double coeff[vec4d_nEntries]={0.0, 0.0, 0.0, 0.0};
CholeskySolve4d_UnitRHS(A_regularized, coeff);
// Undo scaling
double mScale=1;
if(scaling)
mScale=sqrt(dual_triangle_area(vtx,0))/radius;

coeff[0]=coeff[0]*mScale*mScale;
coeff[1]=coeff[1]*mScale;
coeff[2]=coeff[2]*mScale;
coeff[3]=coeff[3]*mScale;
for (int i=0; i<vec4d_nEntries; i++)
VtxCoeffs(vtx,i)=coeff[i];
});
this->precomputedVtxCoeffs = VtxCoeffs;
}

template <MeshFieldIndex meshFieldIndex>
void MPMesh::assemblyVtx1() {

//If no reconstruction till now calculate the coeffs
if (!isPreComputed) {
computeMatricesAndSolve();
isPreComputed=true;
}

auto VtxCoeffs=this->precomputedVtxCoeffs;
//Mesh Information
auto elm2VtxConn = p_mesh->getElm2VtxConn();
int numVtx = p_mesh->getNumVertices();
auto vtxCoords = p_mesh->getMeshField<polyMPO::MeshF_VtxCoords>();

//Mesh Field
constexpr MaterialPointSlice mpfIndex = meshFieldIndexToMPSlice<meshFieldIndex>;
const int numEntries = mpSliceToNumEntries<mpfIndex>();
p_mesh->fillMeshField<meshFieldIndex>(numVtx, numEntries, 0.0);
auto meshField = p_mesh->getMeshField<meshFieldIndex>();

//Material Points
auto mpData = p_MPs->getData<mpfIndex>();
auto weight = p_MPs->getData<MPF_Basis_Vals>();
auto mpPositions = p_MPs->getData<MPF_Cur_Pos_XYZ>();

//Earth Radius
double radius = 1.0;
if(p_mesh->getGeomType() == geom_spherical_surf)
radius=p_mesh->getSphereRadius();

//Reconstructed values
Kokkos::View<double**> reconVals("meshField", p_mesh->getNumVertices(), numEntries);

//Reconstruct
auto reconstruct = PS_LAMBDA(const int& elm, const int& mp, const int& mask) {
if(mask) { //if material point is 'active'/'enabled'
Expand All @@ -175,7 +251,7 @@ void MPMesh::assemblyVtx1() {
double CoordDiffs[vec4d_nEntries] = {1, (vtxCoords(vID,0) - mpPositions(mp,0))/radius,
(vtxCoords(vID,1) - mpPositions(mp,1))/radius,
(vtxCoords(vID,2) - mpPositions(mp,2))/radius};

auto factor = w_vtx*(VtxCoeffs(vID,0) + VtxCoeffs(vID,1)*CoordDiffs[1] +
VtxCoeffs(vID,2)*CoordDiffs[2] +
VtxCoeffs(vID,3)*CoordDiffs[3]);
Expand All @@ -188,7 +264,8 @@ void MPMesh::assemblyVtx1() {
}
};
p_MPs->parallel_for(reconstruct, "reconstruct");


//Assign as a field
Kokkos::parallel_for("assigning", numVtx, KOKKOS_LAMBDA(const int vtx){
for(int k=0; k<numEntries; k++)
meshField(vtx, k) = reconVals(vtx,k);
Expand Down
36 changes: 36 additions & 0 deletions src/pmpo_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,42 @@ void polympo_getMeshElmCenter_f(MPMesh_ptr p_mpmesh, const int nCells, double* x
}
}

void polympo_setMeshDualTriangleArea_f(MPMesh_ptr p_mpmesh, const int nVertices, const double* areaTriangle){

//chech validity
checkMPMeshValid(p_mpmesh);
auto p_mesh = ((polyMPO::MPMesh*)p_mpmesh)->p_mesh;

//check the size
PMT_ALWAYS_ASSERT(p_mesh->getNumVertices()==nVertices);

//copy the host array to the device
auto dualArea = p_mesh->getMeshField<polyMPO::MeshF_DualTriangleArea>();
auto h_dualArea = Kokkos::create_mirror_view(dualArea);
for(int i=0; i<nVertices; i++)
h_dualArea(i,0) = areaTriangle[i];
Kokkos::deep_copy(dualArea, h_dualArea);

}

void polympo_getMeshDualTriangleArea_f(MPMesh_ptr p_mpmesh, const int nVertices, double* areaTriangle){

//chech validity
checkMPMeshValid(p_mpmesh);
auto p_mesh = ((polyMPO::MPMesh*)p_mpmesh)->p_mesh;

//check the size
PMT_ALWAYS_ASSERT(p_mesh->getNumVertices()==nVertices);

//copy the device to host
auto dualArea = p_mesh->getMeshField<polyMPO::MeshF_DualTriangleArea>();
auto h_dualArea = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace(), dualArea);
for(int i=0; i<nVertices; i++)
areaTriangle[i] = h_dualArea(i,0);

}


void polympo_setMeshVtxVel_f(MPMesh_ptr p_mpmesh, const int nVertices, const double* uVelIn, const double* vVelIn){
//check mpMesh is valid
checkMPMeshValid(p_mpmesh);
Expand Down
5 changes: 5 additions & 0 deletions src/pmpo_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ void polympo_setMeshVtxOnSurfDispIncr_f(MPMesh_ptr p_mpmesh, const int nComps, c
void polympo_getMeshVtxOnSurfDispIncr_f(MPMesh_ptr p_mpmesh, const int nComps, const int nVertices, double* array);//vec2d
void polympo_setMeshElmCenter_f(MPMesh_ptr p_mpmesh, const int nCells, const double* xArray, const double* yArray, const double* zArray);
void polympo_getMeshElmCenter_f(MPMesh_ptr p_mpmesh, const int nCells, double* xArray, double* yArray, double* zArray);
//Area Triangle
void polympo_setMeshDualTriangleArea_f(MPMesh_ptr p_mpmesh, const int nVertices, const double* areaTriangle);
void polympo_getMeshDualTriangleArea_f(MPMesh_ptr p_mpmesh, const int nVertices, double* areaTriangle);



// calculations
void polympo_push_f(MPMesh_ptr p_mpmesh);
Expand Down
28 changes: 28 additions & 0 deletions src/pmpo_fortran.f90
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,34 @@ subroutine polympo_getMeshElmCenter(mpMesh, nCells, xArray, yArray, zArray) &
integer(c_int), value :: nCells
type(c_ptr), value :: xArray, yArray, zArray
end subroutine

!---------------------------------------------------------------------------
!> @brief set the polympo dual mesh triangle area
!> @param mpmesh(in/out) MPMesh object
!> @param nVertices(in) length of array in, use for assertion
!> @param Array(in) 1D array of area of dual triangle elements
!---------------------------------------------------------------------------
subroutine polympo_setMeshDualTriangleArea(mpMesh, nVertices, areaTriangle) &
bind(C, NAME='polympo_setMeshDualTriangleArea_f')
use :: iso_c_binding
type(c_ptr), value :: mpMesh
integer(c_int), value :: nVertices
type(c_ptr), intent(in), value :: areaTriangle
end subroutine
!---------------------------------------------------------------------------
!> @brief get the polympo mesh dual mesh triangle area
!> @param mpmesh(in/out) MPMesh object
!> @param nVetices(in) length of array in, use for assertion
!> @param Array(in/out) 1D array of area of dual triangle elements
!---------------------------------------------------------------------------
subroutine polympo_getMeshDualTriangleArea(mpMesh, nVertices, areaTriangle) &
bind(C, NAME='polympo_getMeshDualTriangleArea_f')
use :: iso_c_binding
type(c_ptr), value :: mpMesh
integer(c_int), value :: nVertices
type(c_ptr), value :: areaTriangle
end subroutine

!---------------------------------------------------------------------------
!> @brief set the vertices velocity from a host array
!> @param mpmesh(in/out) MPMesh object
Expand Down
4 changes: 4 additions & 0 deletions src/pmpo_mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ namespace polyMPO{
auto vtxRotLatLonIncrMapEntry = meshFields2TypeAndString.at(MeshF_RotLatLonIncr);
PMT_ALWAYS_ASSERT(vtxRotLatLonIncrMapEntry.first == MeshFType_VtxBased);
vtxRotLatLonIncr_ = MeshFView<MeshF_RotLatLonIncr>(vtxRotLatLonIncrMapEntry.second,numVtxs_);

auto dualTriangleAreaEntry = meshFields2TypeAndString.at(MeshF_DualTriangleArea);
PMT_ALWAYS_ASSERT(dualTriangleAreaEntry.first == MeshFType_VtxBased);
dualTriangleArea_ = MeshFView<MeshF_DualTriangleArea>(dualTriangleAreaEntry.second,numVtxs_);
}

void Mesh::setMeshElmBasedFieldSize(){
Expand Down
7 changes: 7 additions & 0 deletions src/pmpo_mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ enum MeshFieldIndex{
MeshF_VtxCoords,
MeshF_VtxRotLat,
MeshF_ElmCenterXYZ,
MeshF_DualTriangleArea,
MeshF_Vel,
MeshF_VtxMass,
MeshF_ElmMass,
Expand All @@ -38,6 +39,7 @@ template <MeshFieldIndex> struct meshFieldToType;
template <> struct meshFieldToType < MeshF_VtxCoords > { using type = Kokkos::View<vec3d_t*>; };
template <> struct meshFieldToType < MeshF_VtxRotLat > { using type = DoubleView; };
template <> struct meshFieldToType < MeshF_ElmCenterXYZ > { using type = Kokkos::View<vec3d_t*>; };
template <> struct meshFieldToType < MeshF_DualTriangleArea > { using type = Kokkos::View<doubleSclr_t*>; };
template <> struct meshFieldToType < MeshF_Vel > { using type = Kokkos::View<vec2d_t*>; };
template <> struct meshFieldToType < MeshF_VtxMass > { using type = Kokkos::View<doubleSclr_t*>; };
template <> struct meshFieldToType < MeshF_ElmMass > { using type = Kokkos::View<doubleSclr_t*>; };
Expand All @@ -55,6 +57,7 @@ const std::map<MeshFieldIndex, std::pair<MeshFieldType,
{MeshF_VtxCoords, {MeshFType_VtxBased,"MeshField_VerticesCoords"}},
{MeshF_VtxRotLat, {MeshFType_VtxBased,"MeshField_VerticesLatitude"}},
{MeshF_ElmCenterXYZ, {MeshFType_ElmBased,"MeshField_ElementCenterXYZ"}},
{MeshF_DualTriangleArea, {MeshFType_VtxBased,"MeshField_DualTriangleArea"}},
{MeshF_Vel, {MeshFType_VtxBased,"MeshField_Velocity"}},
{MeshF_VtxMass, {MeshFType_VtxBased,"MeshField_VerticesMass"}},
{MeshF_ElmMass, {MeshFType_ElmBased,"MeshField_ElementsMass"}},
Expand Down Expand Up @@ -90,6 +93,7 @@ class Mesh {
MeshFView<MeshF_VtxCoords> vtxCoords_;
MeshFView<MeshF_VtxRotLat> vtxRotLat_;
MeshFView<MeshF_ElmCenterXYZ> elmCenterXYZ_;
MeshFView<MeshF_DualTriangleArea> dualTriangleArea_;
MeshFView<MeshF_Vel> vtxVel_;
MeshFView<MeshF_VtxMass> vtxMass_;
MeshFView<MeshF_ElmMass> elmMass_;
Expand Down Expand Up @@ -181,6 +185,9 @@ auto Mesh::getMeshField(){
else if constexpr (index==MeshF_ElmCenterXYZ){
return elmCenterXYZ_;
}
else if constexpr (index==MeshF_DualTriangleArea){
return dualTriangleArea_;
}
else if constexpr (index==MeshF_Vel){
return vtxVel_;
}
Expand Down
Loading