Real Q2PBorehole::computeQpResidual() { const Real character = _character.value(_t, _q_point[_qp]); if (character == 0.0) return 0.0; const Real bh_pressure = _p_bot + _unit_weight * (_q_point[_qp] - _bottom_point); // really want to use _q_point instaed of _current_point, i think?! // Get the ID we initially assigned to this point const unsigned current_dirac_ptid = currentPointCachedID(); // If getting the ID failed, fall back to the old bodge! // if (current_dirac_ptid == libMesh::invalid_uint) // current_dirac_ptid = (_zs.size() > 2) ? 1 : 0; Real outflow(0.0); // this is the flow rate from porespace out of the system Real wc(0.0); if (current_dirac_ptid > 0) // contribution from half-segment "behind" this point (must have >1 point for // current_dirac_ptid>0) { wc = wellConstant(_permeability[0], _rot_matrix[current_dirac_ptid - 1], _half_seg_len[current_dirac_ptid - 1], _current_elem, _rs[current_dirac_ptid]); if ((character < 0.0 && _pp[_i] < bh_pressure) || (character > 0.0 && _pp[_i] > bh_pressure)) // injection, so outflow<0 || // production, so outflow>0 outflow += _test[_i][_qp] * std::abs(character) * wc * _mobility[_i] * (_pp[_i] - bh_pressure); } if (current_dirac_ptid + 1 < _zs.size() || _zs.size() == 1) // contribution from half-segment "ahead of" this point, or we only have one point { wc = wellConstant(_permeability[0], _rot_matrix[current_dirac_ptid], _half_seg_len[current_dirac_ptid], _current_elem, _rs[current_dirac_ptid]); if ((character < 0.0 && _pp[_i] < bh_pressure) || (character > 0.0 && _pp[_i] > bh_pressure)) // injection, so outflow<0 || // production, so outflow>0 outflow += _test[_i][_qp] * std::abs(character) * wc * _mobility[_i] * (_pp[_i] - bh_pressure); } _total_outflow_mass.add( outflow * _dt); // this is not thread safe, but DiracKernel's aren't currently threaded return outflow; }
//Iteration function //Uses two loops to calculate solution for the given parameters void BeamModel::iteration(const Parameters parameters, Backfill backfill, Creep creep) { extern File file; max_iterations=50; not_converged = 1; iterations = 0; no_crack_opening = 0; error = 0; //Checked against 2 as checkboxes are assigned 2 when selected rather than 1 if ((parameters.outflow_model_on==2) & (parameters.verbose==2)) { dialog *e = new dialog; e->warning("Starting outflowLength refinement with outflow length = ", outflow_length); e->exec(); } do { // Refine given outflow length using the discharge analysis: lambda_last = outflow_length; zetabackfilledlast = zetabackfilled; // Dimensionless foundation stiffness stiffness(); // Dimensionless crack speed crackSpeed(parameters, backfill); file.collect(this, 0); // Determine by FD method the opening profile v*(zeta) for a given outflow length control.lambda and the properties of it which are needed for analysis. // Make first guess for closure length -- two nodes less than input value -- and construct FD solution: node_at_closure -= 2; double wstarmax = 0.0; FDprofile fdSolution(alpha, m, zetabackfilled, pressurefactor, residualpressure, parameters.elements_in_l, node_at_closure); short nodeAtClosure_previous = node_at_closure; // Store position of last node in this FD array double errorLast = fdSolution.closureMoment(); // ...and resulting d2v/dz2 at closure point, divided by that at crack tip if (parameters.verbose==2) { dialog *e = new dialog; e->warning("Starting closure length refinement with closure node = ",nodeAtClosure_previous, "and closure moment = ", errorLast); e->exec(); } // Make second guess for closure length (two nodes MORE than input value): node_at_closure += 4; if (parameters.verbose==2) { dialog *e = new dialog; e->warning("Second-guess closure node = ", node_at_closure); e->exec(); } // Prepare to refine closure length by iteration double dontNeedThis; error = 0; short maximumNonContact = 0; //Need to declare again here! Without this, program exits first loop immediately, hence provides incorrect solutions short notConverged = 1; do { // ...until bending moment at closure point is negligible compared to that at crack tip: fdSolution = FDprofile(alpha, m, zetabackfilled, pressurefactor, residualpressure, parameters.elements_in_l, node_at_closure); error = fdSolution.closureMoment(); short noSurfaceContact = 1; // FIXME: necessary? short minPoint = fdSolution.nodeAtMinimum(); // this is set to -1 if NO minimum is found within domain if (parameters.verbose==2) { dialog *e = new dialog; e->warning("At closure length iteration ",iterations," closure moment = ", error, " min at point ",minPoint); e->exec(); } if (minPoint > 0) { if (parameters.verbose==2) { dialog *e = new dialog; e->warning("BUT there's a minimum (crack surface overlap) to left of closure point ", minPoint); e->exec(); } // So back up to find maximum closure length with NO overlap: double tempError; node_at_closure = minPoint - 2; if (node_at_closure < (parameters.elements_in_l + 1)) node_at_closure = parameters.elements_in_l + 1; // Is this really necessary? Closure might really occur inside decompression length! short newMin; do { fdSolution = FDprofile(alpha, m, zetabackfilled, pressurefactor, residualpressure, parameters.elements_in_l, node_at_closure); tempError = fdSolution.closureMoment(); newMin = fdSolution.nodeAtMinimum(); if (parameters.verbose==2) { dialog *e = new dialog; e->warning("nodeAtClosure = ",node_at_closure, " error = ", tempError, " min point = ", newMin); e->exec(); } node_at_closure++; } while (newMin < 0); node_at_closure = node_at_closure - 1; if (parameters.verbose==2) { dialog *e = new dialog; e->warning("Least worst non-contacting solution nodeAtClosure = ", node_at_closure); e->exec(); } maximumNonContact = true; fdSolution = FDprofile(alpha, m, -1.0, pressurefactor, residualpressure, parameters.elements_in_l, node_at_closure); error = fdSolution.closureMoment(); integral_wstar2 = fdSolution.integral_wStar2(); fdSolution.findBackfillEjectPoint(zetabackfilleject, dontNeedThis); } else { node_at_closure++; if (parameters.verbose==2) { dialog *e = new dialog; e->warning("node interpolated = ", node_at_closure); e->exec(); } } if (maximumNonContact) // not necessarily converged, but the best available notConverged = 0; else if ((fabs(error) < 0.01 and noSurfaceContact) or maximumNonContact) { // converged: notConverged = false; fdSolution.outflowPointValues(wstar2, wstar2dash, wstar2dash2, integral_wstar2); fdSolution.findBackfillEjectPoint(zetabackfilleject, dontNeedThis); wstarmax = fdSolution.wStarMax(node_at_closure); } else { if (parameters.verbose==2) { dialog *e = new dialog; e->warning("Next try for iteration will be nodeAtClosure = ", node_at_closure); e->exec(); } errorLast = error; iterations++; } file.collect(this, 0); // done that refinement iteration } while (notConverged & (iterations < max_iterations)); if (parameters.verbose==2) { dialog *e = new dialog; e->warning("At nodeAtClosure = ", node_at_closure, " converged in ", iterations," iterations with error = ", error); e->exec(); } // done FD solution if (parameters.verbose==2) { dialog *e = new dialog; e->warning("Computed profile properties", "Ejection point = ", zetabackfilleject, "Opening at outflow point = ", wstarmax, "1st-deriv at outflow = ", wstar2dash, "2nd-deriv at outflow = ", wstar2dash2, "Integral to outflow = ", integral_wstar2); e->exec(); } if (integral_wstar2 > 0.0) { if (parameters.outflow_model_on==2) { double throatArea = integral_wstar2; OutflowProcess outflow(p1bar); outflow_length = pow(factor * outflow.get_tStarOutflow() / throatArea, 0.2); } // tStarOutflow being the number of characteristic times for discharge if (parameters.verbose==2) { dialog *e = new dialog; e->warning("alpha = ", alpha[1], "m = ", m[1], "integral_wStar2 = ", integral_wstar2, "New outflowLength = ", outflow_length); e->exec(); } lambdapow4 = pow(outflow_length, 4); v0 = v00 * lambdapow4; vStarRes = creep.residual_crack_closure / v0 / Constants::kilo; if ((fabs(1.0 - lambda_last / outflow_length) < node_resolution) and (fabs(1.0 - zetabackfilledlast / zetabackfilled) < node_resolution)) not_converged = false; iterations++; } else { no_crack_opening = 1; } file.collect(this, 0); } // end outflow length refinement while (not_converged & (iterations < max_iterations) and not no_crack_opening); }
/** * Set the boundary conditions depending on the chosen model */ void boundaryvalues( int imax, int jmax, double dx, double dy, double **U, double **V, double **K, double **W, double nu, int *b, int **Flag ) { int i, j; int c, bound_now; for( c = 0; c < 4; c++ ){ bound_now = b[c]; /* treating different cases of boundaries * inflow treated separately * */ switch(bound_now){ case 1: no_slip( imax, jmax, U, V, K, W, c,dx,dy,nu); break; case 3: outflow( imax, jmax, U, V, K, W, c); break; default: free_slip( imax, jmax, U, V, K, W, c); break; } } /* Boundary conditions for the obstacle cells */ for( i = 1; i <= imax; i++ ) for( j = 1; j <= jmax; j++ ) if( IS_BOUNDARY(Flag[i][j]) ){ /* Boundary conditions for obstacles with North-Eastern fluid cell */ if( ( Flag[ i ][ j ] & B_NE ) == B_NE ){ U[ i ][ j ] = .0; V[ i ][ j ] = .0; U[ i-1 ][ j ] = -U[ i-1 ][ j+1 ]; V[ i ][ j-1 ] = -V[ i+1 ][ j-1 ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 0.5*( 6.0*10.0*nu/(beta_1*SQ(0.5*dy)) + 6.0*10.0*nu/(beta_1*SQ(0.5*dx)) ); } else /* Boundary conditions for obstacles with North-Western fluid cell */ if( ( Flag[ i ][ j ] & B_NW ) == B_NW ){ U[ i-1 ][ j ] = .0; V[ i ][ j ] = .0; U[ i ][ j ] = -U[ i ][ j+1 ]; V[ i ][ j-1 ] = -V[ i-1 ][ j-1 ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 0.5*( 6.0*10.0*nu/(beta_1*SQ(0.5*dy)) + 6.0*10.0*nu/(beta_1*SQ(0.5*dx)) ); } else /* Boundary conditions for obstacles with South-Eastern fluid cell */ if( ( Flag[ i ][ j ] & B_SE ) == B_SE ){ U[ i ][ j ] = .0; V[ i ][ j-1 ] = .0; U[ i-1 ][ j ] = -U[ i-1 ][ j-1 ]; V[ i ][ j ] = -V[ i+1 ][ j ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 0.5*( 6.0*10.0*nu/(beta_1*SQ(0.5*dy)) + 6.0*10.0*nu/(beta_1*SQ(0.5*dx)) ); } else /* Boundary conditions for obstacles with South-Western fluid cell */ if( ( Flag[ i ][ j ] & B_SW ) == B_SW ){ U[ i-1 ][ j ] = .0; V[ i ][ j-1 ] = .0; U[ i ][ j ] = -U[ i ][ j-1 ]; V[ i ][ j ] = -V[ i-1 ][ j ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 0.5*( 6.0*10.0*nu/(beta_1*SQ(0.5*dy)) + 6.0*10.0*nu/(beta_1*SQ(0.5*dx)) ); } else /* Boundary conditions for obstacles with Northern fluid cell */ if( ( Flag[ i ][ j ] & B_N ) == B_N ){ V[ i ][ j ] = .0; U[ i ][ j ] = -U[ i ][ j+1 ]; U[ i-1 ][ j ] = -U[ i-1 ][ j+1 ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 6.0*10.0*nu/(beta_1*SQ(0.5*dy)) ; } else /* Boundary conditions for obstacles with Southern fluid cell */ if(( Flag[ i ][ j ] & B_S ) == B_S ){ V[ i ][ j-1 ] = .0; U[ i ][ j ] = -U[ i ][ j-1 ]; U[ i-1 ][ j ] = -U[ i-1 ][ j-1 ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 6.0*10.0*nu/(beta_1*SQ(0.5*dy)) ; }else /* Boundary conditions for obstacles with Western fluid cell */ if( ( Flag[ i ][ j ] & B_W ) == B_W ){ U[ i-1 ][ j ] = .0; V[ i ][ j ] = -V[ i-1 ][ j ]; V[ i ][ j-1 ] = -V[ i-1 ][ j-1 ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 6.0*10.0*nu/(beta_1*SQ(0.5*dx)) ; } else /* Boundary conditions for obstacles with Eastern fluid cell */ if( ( Flag[ i ][ j ] & B_E ) == B_E ){ U[ i ][ j ] = .0; V[ i ][ j ] = -V[ i+1 ][ j ]; V[ i ][ j-1 ] = -V[ i+1 ][ j-1 ]; K[ i ][ j ] = 0.00001; W[ i ][ j ] = 6.0*10.0*nu/(beta_1*SQ(0.5*dx)) ; } } }