[cig-commits] r18981 - short/3D/PyLith/branches/v1.6-revisedfault/libsrc/pylith/faults

brad at geodynamics.org brad at geodynamics.org
Wed Sep 28 11:58:51 PDT 2011


Author: brad
Date: 2011-09-28 11:58:51 -0700 (Wed, 28 Sep 2011)
New Revision: 18981

Modified:
   short/3D/PyLith/branches/v1.6-revisedfault/libsrc/pylith/faults/FaultCohesiveLagrange.cc
Log:
Improved custon fault preconditioner by summing basis products over quadrature points.

Modified: short/3D/PyLith/branches/v1.6-revisedfault/libsrc/pylith/faults/FaultCohesiveLagrange.cc
===================================================================
--- short/3D/PyLith/branches/v1.6-revisedfault/libsrc/pylith/faults/FaultCohesiveLagrange.cc	2011-09-28 13:00:30 UTC (rev 18980)
+++ short/3D/PyLith/branches/v1.6-revisedfault/libsrc/pylith/faults/FaultCohesiveLagrange.cc	2011-09-28 18:58:51 UTC (rev 18981)
@@ -919,28 +919,26 @@
 
 #else // FULL PRECONDITIONER
 
-  // Compute -( [C] [A]^(-1) [C]^T ) for cell.
+  // Compute Pi = -( [L] [K]^(-1) [L]^T ) for cell using the diagonal of K
+  // to approximate [K]^(-1).
   //
-  // numBasis = number of corners in fault cell
-  // spaceDim = spatial dimension
-  //
-  // For the cell, [A] is 2*numBasis*spaceDim x 2*numBasis*spaceDim,
-  // [C] is numBasis*spaceDim x 2*numBasis*spaceDim
-  //
-  // Decompose [A] into [An] and [Ap], where [An] contains the terms
-  // for vertices on the negative side of the fault and [Ap] contains
+  // Decompose [K] into [Kn] and [Kp], where [Kn] contains the terms
+  // for vertices on the negative side of the fault and [Kp] contains
   // the terms for vertices on the positive side of the fault.
   //
-  // [An] and [Ap] are numBasis*spaceDim x numBasis*spaceDim
+  // [Kn] and [Kp] are numBasis*spaceDim x numBasis*spaceDim
   // 
-  // Let [CAC] = [C] [A]^(-1) [C]^T.
+  // Pi = L_{ik} (1.0/Kn_{kk} + 1.0/Kp{kk}) L_{jk}
   //
-  // CAiC_kl = Cij Ai_jk C_lk
+  // L_{ij} = sum_{qi} N_i N_j w_qi |J|_{qi}
   //
-  // Cij: iLagrange, iDim, jBasis, jDim
-  // Ai_jk: jBasis, jDim, kBasis, kDim
-  // C_lk: lLagrange, lDim, kBasis, kDim
-  
+  // :KLUDGE: There is a difference between Pi using the full system
+  // matrices and the sum of Pi over the cells. The square of the sums
+  // of the basis functions (system matrices) is greater than the sums
+  // of the squares of the basis functions (cell matrices). Empirical
+  // experiments suggests a value of 4.0 improves the rate of
+  // convergence.
+  const double assemblyFactor = 5.0;
 
   const int setupEvent = _logger->eventId("FaPr setup");
   const int computeEvent = _logger->eventId("FaPr compute");
@@ -967,6 +965,7 @@
   double_array preconditionerCell(matrixSizeF);
   double_array jacobianCellP(matrixSizeF);
   double_array jacobianCellN(matrixSizeF);
+  double_array basisProducts(numBasis*numBasis);
 
   // Get sections
   const ALE::Obj<RealSection>& solutionSection = fields->solution().section();
@@ -1113,59 +1112,57 @@
     const double_array& basis = _quadrature->basis();
     const double_array& jacobianDet = _quadrature->jacobianDet();
 
