|
PISM, A Parallel Ice Sheet Model stable 0.4.1779
|
00001 // Copyright (C) 2009--2011 Jed Brown and Ed Bueler and Constantine Khroulev and David Maxwell 00002 // 00003 // This file is part of PISM. 00004 // 00005 // PISM is free software; you can redistribute it and/or modify it under the 00006 // terms of the GNU General Public License as published by the Free Software 00007 // Foundation; either version 2 of the License, or (at your option) any later 00008 // version. 00009 // 00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY 00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00012 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 00013 // details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with PISM; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 #include "SSAFEM_Forward.hh" 00020 #include "Mask.hh" 00021 00022 PetscErrorCode SSAFEM_Forward::allocate_ksp() 00023 { 00024 PetscErrorCode ierr; 00025 00026 // Storage for vector unknowns. 00027 ierr = DAGetMatrix(SSADA, "baij", &m_MatA); CHKERRQ(ierr); 00028 ierr = DACreateLocalVector(SSADA, &m_VecU); CHKERRQ(ierr); 00029 ierr = DACreateGlobalVector(SSADA, &m_VecZ2); CHKERRQ(ierr); 00030 ierr = DACreateLocalVector(SSADA, &m_VecZ); CHKERRQ(ierr); 00031 ierr = DACreateGlobalVector(SSADA, &m_VecRHS2); CHKERRQ(ierr); 00032 00033 // Storage for scalar unknowns. 00034 ierr = DAGetMatrix(grid.da2, "baij", &m_MatB); CHKERRQ(ierr); 00035 ierr = DACreateGlobalVector(grid.da2, &m_VecRHS); CHKERRQ(ierr); 00036 ierr = DACreateGlobalVector(grid.da2, &m_VecV); CHKERRQ(ierr); 00037 00038 ierr = KSPCreate(grid.com, &m_KSP); CHKERRQ(ierr); 00039 PetscReal ksp_rtol = 1e-12; 00040 ierr = KSPSetTolerances(m_KSP,ksp_rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); 00041 PC pc; 00042 ierr = KSPGetPC(m_KSP,&pc); CHKERRQ(ierr); 00043 ierr = PCSetType(pc,PCBJACOBI); CHKERRQ(ierr); 00044 ierr = KSPSetFromOptions(m_KSP); CHKERRQ(ierr); 00045 00046 00047 ierr = KSPCreate(grid.com, &m_KSP_B); CHKERRQ(ierr); 00048 ierr = KSPSetTolerances(m_KSP_B,ksp_rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); 00049 PC pc_B; 00050 ierr = KSPGetPC(m_KSP_B,&pc_B); CHKERRQ(ierr); 00051 ierr = PCSetType(pc_B,PCBJACOBI); CHKERRQ(ierr); 00052 ierr = KSPSetFromOptions(m_KSP_B); CHKERRQ(ierr); 00053 00054 return 0; 00055 } 00056 00057 PetscErrorCode SSAFEM_Forward::deallocate_ksp() 00058 { 00059 PetscErrorCode ierr; 00060 00061 if (m_KSP != PETSC_NULL) { 00062 ierr = KSPDestroy(m_KSP); CHKERRQ(ierr); 00063 } 00064 00065 if (m_KSP_B != PETSC_NULL) { 00066 ierr = KSPDestroy(m_KSP_B); CHKERRQ(ierr); 00067 } 00068 00069 if (m_MatA != PETSC_NULL) { 00070 ierr = MatDestroy(m_MatA); CHKERRQ(ierr); 00071 } 00072 00073 if (m_MatB != PETSC_NULL) { 00074 ierr = MatDestroy(m_MatB); CHKERRQ(ierr); 00075 } 00076 00077 if (m_VecU != PETSC_NULL) { 00078 ierr = VecDestroy(m_VecU); CHKERRQ(ierr); 00079 } 00080 00081 if (m_VecRHS2 != PETSC_NULL) { 00082 ierr = VecDestroy(m_VecRHS2); CHKERRQ(ierr); 00083 } 00084 00085 if (m_VecRHS != PETSC_NULL) { 00086 ierr = VecDestroy(m_VecRHS); CHKERRQ(ierr); 00087 } 00088 00089 if (m_VecZ != PETSC_NULL) { 00090 ierr = VecDestroy(m_VecZ); CHKERRQ(ierr); 00091 } 00092 00093 if (m_VecZ2 != PETSC_NULL) { 00094 ierr = VecDestroy(m_VecZ2); CHKERRQ(ierr); 00095 } 00096 00097 if (m_VecV != PETSC_NULL) { 00098 ierr = VecDestroy(m_VecV); CHKERRQ(ierr); 00099 } 00100 00101 return 0; 00102 } 00103 00104 PetscErrorCode SSAFEM_Forward::set_initial_velocity_guess( IceModelVec2V &v ) 00105 { 00106 PetscErrorCode ierr; 00107 ierr = v.copy_to(SSAX); CHKERRQ(ierr); 00108 m_reassemble_T_matrix_needed = true; 00109 return 0; 00110 } 00111 00112 PetscErrorCode SSAFEM_Forward::setup_vars() 00113 { 00114 PetscErrorCode ierr; 00115 ierr = setup(); CHKERRQ(ierr); 00116 ierr = assemble_DomainNorm_matrix(); CHKERRQ(ierr); 00117 00118 return 0; 00119 } 00120 00121 PetscErrorCode SSAFEM_Forward::set_tauc(IceModelVec2S &new_tauc ) 00122 { 00123 PetscErrorCode ierr; 00124 PetscInt i,j,q; 00125 00126 PetscReal **tauc_array; 00127 ierr = new_tauc.get_array(tauc_array);CHKERRQ(ierr); 00128 PetscInt xs = element_index.xs, xm = element_index.xm, 00129 ys = element_index.ys, ym = element_index.ym; 00130 for (i=xs; i<xs+xm; i++) { 00131 for (j=ys;j<ys+ym; j++) { 00132 PetscReal taucq[FEQuadrature::Nq]; 00133 quadrature.computeTrialFunctionValues(i,j,dofmap,tauc_array,taucq); 00134 const PetscInt ij = element_index.flatten(i,j); 00135 FEStoreNode *feS = &feStore[4*ij]; 00136 for (q=0; q<4; q++) { 00137 feS[q].tauc = taucq[q]; // Or exp(taucq[q])! 00138 } 00139 } 00140 } 00141 ierr = new_tauc.end_access();CHKERRQ(ierr); 00142 00143 m_reassemble_T_matrix_needed = true; 00144 m_forward_F_needed = true; 00145 00146 return 0; 00147 } 00148 00149 PetscErrorCode SSAFEM_Forward::solveF_core() 00150 { 00151 PetscErrorCode ierr; 00152 if(m_forward_F_needed) 00153 { 00154 // Set the SNES callbacks to call into our compute_local_function and compute_local_jacobian 00155 // methods via SSAFEFunction and SSAFEJ 00156 ierr = DASetLocalFunction(SSADA,(DALocalFunction1)SSAFEFunction);CHKERRQ(ierr); 00157 ierr = DASetLocalJacobian(SSADA,(DALocalFunction1)SSAFEJacobian);CHKERRQ(ierr); 00158 callback_data.da = SSADA; callback_data.ssa = this; 00159 ierr = SNESSetFunction(snes, r, SNESDAFormFunction, &callback_data);CHKERRQ(ierr); 00160 ierr = SNESSetJacobian(snes, J, J, SNESDAComputeJacobian,&callback_data);CHKERRQ(ierr); 00161 00162 // Solve: 00163 ierr = SNESSolve(snes,NULL,SSAX);CHKERRQ(ierr); 00164 00165 // See if it worked. 00166 SNESConvergedReason reason; 00167 ierr = SNESGetConvergedReason( snes, &reason); CHKERRQ(ierr); 00168 if(reason < 0) { 00169 SETERRQ1(1, 00170 "SSAFEM solve failed to converge (SNES reason %s)\n\n", SNESConvergedReasons[reason]); 00171 } 00172 verbPrintf(3,grid.com,"SSAFEM solve converged (SNES reason %s)\n\n", SNESConvergedReasons[reason]); 00173 00174 ierr = DAGlobalToLocalBegin(SSADA, SSAX, INSERT_VALUES, m_VecU); CHKERRQ(ierr); 00175 ierr = DAGlobalToLocalEnd(SSADA, SSAX, INSERT_VALUES, m_VecU); CHKERRQ(ierr); 00176 // ierr = DALocalToLocalBegin(SSADA, m_VecU, INSERT_VALUES, m_VecU); CHKERRQ(ierr); 00177 // ierr = DALocalToLocalEnd(SSADA, m_VecU, INSERT_VALUES, m_VecU); CHKERRQ(ierr); 00178 00179 m_forward_F_needed = false; 00180 } 00181 return 0; 00182 } 00183 00184 PetscErrorCode SSAFEM_Forward::solveF(IceModelVec2V &result) 00185 { 00186 PetscErrorCode ierr; 00187 ierr = solveF_core(); CHKERRQ(ierr); 00188 00189 ierr = result.copy_from(SSAX); CHKERRQ(ierr); 00190 ierr = result.beginGhostComm(); CHKERRQ(ierr); 00191 ierr = result.endGhostComm(); CHKERRQ(ierr); 00192 return 0; 00193 } 00194 00195 00196 PetscErrorCode SSAFEM_Forward::solveT( IceModelVec2S &dtauc, IceModelVec2V &result) 00197 { 00198 KSPConvergedReason reason; 00199 PetscErrorCode ierr; 00200 PetscScalar **dtauc_a; 00201 PISMVector2 **vel; 00202 PISMVector2 **rhs; 00203 00204 ierr = solveF_core(); CHKERRQ(ierr); 00205 00206 if(m_reassemble_T_matrix_needed) 00207 { 00208 assemble_T_matrix(); 00209 } 00210 00211 dtauc.get_array(dtauc_a); 00212 ierr = DAVecGetArray(SSADA,m_VecU,&vel); CHKERRQ(ierr); 00213 ierr = DAVecGetArray(SSADA,m_VecRHS2,&rhs); CHKERRQ(ierr); 00214 ierr = assemble_T_rhs(vel,dtauc_a,rhs); CHKERRQ(ierr); 00215 dtauc.end_access(); 00216 ierr = DAVecRestoreArray(SSADA, m_VecU, &vel); CHKERRQ(ierr); 00217 ierr = DAVecRestoreArray(SSADA, m_VecRHS2, &rhs); CHKERRQ(ierr); 00218 00219 00220 00221 // call PETSc to solve linear system by iterative method. 00222 ierr = KSPSetOperators(m_KSP, m_MatA, m_MatA, SAME_NONZERO_PATTERN); CHKERRQ(ierr); 00223 ierr = KSPSolve(m_KSP, m_VecRHS2, m_VecZ2); CHKERRQ(ierr); // SOLVE 00224 00225 ierr = KSPGetConvergedReason(m_KSP, &reason); CHKERRQ(ierr); 00226 if (reason < 0) { 00227 SETERRQ1(1, 00228 "SSAFEM_Forward::solveT solve failed to converge (KSP reason %s)\n\n", KSPConvergedReasons[reason]); 00229 } 00230 else 00231 { 00232 verbPrintf(4,grid.com,"SSAFEM_Forward::solveT converged (KSP reason %s)\n", KSPConvergedReasons[reason] ); 00233 } 00234 00235 // Extract the solution and communicate. 00236 ierr = result.copy_from(m_VecZ2); CHKERRQ(ierr); 00237 ierr = result.beginGhostComm(); CHKERRQ(ierr); 00238 ierr = result.endGhostComm(); CHKERRQ(ierr); 00239 00240 return 0; 00241 } 00242 00243 PetscErrorCode SSAFEM_Forward::solveTStar( IceModelVec2V &residual, IceModelVec2S &result) 00244 { 00245 KSPConvergedReason reason; 00246 PetscErrorCode ierr; 00247 PISMVector2 **R; 00248 PISMVector2 **U; 00249 PISMVector2 **RHS2; 00250 PISMVector2 **Z; 00251 PetscScalar **RHS; 00252 00253 // Solve the nonlinear forward problem if this has not yet been done. 00254 ierr = solveF_core(); CHKERRQ(ierr); 00255 00256 // If tauc has been updated, we'll need to update the linearized forward map. 00257 if(m_reassemble_T_matrix_needed) 00258 { 00259 assemble_T_matrix(); 00260 } 00261 00262 // Assemble the right-hand side for the first step. 00263 residual.get_array(R); 00264 ierr = DAVecGetArray(SSADA,m_VecRHS2,&RHS2); CHKERRQ(ierr); 00265 ierr = assemble_TStarA_rhs(R,RHS2); CHKERRQ(ierr); 00266 ierr = DAVecRestoreArray(SSADA, m_VecRHS2, &RHS2); CHKERRQ(ierr); 00267 residual.end_access(); 00268 00269 // call PETSc to solve linear system by iterative method. 00270 ierr = KSPSetOperators(m_KSP, m_MatA, m_MatA, SAME_NONZERO_PATTERN); CHKERRQ(ierr); 00271 ierr = KSPSolve(m_KSP, m_VecRHS2, m_VecZ2); CHKERRQ(ierr); // SOLVE 00272 ierr = KSPGetConvergedReason(m_KSP, &reason); CHKERRQ(ierr); 00273 if (reason < 0) { 00274 SETERRQ1(1, 00275 "SSAFEM_Forward::solveTStarA solve failed to converge (KSP reason %s)\n\n", KSPConvergedReasons[reason]); 00276 } 00277 else 00278 { 00279 verbPrintf(4,grid.com,"SSAFEM_Forward::solveTStarA converged (KSP reason %s)\n", KSPConvergedReasons[reason] ); 00280 } 00281 00282 00283 ierr = DAGlobalToLocalBegin(SSADA, m_VecZ2, INSERT_VALUES, m_VecZ); CHKERRQ(ierr); 00284 ierr = DAGlobalToLocalEnd(SSADA, m_VecZ2, INSERT_VALUES, m_VecZ); CHKERRQ(ierr); 00285 00286 // Assemble the right-hand side for the second step. 00287 ierr = DAVecGetArray(SSADA,m_VecZ,&Z); CHKERRQ(ierr); 00288 ierr = DAVecGetArray(SSADA,m_VecU,&U); CHKERRQ(ierr); 00289 ierr = DAVecGetArray(grid.da2,m_VecRHS,&RHS); CHKERRQ(ierr); 00290 ierr = assemble_TStarB_rhs(Z,U,RHS); CHKERRQ(ierr); 00291 ierr = DAVecRestoreArray(grid.da2,m_VecRHS,&RHS); CHKERRQ(ierr); 00292 ierr = DAVecRestoreArray(SSADA,m_VecU,&U); CHKERRQ(ierr); 00293 ierr = DAVecRestoreArray(SSADA,m_VecZ,&Z); CHKERRQ(ierr); 00294 00295 00296 // call PETSc to solve linear system by iterative method. 00297 ierr = KSPSetOperators(m_KSP_B, m_MatB, m_MatB, SAME_NONZERO_PATTERN); CHKERRQ(ierr); 00298 ierr = KSPSolve(m_KSP_B, m_VecRHS, m_VecV); CHKERRQ(ierr); // SOLVE 00299 ierr = KSPGetConvergedReason(m_KSP, &reason); CHKERRQ(ierr); 00300 if (reason < 0) { 00301 SETERRQ1(1, 00302 "SSAFEM_Forward::solveTStarB solve failed to converge (KSP reason %s)\n\n", KSPConvergedReasons[reason]); 00303 } 00304 else { 00305 verbPrintf(4,grid.com,"SSAFEM_Forward::solveTStarB converged (KSP reason %s)\n", KSPConvergedReasons[reason] ); 00306 } 00307 00308 // Extract the solution and communicate. 00309 ierr = result.copy_from(m_VecV); CHKERRQ(ierr); 00310 ierr = result.beginGhostComm(); CHKERRQ(ierr); 00311 ierr = result.endGhostComm(); CHKERRQ(ierr); 00312 00313 return 0; 00314 } 00315 00316 PetscErrorCode SSAFEM_Forward::assemble_T_matrix() 00317 { 00318 PISMVector2 **vel; 00319 PetscErrorCode ierr; 00320 00321 ierr = DAVecGetArray(SSADA,m_VecU,&vel); CHKERRQ(ierr); 00322 00323 DALocalInfo *info = NULL; 00324 ierr = compute_local_jacobian(info,const_cast<const PISMVector2**>(vel),m_MatA); 00325 00326 ierr = DAVecRestoreArray(SSADA, m_VecU, &vel); CHKERRQ(ierr); 00327 return 0; 00328 } 00329 00330 PetscErrorCode SSAFEM_Forward::assemble_DomainNorm_matrix() 00331 { 00332 // Just L2 matrix for now. 00333 PetscInt i,j; 00334 PetscErrorCode ierr; 00335 00336 // Zero out the Jacobian in preparation for updating it. 00337 ierr = MatZeroEntries(m_MatB);CHKERRQ(ierr); 00338 00339 // Jacobian times weights for quadrature. 00340 PetscScalar JxW[FEQuadrature::Nq]; 00341 quadrature.getWeightedJacobian(JxW); 00342 00343 // Values of the finite element test functions at the quadrature points. 00344 // This is an Nq by Nk array of function germs (Nq=#of quad pts, Nk=#of test functions). 00345 const FEFunctionGerm (*test)[FEQuadrature::Nk] = quadrature.testFunctionValues(); 00346 00347 // Loop through all the elements. 00348 PetscInt xs = element_index.xs, xm = element_index.xm, 00349 ys = element_index.ys, ym = element_index.ym; 00350 for (i=xs; i<xs+xm; i++) { 00351 for (j=ys; j<ys+ym; j++) { 00352 // Element-local Jacobian matrix (there are FEQuadrature::Nk vector valued degrees 00353 // of freedom per elment, for a total of (2*FEQuadrature::Nk)*(2*FEQuadrature::Nk) = 16 00354 // entries in the local Jacobian. 00355 PetscReal K[FEQuadrature::Nk][FEQuadrature::Nk]; 00356 00357 // Initialize the map from global to local degrees of freedom for this element. 00358 dofmap.reset(i,j,grid); 00359 00360 // Build the element-local Jacobian. 00361 ierr = PetscMemzero(K,sizeof(K));CHKERRQ(ierr); 00362 for (PetscInt q=0; q<FEQuadrature::Nq; q++) { 00363 for (PetscInt k=0; k<4; k++) { // Test functions 00364 for (PetscInt l=0; l<4; l++) { // Trial functions 00365 const FEFunctionGerm &test_qk=test[q][k]; 00366 const FEFunctionGerm &test_ql=test[q][l]; 00367 K[k][l] += JxW[q]*test_qk.val*test_ql.val; 00368 } // l 00369 } // k 00370 } // q 00371 ierr = dofmap.addLocalJacobianBlock(&K[0][0],m_MatB); 00372 } // j 00373 } // i 00374 00375 ierr = MatAssemblyBegin(m_MatB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 00376 ierr = MatAssemblyEnd(m_MatB,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 00377 00378 return 0; 00379 } 00380 00381 PetscErrorCode SSAFEM_Forward::domainIP(Vec a, Vec b, PetscScalar *OUTPUT) 00382 { 00383 PetscErrorCode ierr; 00384 PetscScalar **A, **B; 00385 ierr = DAVecGetArray(grid.da2,a,&A); CHKERRQ(ierr); 00386 ierr = DAVecGetArray(grid.da2,b,&B); CHKERRQ(ierr); 00387 ierr = domainIP_core(A,B,OUTPUT); 00388 ierr = DAVecRestoreArray(grid.da2,a,&A); CHKERRQ(ierr); 00389 ierr = DAVecRestoreArray(grid.da2,b,&B); CHKERRQ(ierr); 00390 return 0; 00391 } 00392 PetscErrorCode SSAFEM_Forward::domainIP(IceModelVec2S &a, IceModelVec2S &b, PetscScalar *OUTPUT) 00393 { 00394 PetscErrorCode ierr; 00395 PetscReal **A, **B; 00396 ierr = a.get_array(A); CHKERRQ(ierr); 00397 ierr = b.get_array(B); CHKERRQ(ierr); 00398 ierr = domainIP_core(A,B,OUTPUT); 00399 ierr = a.end_access(); CHKERRQ(ierr); 00400 ierr = b.end_access(); CHKERRQ(ierr); 00401 return 0; 00402 } 00403 00404 PetscErrorCode SSAFEM_Forward::rangeIP(Vec a, Vec b, PetscScalar *OUTPUT) 00405 { 00406 PetscErrorCode ierr; 00407 PISMVector2 **A, **B; 00408 ierr = DAVecGetArray(SSADA,a,&A); CHKERRQ(ierr); 00409 ierr = DAVecGetArray(SSADA,b,&B); CHKERRQ(ierr); 00410 ierr = rangeIP_core(A,B,OUTPUT); 00411 ierr = DAVecRestoreArray(SSADA,a,&A); CHKERRQ(ierr); 00412 ierr = DAVecRestoreArray(SSADA,b,&B); CHKERRQ(ierr); 00413 return 0; 00414 } 00415 00416 PetscErrorCode SSAFEM_Forward::rangeIP(IceModelVec2V &a, IceModelVec2V &b, PetscScalar *OUTPUT) 00417 { 00418 PetscErrorCode ierr; 00419 PISMVector2 **A, **B; 00420 ierr = a.get_array(A); CHKERRQ(ierr); 00421 ierr = b.get_array(B); CHKERRQ(ierr); 00422 ierr = rangeIP_core(A,B,OUTPUT); 00423 ierr = a.end_access(); CHKERRQ(ierr); 00424 ierr = b.end_access(); CHKERRQ(ierr); 00425 return 0; 00426 } 00427 00428 PetscErrorCode SSAFEM_Forward::domainIP_core(PetscReal **A, PetscReal**B, PetscScalar *OUTPUT) 00429 { 00430 00431 // Just L2 matrix for now. 00432 PetscInt i,j; 00433 PetscErrorCode ierr; 00434 00435 // The value of the inner product. 00436 PetscReal IP = 0; 00437 00438 PetscReal a[FEQuadrature::Nq], b[FEQuadrature::Nq]; 00439 00440 // Jacobian times weights for quadrature. 00441 PetscScalar JxW[FEQuadrature::Nq]; 00442 quadrature.getWeightedJacobian(JxW); 00443 00444 // Loop through all LOCAL elements. 00445 PetscInt xs = element_index.lxs, xm = element_index.lxm, 00446 ys = element_index.lys, ym = element_index.lym; 00447 for (i=xs; i<xs+xm; i++) { 00448 for (j=ys; j<ys+ym; j++) { 00449 quadrature.computeTrialFunctionValues(i,j,dofmap,A,a); 00450 quadrature.computeTrialFunctionValues(i,j,dofmap,B,b); 00451 for (PetscInt q=0; q<FEQuadrature::Nq; q++) { 00452 IP += JxW[q]*a[q]*b[q]; 00453 } // q 00454 } // j 00455 } // i 00456 00457 ierr = PetscGlobalSum(&IP, OUTPUT, grid.com); CHKERRQ(ierr); 00458 return 0; 00459 } 00460 00461 PetscErrorCode SSAFEM_Forward::rangeIP_core(PISMVector2 **A, PISMVector2**B, PetscScalar *OUTPUT) 00462 { 00463 PetscInt i,j; 00464 PetscErrorCode ierr; 00465 00466 // The value of the inner product on the local part of the domain. 00467 PetscReal IP = 0; 00468 00469 PISMVector2 a[FEQuadrature::Nq], b[FEQuadrature::Nq]; 00470 00471 // Jacobian times weights for quadrature. 00472 PetscScalar JxW[FEQuadrature::Nq]; 00473 quadrature.getWeightedJacobian(JxW); 00474 00475 // Loop through all LOCAL elements. 00476 PetscInt xs = element_index.lxs, xm = element_index.lxm, 00477 ys = element_index.lys, ym = element_index.lym; 00478 for (i=xs; i<xs+xm; i++) { 00479 for (j=ys; j<ys+ym; j++) { 00480 PISMVector2 tmp[FEQuadrature::Nq]; 00481 dofmap.extractLocalDOFs(i,j,A,tmp); 00482 quadrature.computeTrialFunctionValues(tmp,a); 00483 dofmap.extractLocalDOFs(i,j,B,tmp); 00484 quadrature.computeTrialFunctionValues(tmp,b); 00485 00486 // quadrature.computeTrialFunctionValues(i,j,dofmap,A,a); 00487 // quadrature.computeTrialFunctionValues(i,j,dofmap,B,b); 00488 for (PetscInt q=0; q<FEQuadrature::Nq; q++) { 00489 IP += JxW[q]*(a[q].u*b[q].u + a[q].v*b[q].v); 00490 } // q 00491 } // j 00492 } // i 00493 00494 PetscReal area = 4*grid.Lx*grid.Ly; 00495 IP /= area; 00496 ierr = PetscGlobalSum(&IP, OUTPUT, grid.com); CHKERRQ(ierr); 00497 00498 return 0; 00499 } 00500 00501 PetscErrorCode SSAFEM_Forward::assemble_T_rhs( PISMVector2 **gvel, PetscReal **gdtauc, PISMVector2 **grhs) 00502 { 00503 PetscInt i,j,k,q; 00504 PetscErrorCode ierr; 00505 PetscReal **bc_mask; 00506 00507 // Zero out the portion of the function we are responsible for computing. 00508 for (i=grid.xs; i<grid.xs+grid.xm; i++) { 00509 for (j=grid.ys; j<grid.ys+grid.ym; j++) { 00510 grhs[i][j].u = 0; 00511 grhs[i][j].v = 0; 00512 } 00513 } 00514 00515 // Start access of Dirichlet data, if present. 00516 if (bc_locations && vel_bc) { 00517 ierr = bc_locations->get_array(bc_mask);CHKERRQ(ierr); 00518 } 00519 00520 // Jacobian times weights for quadrature. 00521 PetscScalar JxW[FEQuadrature::Nq]; 00522 quadrature.getWeightedJacobian(JxW); 00523 00524 // Storage for velocity and dtauc at quadrature points. 00525 PISMVector2 u[FEQuadrature::Nq]; 00526 PetscReal dtauc[FEQuadrature::Nq]; 00527 00528 // An Nq by Nk array of test function values. 00529 const FEFunctionGerm (*test)[FEQuadrature::Nk] = quadrature.testFunctionValues(); 00530 00531 // Flags for each vertex in an element that determine if explicit Dirichlet data has 00532 // been set. 00533 PetscReal local_bc_mask[FEQuadrature::Nk]; 00534 Mask M; 00535 00536 // Iterate over the elements. 00537 PetscInt xs = element_index.xs, xm = element_index.xm, 00538 ys = element_index.ys, ym = element_index.ym; 00539 for (i=xs; i<xs+xm; i++) { 00540 for (j=ys; j<ys+ym; j++) { 00541 // Storage for element-local data 00542 PISMVector2 y[4]; 00543 00544 // Index into coefficient storage in feStore 00545 const PetscInt ij = element_index.flatten(i,j); 00546 00547 // Initialize the map from global to local degrees of freedom for this element. 00548 dofmap.reset(i,j,grid); 00549 00550 // These values now need to be adjusted if some nodes in the element have 00551 // Dirichlet data. 00552 if(bc_locations && vel_bc) { 00553 dofmap.extractLocalDOFs(i,j,bc_mask,local_bc_mask); 00554 for (k=0; k<4; k++) { 00555 if (PismIntMask(local_bc_mask[k]) == 1) { // Dirichlet node 00556 // Mark any kind of Dirichlet node as not to be touched 00557 dofmap.markRowInvalid(k); 00558 dofmap.markColInvalid(k); 00559 } 00560 } 00561 } 00562 00563 // Obtain the value of the solution at the adjacent nodes to the element. 00564 quadrature.computeTrialFunctionValues(i,j,dofmap,gvel,u); 00565 quadrature.computeTrialFunctionValues(i,j,dofmap,gdtauc,dtauc); 00566 00567 // Zero out the element-local residual in prep for updating it. 00568 for(k=0;k<FEQuadrature::Nk;k++){ 00569 y[k].u = 0; y[k].v = 0; 00570 } 00571 00572 for (q=0; q<FEQuadrature::Nq; q++) { // loop over quadrature points on this element. 00573 00574 // Coefficients and weights for this quadrature point. 00575 const FEStoreNode *feS = &feStore[ij*FEQuadrature::Nq+q]; 00576 const PetscReal jw = JxW[q]; 00577 00578 // Determine dbeta/dtauc at the quadrature point 00579 PetscReal dbeta_dtauc = 0; 00580 if( M.grounded_ice(feS->mask) ) { 00581 dbeta_dtauc = basal.drag(dtauc[q],u[q].u,u[q].v); 00582 } 00583 // dbeta_dtauc *= exp(dtauc[q]) 00584 00585 for(k=0; k<FEQuadrature::Nk;k++) { // loop over the test functions. 00586 const FEFunctionGerm &testqk = test[q][k]; 00587 //Note the -= (not +=) in the following lines. 00588 y[k].u -= jw*dbeta_dtauc*testqk.val*u[q].u; 00589 y[k].v -= jw*dbeta_dtauc*testqk.val*u[q].v; 00590 } // k 00591 } // q 00592 00593 dofmap.addLocalResidualBlock(y,grhs); 00594 } // j-loop 00595 } // i-loop 00596 00597 // Until now we have not touched rows in the residual corresponding to Dirichlet data. 00598 // We fix this now. 00599 if (bc_locations && vel_bc) { 00600 // Enforce Dirichlet conditions strongly 00601 for (i=grid.xs; i<grid.xs+grid.xm; i++) { 00602 for (j=grid.ys; j<grid.ys+grid.ym; j++) { 00603 if (bc_locations->as_int(i,j) == 1) { 00604 // Enforce explicit homogeneous dirichlet data. 00605 grhs[i][j].u = 0; 00606 grhs[i][j].v = 0; 00607 } 00608 } 00609 } 00610 ierr = bc_locations->end_access();CHKERRQ(ierr); 00611 } 00612 00613 return 0; 00614 } 00615 00616 PetscErrorCode SSAFEM_Forward::assemble_TStarA_rhs( PISMVector2 **R, PISMVector2 **RHS) 00617 { 00618 PetscInt i,j,k,q; 00619 PetscErrorCode ierr; 00620 PetscReal **bc_mask; 00621 00622 // Zero out the portion of the function we are responsible for computing. 00623 for (i=grid.xs; i<grid.xs+grid.xm; i++) { 00624 for (j=grid.ys; j<grid.ys+grid.ym; j++) { 00625 RHS[i][j].u = 0; 00626 RHS[i][j].v = 0; 00627 } 00628 } 00629 00630 PetscReal area = 4*grid.Lx*grid.Ly; 00631 00632 // Start access of Dirichlet data, if present. 00633 if (bc_locations && vel_bc) { 00634 ierr = bc_locations->get_array(bc_mask);CHKERRQ(ierr); 00635 } 00636 00637 // Jacobian times weights for quadrature. 00638 PetscScalar JxW[FEQuadrature::Nq]; 00639 quadrature.getWeightedJacobian(JxW); 00640 00641 // Flags for each vertex in an element that determine if explicit Dirichlet data has 00642 // been set. 00643 PetscReal local_bc_mask[FEQuadrature::Nk]; 00644 00645 // Storage for R at quadrature points. 00646 PISMVector2 res[FEQuadrature::Nq]; 00647 00648 // An Nq by Nk array of test function values. 00649 const FEFunctionGerm (*test)[FEQuadrature::Nk] = quadrature.testFunctionValues(); 00650 00651 // Iterate over the elements. 00652 PetscInt xs = element_index.xs, xm = element_index.xm, 00653 ys = element_index.ys, ym = element_index.ym; 00654 for (i=xs; i<xs+xm; i++) { 00655 for (j=ys; j<ys+ym; j++) { 00656 // Storage for element-local data 00657 PISMVector2 y[FEQuadrature::Nk]; 00658 00659 // Initialize the map from global to local degrees of freedom for this element. 00660 dofmap.reset(i,j,grid); 00661 00662 00663 // These values now need to be adjusted if some nodes in the element have 00664 // Dirichlet data. 00665 if(bc_locations && vel_bc) { 00666 dofmap.extractLocalDOFs(i,j,bc_mask,local_bc_mask); 00667 for (k=0; k<4; k++) { 00668 if (PismIntMask(local_bc_mask[k]) == 1) { // Dirichlet node 00669 // Mark any kind of Dirichlet node as not to be touched 00670 dofmap.markRowInvalid(k); 00671 dofmap.markColInvalid(k); 00672 } 00673 } 00674 } 00675 00676 // Obtain the value of the solution at the adjacent nodes to the element. 00677 quadrature.computeTrialFunctionValues(i,j,dofmap,R,res); 00678 00679 // Zero out the element-local residual in prep for updating it. 00680 for(k=0;k<FEQuadrature::Nk;k++){ 00681 y[k].u = 0; y[k].v = 0; 00682 } 00683 00684 for (q=0; q<FEQuadrature::Nq; q++) { // loop over quadrature points on this element. 00685 // Coefficients and weights for this quadrature point. 00686 const PetscReal jw = JxW[q]/area; 00687 for(k=0; k<FEQuadrature::Nk;k++) { // loop over the test functions. 00688 const FEFunctionGerm &testqk = test[q][k]; 00689 y[k].u += jw*testqk.val*res[q].u; 00690 y[k].v += jw*testqk.val*res[q].v; 00691 } 00692 } // q 00693 00694 dofmap.addLocalResidualBlock(y,RHS); 00695 } // j-loop 00696 } // i-loop 00697 00698 // Until now we have not touched rows in the residual corresponding to Dirichlet data. 00699 // We fix this now. 00700 if (bc_locations && vel_bc) { 00701 // Enforce Dirichlet conditions strongly 00702 for (i=grid.xs; i<grid.xs+grid.xm; i++) { 00703 for (j=grid.ys; j<grid.ys+grid.ym; j++) { 00704 if (bc_locations->as_int(i,j) == 1) { 00705 // Enforce explicit homogeneous dirichlet data. 00706 RHS[i][j].u = 0; 00707 RHS[i][j].v = 0; 00708 } 00709 } 00710 } 00711 ierr = bc_locations->end_access();CHKERRQ(ierr); 00712 } 00713 00714 return 0; 00715 } 00716 00717 00718 PetscErrorCode SSAFEM_Forward::assemble_TStarB_rhs( PISMVector2 **Z, 00719 PISMVector2 **U, 00720 PetscScalar **RHS) 00721 { 00722 PetscInt i,j,k,q; 00723 00724 // Zero out the portion of the function we are responsible for computing. 00725 for (i=grid.xs; i<grid.xs+grid.xm; i++) { 00726 for (j=grid.ys; j<grid.ys+grid.ym; j++) { 00727 RHS[i][j] = 0; 00728 } 00729 } 00730 00731 // Jacobian times weights for quadrature. 00732 PetscScalar JxW[FEQuadrature::Nq]; 00733 quadrature.getWeightedJacobian(JxW); 00734 00735 // Storage for z, u at quadrature points. 00736 PISMVector2 z[FEQuadrature::Nq]; 00737 PISMVector2 u[FEQuadrature::Nq]; 00738 00739 // An Nq by Nk array of test function values. 00740 const FEFunctionGerm (*test)[FEQuadrature::Nk] = quadrature.testFunctionValues(); 00741 00742 Mask M; 00743 00744 // Iterate over the elements. 00745 PetscInt xs = element_index.xs, xm = element_index.xm, 00746 ys = element_index.ys, ym = element_index.ym; 00747 for (i=xs; i<xs+xm; i++) { 00748 for (j=ys; j<ys+ym; j++) { 00749 // Storage for element-local data 00750 PISMVector2 x[FEQuadrature::Nk]; 00751 PetscScalar y[FEQuadrature::Nk]; 00752 00753 // Index into coefficient storage in feStore 00754 const PetscInt ij = element_index.flatten(i,j); 00755 00756 // Initialize the map from global to local degrees of freedom for this element. 00757 dofmap.reset(i,j,grid); 00758 00759 // Obtain the values of Z and VEL at the element quad points 00760 dofmap.extractLocalDOFs(i,j,Z,x); 00761 quadrature.computeTrialFunctionValues(x,z); 00762 dofmap.extractLocalDOFs(i,j,U,x); 00763 quadrature.computeTrialFunctionValues(x,u); 00764 00765 // Zero out the element-local residual in prep for updating it. 00766 for(k=0;k<FEQuadrature::Nk;k++){ 00767 y[k] = 0; 00768 } 00769 00770 for (q=0; q<FEQuadrature::Nq; q++) { // loop over quadrature points on this element. 00771 // Coefficients and weights for this quadrature point. 00772 const FEStoreNode *feS = &feStore[ij*FEQuadrature::Nq+q]; 00773 const PetscReal jw = JxW[q]; 00774 00775 // Determine "beta" at the quadrature point 00776 PetscReal notquitebeta = 0; 00777 if( M.grounded_ice(feS->mask) ) { 00778 notquitebeta = basal.drag(1.,u[q].u,u[q].v); 00779 } 00780 // dbeta_dtauc *= exp(dtauc[q]) 00781 00782 for(k=0; k<FEQuadrature::Nk;k++) { // loop over the test functions. 00783 const FEFunctionGerm &testqk = test[q][k]; 00784 y[k] -= jw*notquitebeta*testqk.val*(u[q].u*z[q].u+u[q].v*z[q].v); 00785 } 00786 } // q 00787 00788 dofmap.addLocalResidualBlock(y,RHS); 00789 } // j-loop 00790 } // i-loop 00791 return 0; 00792 00793 } 00794
1.7.3