PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/base/stressbalance/SSAFEM_Forward.cc

Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines