@@ -11,6 +11,7 @@ void printVTP_mesh(MPMesh& mpMesh, int printVTPIndex=-1);
1111void MPMesh::calculateStrain (){
1212 auto MPsPosition = p_MPs->getPositions ();
1313 auto MPsBasis = p_MPs->getData <MPF_Basis_Vals>();
14+ auto MPsBasisGrads = p_MPs->getData <MPF_Basis_Grad_Vals>();
1415 auto MPsAppID = p_MPs->getData <MPF_MP_APP_ID>();
1516 auto MPsStrainRate = p_MPs->getData <MPF_Strain_Rate>();
1617 // Mesh Fields
@@ -19,9 +20,6 @@ void MPMesh::calculateStrain(){
1920 auto gnomProjElmCenter = p_mesh->getMeshField <MeshF_ElmCenterGnomProj>();
2021 auto elm2VtxConn = p_mesh->getElm2VtxConn ();
2122 auto velField = p_mesh->getMeshField <MeshF_Vel>();
22- double radius = 1.0 ;
23- if (p_mesh->getGeomType () == geom_spherical_surf)
24- radius=p_mesh->getSphereRadius ();
2523
2624 bool isRotated = p_mesh->getRotatedFlag ();
2725
@@ -39,30 +37,28 @@ void MPMesh::calculateStrain(){
3937 computeGnomonicProjectionAtPoint (position3d, gnomProjElmCenter_sub, mpProjX, mpProjY);
4038 auto gnom_vtx_subview = Kokkos::subview (gnomProjVtx, elm, Kokkos::ALL, Kokkos::ALL);
4139
42- double basisByArea[maxVtxsPerElm] = {0.0 };
43- initArray (basisByArea,maxVtxsPerElm,0.0 );
44- double gradBasisByArea[2 *maxVtxsPerElm] = {0.0 };
45- initArray (gradBasisByArea,maxVtxsPerElm,0.0 );
46-
47- wachpress_weights_grads_2D (numVtx, gnom_vtx_subview, mpProjX, mpProjY, radius, basisByArea, gradBasisByArea);
48-
4940 double v11 = 0.0 ;
5041 double v12 = 0.0 ;
5142 double v21 = 0.0 ;
5243 double v22 = 0.0 ;
5344 double uTanOverR = 0.0 ;
5445 double vTanOverR = 0.0 ;
46+
5547 for (int i = 0 ; i < numVtx; i++){
5648 int iVertex = elm2VtxConn (elm, i+1 )-1 ;
57- v11 = v11 + gradBasisByArea[ i*2 + 0 ] * velField (iVertex, 0 );
58- v12 = v12 + gradBasisByArea[ i*2 + 1 ] * velField (iVertex, 0 );
59- v21 = v21 + gradBasisByArea[ i*2 + 0 ] * velField (iVertex, 1 );
60- v22 = v22 + gradBasisByArea[ i*2 + 1 ] * velField (iVertex, 1 );
61- uTanOverR = uTanOverR + basisByArea[i] * tanLatVertexRotatedOverRadius (iVertex, 0 ) * velField (iVertex, 0 );
62- vTanOverR = vTanOverR + basisByArea[i] * tanLatVertexRotatedOverRadius (iVertex, 0 ) * velField (iVertex, 1 );
49+ v11 = v11 + MPsBasisGrads (mp, i*2 + 0 ) * velField (iVertex, 0 );
50+ v12 = v12 + MPsBasisGrads (mp, i*2 + 1 ) * velField (iVertex, 0 );
51+ v21 = v21 + MPsBasisGrads (mp, i*2 + 0 ) * velField (iVertex, 1 );
52+ v22 = v22 + MPsBasisGrads (mp, i*2 + 1 ) * velField (iVertex, 1 );
53+ uTanOverR = uTanOverR + MPsBasis (mp, i) * tanLatVertexRotatedOverRadius (iVertex, 0 ) * velField (iVertex, 0 );
54+ vTanOverR = vTanOverR + MPsBasis (mp, i) * tanLatVertexRotatedOverRadius (iVertex, 0 ) * velField (iVertex, 1 );
6355 MPsStrainRate (mp, 0 ) = v11 - vTanOverR;
6456 MPsStrainRate (mp, 1 ) = v22;
6557 MPsStrainRate (mp, 2 ) = 0.5 *(v12 + v21 + uTanOverR);
58+ // Debugging
59+ if (MPsAppID (mp)==0 ){
60+ printf (" Strain Calc: iVertex %d vel field %.15e %.15e \n " , iVertex, velField (iVertex, 0 ), velField (iVertex, 1 ));
61+ }
6662 }
6763 MPsStrainRate (mp, 0 ) = v11 - vTanOverR;
6864 MPsStrainRate (mp, 1 ) = v22;
@@ -79,32 +75,133 @@ void MPMesh::calculateStress(){
7975 auto dynamicTimeStep = p_mesh->getDynamicTimeStep ();
8076 auto dampingTimescale = polyMPO::dampingTimescaleParameter * dynamicTimeStep;
8177 // MPFields
82- auto MPsAppID = p_MPs->getData <MPF_MP_APP_ID>();
83- auto MPsStrainRate = p_MPs->getData <MPF_Strain_Rate>();
84- auto MPsArea = p_MPs->getData <polyMPO::MPF_Area>();
78+ auto MPsAppID = p_MPs->getData <MPF_MP_APP_ID>();
79+ auto MPsStrainRate = p_MPs->getData <MPF_Strain_Rate>();
80+ auto MPsStress = p_MPs->getData <MPF_Stress>();
81+ auto MPsArea = p_MPs->getData <polyMPO::MPF_Area>();
8582 auto MPsIcePressure = p_MPs->getData <polyMPO::MPF_IcePressure>();
8683 auto MPsRepPressure = p_MPs->getData <polyMPO::MPF_ReplacementPressure>();
8784
8885 auto setMPStress = PS_LAMBDA (const int & elm, const int & mp, const int & mask){
8986 if (mask){
87+
88+ Vec3d strain_rate (MPsStrainRate (mp, 0 ), MPsStrainRate (mp, 1 ), MPsStrainRate (mp, 2 ));
89+ Vec3d stress (MPsStress (mp, 0 ), MPsStress (mp, 1 ), MPsStress (mp, 1 ));
90+ constitutive_evp (strain_rate, stress, MPsIcePressure (mp, 0 ), MPsRepPressure (mp, 0 ), MPsArea (mp, 0 ), elasticTimeStep, dampingTimescale);
91+ for (int m=0 ; m<3 ; m++)
92+ MPsStress (mp, m) = stress[m];
9093 // Debugging
9194 if (MPsAppID (mp)==0 ){
92- printf (" Strain %.15e %.15e %.15e\n " , MPsStrainRate (mp, 0 ), MPsStrainRate (mp, 1 ), MPsStrainRate (mp, 2 ));
93- printf (" Mesh:%.15e %d, MP:%.15e %.15e %.15e\n " ,elasticTimeStep,solveStress (elm),MPsArea (mp,0 ),MPsIcePressure (mp,0 ),MPsRepPressure (mp,0 ));
94- Vec3d strain_rate (MPsStrainRate (mp, 0 ), MPsStrainRate (mp, 1 ), MPsStrainRate (mp, 2 ));
95- Vec3d stress (0 , 0 , 0 );
96- constitutive_evp (strain_rate, stress, MPsIcePressure (mp, 0 ), MPsRepPressure (mp, 0 ), MPsArea (mp, 0 ), elasticTimeStep, dampingTimescale);
95+ printf (" Stress in GPU: %.15e %.15e %.15e\n " , MPsStress (mp, 0 ), MPsStress (mp, 1 ), MPsStress (mp, 2 ));
9796 }
9897 }
9998 };
10099 p_MPs->parallel_for (setMPStress, " setMPStress" );
101100}
102101
102+ void MPMesh::calculateStressDivergence (){
103+
104+ // Mesh Information
105+ auto elm2VtxConn = p_mesh->getElm2VtxConn ();
106+ int numVtx = p_mesh->getNumVertices ();
107+ auto vtxCoords = p_mesh->getMeshField <polyMPO::MeshF_VtxCoords>();
108+ int numVertices = p_mesh->getNumVertices ();
109+ auto tanLatVertexRotatedOverRadius = p_mesh->getMeshField <MeshF_TanLatVertexRotatedOverRadius>();
110+
111+ // Material Points
112+ auto MPsAppID = p_MPs->getData <MPF_MP_APP_ID>();
113+ auto weight = p_MPs->getData <MPF_Basis_Vals>();
114+ auto weight_grads = p_MPs->getData <MPF_Basis_Grad_Vals>();
115+ auto mpPos = p_MPs->getData <MPF_Cur_Pos_XYZ>();
116+ auto MPsStress = p_MPs->getData <MPF_Stress>();
117+ auto mpPositions = p_MPs->getData <MPF_Cur_Pos_XYZ>();
118+
119+ auto VtxCoeffs_new = this ->precomputedVtxCoeffs_new ;
120+
121+ // Earth Radius
122+ double radius = 1.0 ;
123+ if (p_mesh->getGeomType () == geom_spherical_surf)
124+ radius=p_mesh->getSphereRadius ();
125+
126+ // Reconstructed the stress
127+ Kokkos::View<double *[3 ]> stress_rec (" stress_rec" , p_mesh->getNumVertices ());
128+ Kokkos::View<double *> stress_divU (" stress_divu" , p_mesh->getNumVertices ());
129+ Kokkos::View<double *> stress_divV (" stress_divv" , p_mesh->getNumVertices ());
130+ Kokkos::View<double *> dSdX (" dSdX" , p_mesh->getNumVertices ());
131+ Kokkos::View<double *> dSdY (" dSdY" , p_mesh->getNumVertices ());
132+
133+ // Assemble fields for Stress Divergence
134+ auto stress_div = PS_LAMBDA (const int & elm, const int & mp, const int & mask) {
135+ if (mask) { // if material point is 'active'/'enabled'
136+ int nVtxE = elm2VtxConn (elm,0 ); // number of vertices bounding the element
137+ for (int i=0 ; i<nVtxE; i++){
138+ int vID = elm2VtxConn (elm,i+1 )-1 ;
139+ double w_vtx=weight (mp,i);
140+ double CoordDiffs[vec4d_nEntries] = {1 , (-vtxCoords (vID,0 ) + mpPositions (mp,0 ))/radius,
141+ (-vtxCoords (vID,1 ) + mpPositions (mp,1 ))/radius,
142+ (-vtxCoords (vID,2 ) + mpPositions (mp,2 ))/radius};
143+
144+ auto factor = w_vtx*(VtxCoeffs_new (vID,0 , 0 ) + VtxCoeffs_new (vID,0 , 1 )*CoordDiffs[1 ] +
145+ VtxCoeffs_new (vID,0 , 2 )*CoordDiffs[2 ] +
146+ VtxCoeffs_new (vID,0 , 3 )*CoordDiffs[3 ]);
147+
148+ auto factor1 = (w_vtx/radius)*(VtxCoeffs_new (vID,1 , 0 ) + VtxCoeffs_new (vID,1 , 1 )*CoordDiffs[1 ] +
149+ VtxCoeffs_new (vID,1 , 2 )*CoordDiffs[2 ] +
150+ VtxCoeffs_new (vID,1 , 3 )*CoordDiffs[3 ]);
151+ auto factor2 = (w_vtx/radius)*(VtxCoeffs_new (vID,2 , 0 ) + VtxCoeffs_new (vID,2 , 1 )*CoordDiffs[1 ] +
152+ VtxCoeffs_new (vID,2 , 2 )*CoordDiffs[2 ] +
153+ VtxCoeffs_new (vID,2 , 3 )*CoordDiffs[3 ]);
154+
155+ for (int k=0 ; k<3 ; k++){
156+ auto val = factor*MPsStress (mp,k);
157+ Kokkos::atomic_add (&stress_rec (vID,k), val);
158+ }
159+ Kokkos::atomic_add (&stress_divU (vID), factor1 * MPsStress (mp, 0 ) + factor2 * MPsStress (mp, 2 ) -
160+ 2 * tanLatVertexRotatedOverRadius (vID, 0 ) * factor * MPsStress (mp, 2 ));
161+ Kokkos::atomic_add (&stress_divV (vID), factor2 * MPsStress (mp, 1 ) + factor1*MPsStress (mp, 2 ) +
162+ factor * tanLatVertexRotatedOverRadius (vID, 0 ) * (MPsStress (mp, 0 )-MPsStress (mp, 1 )));
163+ Kokkos::atomic_add (&dSdX (vID), -factor * weight_grads (mp, i*2 + 0 ));
164+ Kokkos::atomic_add (&dSdY (vID), -factor * weight_grads (mp, i*2 + 1 ));
165+ }
166+ }
167+ };
168+ p_MPs->parallel_for (stress_div, " assembly" );
169+
170+ // TODO
171+ // COMMUNICATE THE VERTEX FIELDS
172+
173+ // TODO put as mesh field
174+ Kokkos::View<doubleSclr_t*> stressDivergence (" stressDivergence" , p_mesh->getNumVertices ());
175+ auto areaVertex = p_mesh->getMeshField <MeshF_DualTriangleArea>();
176+
177+ Kokkos::parallel_for (" calculate_divergence" , numVtx, KOKKOS_LAMBDA (const int vtx){
178+ double threshold = 0.15 / Kokkos::sqrt (areaVertex (vtx, 0 ));
179+ double valX = Kokkos::max (Kokkos::abs (dSdX (vtx)) - threshold, 0.0 );
180+ double dSdX_filtered = Kokkos::copysign (valX, dSdX (vtx));
181+ double valY = Kokkos::max (Kokkos::abs (dSdY (vtx)) - threshold, 0.0 );
182+ double dSdY_filtered = Kokkos::copysign (valY, dSdY (vtx));
183+
184+ stressDivergence (vtx, 0 ) = stress_divU (vtx) + dSdX_filtered * stress_rec (vtx, 0 ) + dSdY_filtered * stress_rec (vtx, 2 );
185+ stressDivergence (vtx, 1 ) = stress_divV (vtx) + dSdY_filtered * stress_rec (vtx, 1 ) + dSdX_filtered * stress_rec (vtx, 2 );
186+ // Debugging
187+ if (vtx >= 10 && vtx <= 11 ) {
188+ printf (" Vtx %d Area %.15e ds: %.15e %.15e \n " , vtx, areaVertex (vtx, 0 ), dSdX_filtered, dSdY_filtered);
189+ printf (" Vtx %d Divergence %.15e %.15e \n " , vtx, stressDivergence (vtx, 0 ), stressDivergence (vtx, 1 ));
190+ }
191+ });
192+
193+ // TODO
194+ // COMMUNICATE THE VERTEX FIELDS
195+
196+ }
197+
198+
103199void MPMesh::calcBasis () {
104200 assert (p_mesh->getGeomType () == geom_spherical_surf);
105201
106202 auto MPsPosition = p_MPs->getPositions ();
107203 auto MPsBasis = p_MPs->getData <MPF_Basis_Vals>();
204+ auto MPsBasisGrads = p_MPs->getData <MPF_Basis_Grad_Vals>();
108205 auto MPsAppID = p_MPs->getData <MPF_MP_APP_ID>();
109206
110207 auto elm2VtxConn = p_mesh->getElm2VtxConn ();
@@ -141,7 +238,9 @@ void MPMesh::calcBasis() {
141238 wachpress_weights_grads_2D (numVtx, gnom_vtx_subview, mpProjX, mpProjY, radius, basisByArea, gradBasisByArea);
142239
143240 for (int i=0 ; i<= numVtx; i++){
144- MPsBasis (mp,i) = basisByArea[i];
241+ MPsBasis (mp, i) = basisByArea[i];
242+ MPsBasisGrads (mp, i*2 +0 ) = gradBasisByArea[i*2 + 0 ];
243+ MPsBasisGrads (mp, i*2 +1 ) = gradBasisByArea[i*2 + 1 ];
145244 }
146245
147246 // Old method where basis functions calculated using 3D Area
0 commit comments