-    preconditionerCell = 0.0;
-
-    const int rowSize = numBasis*spaceDim;
-
+    // Compute product of basis functions.
+    // Want values summed over quadrature points
+    basisProducts = 0.0;
     for (int iQuad=0; iQuad < numQuadPts; ++iQuad) {
       const double wt = quadWts[iQuad] * jacobianDet[iQuad];
+
       for (int iBasis=0, iQ=iQuad*numBasis; iBasis < numBasis; ++iBasis) {
         const double valI = wt*basis[iQ+iBasis];
 
-	// First index Lagrange vertices
-	const int iB = iBasis*spaceDim;
-
         for (int jBasis=0; jBasis < numBasis; ++jBasis) {
 
-	  // First index for Lagrange vertices
-	  const int jB = jBasis*spaceDim;
+	  basisProducts[iBasis*numBasis+jBasis] += valI*basis[iQ+jBasis];
+	} // for
+      } // for
+    } // for
 
-	  for (int kBasis=0; kBasis < numBasis; ++kBasis) {
-	    const int kB = kBasis*spaceDim;
+    preconditionerCell = 0.0;
 
-	    const double valIK = valI * basis[iQ+kBasis];
-	    const double valJK = basis[iQ+jBasis]*basis[iQ+kBasis];
+    for (int iBasis=0; iBasis < numBasis; ++iBasis) {
+      // First index Lagrange vertices
+      const int iB = iBasis*spaceDim;
 
-	    for (int iDim=0; iDim < spaceDim; ++iDim) {
-	      // Add entries to Jacobian at (i,j) where
-	      // iL = DOF at constraint node, jL = DOF at constraint node
-	      const int iL = (iB + iDim) * rowSize; // row
-	      const int jL = (jB + iDim); // col
+      for (int jBasis=0; jBasis < numBasis; ++jBasis) {
+	  
+	// First index for Lagrange vertices
+	const int jB = jBasis*spaceDim;
 
-	      const int k = (kB+iDim)*rowSize+(kB+iDim);
-	      const double jacobianNPInv = 
-		1.0/jacobianCellN[k] + 1.0/jacobianCellP[k];
+	for (int kBasis=0; kBasis < numBasis; ++kBasis) {
+	  const int kB = kBasis*spaceDim;
 
-	      std::cout << "iB: " << iB
-			<< ", jB: " << jB
-			<< ", kB: " << kB
-			<< ", iDim: " << iDim
-			<< ", iL: " << iL
-			<< ", jL: " << jL
-			<< ", k: " << k
-			<< ", valIK: " << valIK
-			<< ", valJK: " << valJK
-			<< ", jacobianInv: " << jacobianNPInv
-			<< std::endl;
+	  const double valIK = basisProducts[iBasis*numBasis+kBasis];
+	  const double valJK = basisProducts[jBasis*numBasis+kBasis];
 
-	      preconditionerCell[iL + jL] -= valIK*valJK*jacobianNPInv;
-	    } // for
+	  for (int iDim=0; iDim < spaceDim; ++iDim) {
+	    // Add entries to Jacobian at (i,j) where
+	    // iL = DOF at constraint node, jL = DOF at constraint node
+	    const int iL = (iB + iDim) * nrowsF; // row
+	    const int jL = (jB + iDim); // col
+
+	    const int k = (kB+iDim)*nrowsF+(kB+iDim);
+	    const double jacobianNPInv = 
+	      1.0/jacobianCellN[k] + 1.0/jacobianCellP[k];
+
+	    preconditionerCell[iL + jL] -= valIK*valJK*jacobianNPInv;
 	  } // for
         } // for
       } // for
     } // for
+    preconditionerCell *= assemblyFactor;
 
-#if 1
+#if 0
     std::cout << "1/P_cell " << *c_iter << std::endl;
     for(int i = 0; i < nrowsF; ++i) {
       for(int j = 0; j < nrowsF; ++j) {



More information about the CIG-COMMITS mailing list