atmBoundaryLayer::atmBoundaryLayer(const vectorField& p, const dictionary& dict) : flowDir_(dict.lookup("flowDir")), zDir_(dict.lookup("zDir")), kappa_(dict.lookupOrDefault<scalar>("kappa", 0.41)), Cmu_(dict.lookupOrDefault<scalar>("Cmu", 0.09)), Uref_(readScalar(dict.lookup("Uref"))), Zref_(readScalar(dict.lookup("Zref"))), z0_("z0", dict, p.size()), zGround_("zGround", dict, p.size()), Ustar_(p.size()) { if (mag(flowDir_) < SMALL || mag(zDir_) < SMALL) { FatalErrorInFunction << "magnitude of n or z must be greater than zero" << abort(FatalError); } // Ensure direction vectors are normalized flowDir_ /= mag(flowDir_); zDir_ /= mag(zDir_); Ustar_ = kappa_*Uref_/(log((Zref_ + z0_)/z0_)); }
Foam::tmp<Foam::vectorField> Foam::sphericalCS::localToGlobal ( const vectorField& local, bool translate ) const { const scalarField r(local.component(vector::X)); const scalarField theta ( local.component(vector::Y) *(inDegrees_ ? constant::mathematical::pi/180.0 : 1.0) ); const scalarField phi ( local.component(vector::Z) *(inDegrees_ ? constant::mathematical::pi/180.0 : 1.0) ); vectorField lc(local.size()); lc.replace(vector::X, r*cos(theta)*sin(phi)); lc.replace(vector::Y, r*sin(theta)*sin(phi)); lc.replace(vector::Z, r*cos(phi)); return coordinateSystem::localToGlobal(lc, translate); }
void Foam::dx<Type>::writeDXData ( const pointField& points, const vectorField& values, Ostream& os ) const { // Write data os << "object 3 class array type float rank 1 shape 3 items " << values.size() << " data follows" << nl; forAll(values, elemI) { os << float(values[elemI].x()) << ' ' << float(values[elemI].y()) << ' ' << float(values[elemI].z()) << nl; } if (values.size() == points.size()) { os << nl << "attribute \"dep\" string \"positions\"" << nl << nl; } else { os << nl << "attribute \"dep\" string \"connections\"" << nl << nl; } }
// Calculate a simple check on a vector field void record(vectorField& V) { // Calculate the magnitude of a field const int x=0, y=1, z=2; double magx = sum(pow2(V[x])) / V.numElements(); double magy = sum(pow2(V[y])) / V.numElements(); double magz = sum(pow2(V[z])) / V.numElements(); cout << "norm = [" << magx << " " << magy << " " << magz << " ]" << endl; }
// Update vectorField for all the new cells. Takes over value of // original cell. void Foam::multiDirRefinement::update ( const Map<label>& splitMap, vectorField& field ) { field.setSize(field.size() + splitMap.size()); forAllConstIter(Map<label>, splitMap, iter) { field[iter()] = field[iter.key()]; } }
Foam::tmp<Foam::Field<Type> > Foam::basicSymmetryFvPatchField<Type>::snGradTransformDiag() const { const vectorField nHat(this->patch().nf()); vectorField diag(nHat.size()); diag.replace(vector::X, mag(nHat.component(vector::X))); diag.replace(vector::Y, mag(nHat.component(vector::Y))); diag.replace(vector::Z, mag(nHat.component(vector::Z))); return transformFieldMask<Type>(pow<vector, pTraits<Type>::rank>(diag)); }
Foam::tmp<Foam::Field<Type> > Foam::partialSlipFvPatchField<Type>::snGradTransformDiag() const { const vectorField nHat(this->patch().nf()); vectorField diag(nHat.size()); diag.replace(vector::X, mag(nHat.component(vector::X))); diag.replace(vector::Y, mag(nHat.component(vector::Y))); diag.replace(vector::Z, mag(nHat.component(vector::Z))); return valueFraction_*pTraits<Type>::one + (1.0 - valueFraction_) *transformFieldMask<Type>(pow<vector, pTraits<Type>::rank>(diag)); }
void snapshot(vectorField& P) { static int snapshotNum = 0; ++snapshotNum; char filename[128]; sprintf(filename, "velocity%03d.m", snapshotNum); ofstream ofs(filename); int N = P.length(firstDim); int k = N/2; ofs << "P" << snapshotNum << " = [ "; for (int i=0; i < N; ++i) { for (int j=0; j < N; ++j) { float value = norm(P(k,j,N-i-1)); ofs << value << " "; } if (i < N-1) ofs << ";" << endl; } ofs << "];" << endl; }
// Update vectorField for all the new cells. Takes over value of // original cell. void Foam::multiDirRefinement::update ( const Map<label>& splitMap, vectorField& field ) { field.setSize(field.size() + splitMap.size()); for ( Map<label>::const_iterator iter = splitMap.begin(); iter != splitMap.end(); ++iter ) { field[iter()] = field[iter.key()]; } }
Foam::tmp<Foam::vectorField> Foam::transform ( const quaternion& q, const vectorField& tf ) { tmp<vectorField > tranf(new vectorField(tf.size())); transform(tranf.ref(), q, tf); return tranf; }
Foam::tmp<Foam::vectorField> Foam::waveSuperposition::velocity ( const scalar t, const vectorField& xyz ) const { vectorField result(xyz.size(), vector::zero); forAll(waveModels_, wavei) { const vector2D d(cos(waveAngles_[wavei]), sin(waveAngles_[wavei])); const vector2DField xz ( zip ( d & zip(xyz.component(0), xyz.component(1)), tmp<scalarField>(xyz.component(2)) ) ); const vector2DField uw ( waveModels_[wavei].velocity(t, xz) ); result += zip ( d.x()*uw.component(0), d.y()*uw.component(0), uw.component(1) ); } tmp<scalarField> s = scale(zip(xyz.component(0), xyz.component(1))); return s*result; }
/* * Adjust the time step according to the CFL stability criterion */ void adjustTimeStep(vectorField& V) { // Find maximum velocity magnitude double maxV = 0.0; // NEEDS_WORK: Blitz should provide a norm(vectorField) function. // This is ugly. for (int i=V.lbound(0); i <= V.ubound(0); ++i) for (int j=V.lbound(1); j <= V.ubound(1); ++j) for (int k=V.lbound(2); k <= V.ubound(2); ++k) { double normV = norm(V(i,j,k)); if (normV > maxV) maxV = normV; } cout << "Maximum velocity is " << maxV << " m/s" << endl; maxV += 1e-10; // Avoid divide-by-zero // Steve K: need to have spatialStep^2 / diffusion constant // diffusion constant = eta * recip_rho delta_t = 0.3 * spatialStep / maxV; const double maxTimeStep = 0.01; if (delta_t > maxTimeStep) delta_t = maxTimeStep; cout << "Set time step to " << delta_t << " s" << endl; }
Foam::tmp<Foam::symmTensorField> Foam::STARCDCoordinateRotation:: transformVector ( const vectorField& st ) const { tmp<symmTensorField> tfld(new symmTensorField(st.size())); symmTensorField& fld = tfld(); forAll(fld, i) { fld[i] = transformPrincipal(R_, st[i]); }
Foam::tmp<Foam::vectorField> Foam::toroidalCS::localToGlobal ( const vectorField& local, bool translate ) const { const scalarField r = local.component(vector::X); const scalarField theta = local.component(vector::Y)*mathematicalConstant::pi/180.0; const scalarField phi = local.component(vector::Z)*mathematicalConstant::pi/180.0; const scalarField rprime = radius_ + r*sin(phi); vectorField lc(local.size()); lc.replace(vector::X, rprime*cos(theta)); lc.replace(vector::Y, rprime*sin(theta)); lc.replace(vector::Z, r*cos(phi)); return coordinateSystem::localToGlobal(lc, translate); }
Foam::tmp<Foam::vectorField> Foam::sphericalCS::globalToLocal ( const vectorField& global, bool translate ) const { const vectorField lc = coordinateSystem::globalToLocal(global, translate); const scalarField r = mag(lc); tmp<vectorField> tresult(new vectorField(lc.size())); vectorField& result = tresult(); result.replace ( vector::X, r ); result.replace ( vector::Y, atan2 ( lc.component(vector::Y), lc.component(vector::X) )*180.0/mathematicalConstant::pi ); result.replace ( vector::Z, acos(lc.component(vector::Z)/(r + SMALL))*180.0/mathematicalConstant::pi ); return tresult; }
void Foam::rotateSearchableSurface::getNormal ( const List<pointIndexHit>& info, vectorField& normal ) const { vectorField iNormal; transformationSearchableSurface::getNormal ( info, iNormal ); normal.setSize(iNormal.size()); forAll(normal,i) { normal[i]=transform(iNormal[i]); }
void Foam::scaleSearchableSurface::getNormal ( const List<pointIndexHit>& info, vectorField& normal ) const { vectorField iNormal; transformationSearchableSurface::getNormal ( info, iNormal ); normal.setSize(iNormal.size()); forAll(normal,i) { normal[i]=inverseTransform(iNormal[i]); scalar len=mag(normal[i]); if(len>SMALL) { normal[i]/=len; } }
Foam::tmp<Foam::vectorField> Foam::parabolicCylindricalCS::localToGlobal ( const vectorField& local, bool translate ) const { if (min(local.component(vector::Y)) < 0.0) { FatalErrorIn ( "parabolicCylindricalCS::localToGlobal" "(const vectorField&, bool) const" ) << "parabolic cylindrical coordinates v < 0" << abort(FatalError); } vectorField lc(local.size()); lc.replace ( vector::X, 0.5* ( sqr(local.component(vector::X)) - sqr(local.component(vector::Y)) ) ); lc.replace ( vector::Y, local.component(vector::X) * local.component(vector::Y) ); lc.replace ( vector::Z, local.component(vector::Z) ); return coordinateSystem::localToGlobal(lc, translate); }
void Foam::meshRefinement::findNearest ( const labelList& meshFaces, List<pointIndexHit>& nearestInfo, labelList& nearestSurface, labelList& nearestRegion, vectorField& nearestNormal ) const { pointField fc(meshFaces.size()); forAll(meshFaces, i) { fc[i] = mesh_.faceCentres()[meshFaces[i]]; } const labelList allSurfaces(identity(surfaces_.surfaces().size())); surfaces_.findNearest ( allSurfaces, fc, scalarField(fc.size(), sqr(GREAT)), // sqr of attraction nearestSurface, nearestInfo ); // Do normal testing per surface. nearestNormal.setSize(nearestInfo.size()); nearestRegion.setSize(nearestInfo.size()); forAll(allSurfaces, surfI) { DynamicList<pointIndexHit> localHits; forAll(nearestSurface, i) { if (nearestSurface[i] == surfI) { localHits.append(nearestInfo[i]); } } label geomI = surfaces_.surfaces()[surfI]; pointField localNormals; surfaces_.geometry()[geomI].getNormal(localHits, localNormals); labelList localRegion; surfaces_.geometry()[geomI].getRegion(localHits, localRegion); label localI = 0; forAll(nearestSurface, i) { if (nearestSurface[i] == surfI) { nearestNormal[i] = localNormals[localI]; nearestRegion[i] = localRegion[localI]; localI++; } } }
void Foam::dirichletNeumannFriction::correct ( const vectorField& slavePressure, const PrimitivePatch<face, List, pointField>& masterFaceZonePatch, const PrimitivePatch<face, List, pointField>& slaveFaceZonePatch, const intersection::algorithm alg, const intersection::direction dir, const word interpolationMethod, const word fieldName, const Switch orthotropic, const word nonLinear, const vectorField& slaveFaceNormals ) { const fvMesh& mesh = mesh_; const label slavePatchIndex = slavePatchID(); const label masterPatchIndex = masterPatchID(); contactIterNum_++; // we have local masterDU and we want to interpolate it to the slave // to get local masterDUInterpToSlave (i.e. masterDU interpolated // to the slave) // so the method is: // create global masterDU field // interpolate global masterDU from master global face zone to // slave global zone // then find local masterDUInterpToSlave from the global interpolated field vectorField masterDUInterpToSlave (mesh.boundaryMesh()[slavePatchIndex].size(), vector::zero); // global master DU vectorField globalMasterDU(masterFaceZonePatch.size(), vector::zero); // lookup current displacement field const volVectorField& dispField = mesh.objectRegistry::lookupObject<volVectorField>(fieldName); // local master and slave DU increment vectorField masterDU = dispField.boundaryField()[masterPatchIndex]; vectorField slaveDU = dispField.boundaryField()[slavePatchIndex]; if (fieldName == "U") { // lookup old U const volVectorField& dispOldField = mesh.objectRegistry::lookupObject<volVectorField>(fieldName+"_0"); // subtract old U masterDU -= dispOldField.boundaryField()[masterPatchIndex]; slaveDU -= dispOldField.boundaryField()[slavePatchIndex]; } else if (fieldName != "DU") { FatalError << "dirichletNeumannFriction::correct()\n" " The displacement field must be called U or DU" << exit(FatalError); } // put local masterDU into globalMasterDU const label masterPatchStart = mesh.boundaryMesh()[masterPatchIndex].start(); forAll(masterDU, i) { globalMasterDU[ mesh.faceZones()[masterFaceZoneID() ].whichFace(masterPatchStart + i)] = masterDU[i]; } //- exchange parallel data // sum because each face is only on one proc reduce(globalMasterDU, sumOp<vectorField>()); // globalMasterDU is interpolated to the slave vectorField globalMasterDUInterpToSlave (slaveFaceZonePatch.size(), vector::zero); // interpolate DU from master to slave using inverse distance or ggi if (interpolationMethod == "patchToPatch") { PatchToPatchInterpolation< PrimitivePatch< face, List, pointField >, PrimitivePatch<face, List, pointField> > masterToSlavePatchToPatchInterpolator ( masterFaceZonePatch, // from zone slaveFaceZonePatch, // to zone alg, dir ); globalMasterDUInterpToSlave = masterToSlavePatchToPatchInterpolator.faceInterpolate<vector> ( globalMasterDU ); } else if (interpolationMethod == "ggi") { GGIInterpolation< PrimitivePatch< face, List, pointField >, PrimitivePatch< face, List, pointField > > masterToSlaveGgiInterpolator ( masterFaceZonePatch, // master zone slaveFaceZonePatch, // slave zone tensorField(0), tensorField(0), vectorField(0), 0.0, 0.0, true, ggiInterpolation::AABB ); globalMasterDUInterpToSlave = masterToSlaveGgiInterpolator.masterToSlave ( globalMasterDU ); } else { FatalError << "dirichletNeumannFriction::correct()\n" "interpolationMethod " << interpolationMethod << " not known\n" "interpolationMethod must be patchToPatch or ggi" << exit(FatalError); } // now put global back into local const label slavePatchStart = mesh.boundaryMesh()[slavePatchIndex].start(); forAll(masterDUInterpToSlave, i) { masterDUInterpToSlave[i] = globalMasterDUInterpToSlave [ mesh.faceZones()[slaveFaceZoneID()].whichFace(slavePatchStart + i) ]; } // Now masterDUInterpToSlave should have masterDU interpolated to the slave // Calculate current slave shear traction from the normal gradient field const fvPatch& slavePatch = mesh.boundary()[slavePatchIndex]; const fvPatchField<tensor>& gradField = slavePatch.lookupPatchField<volTensorField, tensor> ("grad(" + fieldName + ")"); bool incremental(fieldName == "DU"); vectorField slaveShearTraction ( (I - sqr(slaveFaceNormals)) & tractionBoundaryGradient::traction ( gradField, fieldName, "U", slavePatch, orthotropic, nonLinearGeometry::nonLinearNames_[nonLinear], incremental ) ); // algorithm // if the face pressure is negative/zero then the friction is zero // so set valueFrac to zero and traction to zero // if the face pressure is positive and the shear traction is less // than fricCoeff*pressure then this is a sticking face so // set the valueFrac to (I-n^2) and set the disp to remove any // slip // if the face pressure is positive and the shear traction is greater // than fricCoeff*pressure then this is a slipping face so // set the valueFrac to zero and set the shear traction to // fricCoeff*pressure in the opposite direction to slip // if the shear traction on a slipping face is acting in the same // direction as the slip then this face should not be slipping // so we make it a sticking face // const volVectorField& prevSlaveDispField = // mesh.objectRegistry::lookupObject<volVectorField>(fieldName); const vectorField prevSlaveShearDisp = (I - sqr(slaveFaceNormals)) & dispField.boundaryField()[slavePatchIndex]; label numSlipFaces = 0; label numStickFaces = 0; scalarField& stickSlip = stickSlipFaces(); const scalarField magSlavePressure = mag(slavePressure); scalar maxMagSlavePressure = 0.0; if (slavePressure.size() > 0) maxMagSlavePressure = max(magSlavePressure); reduce(maxMagSlavePressure, maxOp<scalar>()); // slip is the difference between the master tangential DU // and slave tangential DU vectorField slip = (I - sqr(slaveFaceNormals)) & ( slaveDU - masterDUInterpToSlave); // under-relax the slip slip = relaxationFactor_*slip + (1.0 - relaxationFactor_)*oldSlip_; oldSlip_ = slip; vectorField slipDir = slip/(mag(slip)+SMALL); const scalar pressureTol = 1e-3*maxMagSlavePressure; // first we calculate slaveDisp assuming every face is sticking // and we calculate slaveTraction assuming every face is sliding // then we use the slaveValueFrac to set the face to slip/stick // depending on the slip function slaveDisp_ = -slip + prevSlaveShearDisp; //slaveDisp_ = -slip + slaveDisp_; // see if convergence is better scalarField slipTrac = frictionLawPtr_->slipTraction(magSlavePressure); // new forAll(slaveDisp_, facei) { if (mag(slavePressure[facei]) < pressureTol) { // not in contact slaveDisp_[facei] = prevSlaveShearDisp[facei]; slaveTraction_[facei] = vector::zero; slaveValueFrac_[facei] = symmTensor::zero; stickSlip[facei] = -1; } else if ( (mag(slaveShearTraction[facei]) > 0.999*slipTrac[facei]) && ((slip[facei] & slaveShearTraction[facei]) < 0.0) // opposite directions ) { // slip slaveDisp_[facei] = -slip[facei] + prevSlaveShearDisp[facei]; // better convergence slaveTraction_[facei] = -slipDir[facei] * slipTrac[facei]; slaveValueFrac_[facei] = symmTensor::zero; numSlipFaces++; stickSlip[facei] = 0; } else { // stick slaveDisp_[facei] = -slip[facei] + prevSlaveShearDisp[facei]; slaveTraction_[facei] = -slipDir[facei] * slipTrac[facei]; //slaveTraction_[facei] = slaveShearTraction[facei]; //slaveTraction_[facei] = vector::zero; slaveValueFrac_[facei] = (I - sqr(slaveFaceNormals[facei])); numStickFaces++; stickSlip[facei] = 2; } } // slaveTraction_ = -slipDir * slipTrac; // // slipFunc is 1.0 for slip and 0.0 for stick // // scalarField slipFunc = mag(slaveShearTraction) - 0.999*slipTrac; // scalarField slipFunc = mag(slaveShearTraction) - slipTrac; // //slipFunc /= mag(slipFunc+SMALL); // bugfix add SMALL // //slipFunc = max(slipFunc, 0.0); // //const scalar slipStressTol = 1e-4*gMax(mag(slaveShearTraction)); // const scalar pressureTol = 1e-3*maxMagSlavePressure; // forAll(slipFunc, facei) // { // if (slipFunc[facei] > pressureTol) // { // slipFunc[facei] = 1.0; // } // else // { // slipFunc[facei] = 0.0; // } // } // // if the slip and trac are in the same direction then we will change // // the face from slip to stick // // { // // scalarField changeFace = slip & slaveTraction_; // // forAll(changeFace, facei) // // { // // if (changeFace[facei] > SMALL) // // { // // slipFunc[facei] = 0.0; // // } // // } // // } // // stickSlip // // -1 for faces not in contact // // 0 for slipping faces // // 1 for stick faces // stickSlip = (1.0 - slipFunc); // // const scalar pressureTol = 1e-3*maxMagSlavePressure; // forAll(slip, facei) // { // if (magSlavePressure[facei] < pressureTol) // { // stickSlip[facei] = -1; // } // } // //slaveValueFrac_ = (1.0 - slipFunc) * (I - sqr(slaveFaceNormals)); // slaveValueFrac_ = max(stickSlip, 0.0) * (I - sqr(slaveFaceNormals)); // // set valueFace to zero for faces not in contact // // and also reset traction on sticking faces and displacement // // on slipping faces // forAll(slip, facei) // { // if (magSlavePressure[facei] < pressureTol) // { // slaveDisp_[facei] = prevSlaveShearDisp[facei]; // slaveTraction_[facei] = vector::zero; // slaveValueFrac_[facei] = symmTensor::zero; // if ( mag(stickSlip[facei] + 1) > SMALL) // Info << "face " << facei << "changed to tracFree" << endl; // stickSlip[facei] = -1; // } // else if (slipFunc[facei] > SMALL) // { // slaveDisp_[facei] = prevSlaveShearDisp[facei]; // numSlipFaces++; // if ( mag(stickSlip[facei]) > SMALL) // Info << "face " << facei << "changed to slip" << endl; // stickSlip[facei] = 0; // } // else // { // //slaveTraction_[facei] = slaveShearTraction[facei]; // numStickFaces++; // if ( mag(stickSlip[facei] - 1) > SMALL) // Info << "face " << facei << "changed to stick" << endl; // stickSlip[facei] = 1; // } // } // correct oscillations if (oscillationCorr_) { //correctOscillations(slaveFaceZonePatch); // interpolate face values to points then interpolate back // this essentially smooths the field primitivePatchInterpolation localSlaveInterpolator (mesh.boundaryMesh()[slavePatchIndex]); vectorField slaveDispPoints (mesh.boundaryMesh()[slavePatchIndex].nPoints(), vector::zero); for (int i=0; i<smoothingSteps_; i++) { slaveDispPoints = localSlaveInterpolator.faceToPointInterpolate<vector>(slaveDisp_); slaveDisp_ = localSlaveInterpolator.pointToFaceInterpolate<vector> (slaveDispPoints); // make sure no normal component slaveDisp_ = (I - sqr(slaveFaceNormals)) & slaveDisp_; } } // under-relax traction slaveDisp_ = relaxationFactor_*slaveDisp_ + (1.0 - relaxationFactor_)*prevSlaveShearDisp; //oldSlaveDisp_; oldSlaveDisp_ = slaveDisp_; slaveValueFrac_ = relaxationFactor_*slaveValueFrac_ + (1.0 - relaxationFactor_)*oldSlaveValueFrac_; oldSlaveValueFrac_ = slaveValueFrac_; slaveTraction_ = relaxationFactor_*slaveTraction_ + (1.0 - relaxationFactor_)*oldSlaveTraction_; oldSlaveTraction_ = slaveTraction_; stickSlip = relaxationFactor_*stickSlip + (1.0 - relaxationFactor_)*oldStickSlip_; oldStickSlip_ = stickSlip; // get global values // in parallel, the log is poluted with warnings that // I am getting max of a list of size zero so // I will get the max of procs which have some // of the slave faces //scalar maxMagMasterTraction = gMax(mag(slaveTraction_)) scalar maxMagMasterTraction = 0.0; if (slaveTraction_.size() > 0) { maxMagMasterTraction = max(mag(slaveTraction_)); } reduce(maxMagMasterTraction, maxOp<scalar>()); reduce(numSlipFaces, sumOp<int>()); reduce(numStickFaces, sumOp<int>()); // master writes to contact info file if (Pstream::master() && (contactIterNum_ % infoFreq_ == 0)) { OFstream& contactFile = *contactFilePtr_; int width = 20; contactFile << mesh.time().value(); contactFile.width(width); contactFile << contactIterNum_; contactFile.width(width); contactFile << relaxationFactor_; contactFile.width(width); contactFile << numSlipFaces; contactFile.width(width); contactFile << numStickFaces; contactFile.width(width); contactFile << maxMagMasterTraction << endl; } }
BZ_END_STENCIL /* * Allocate arrays and set their initial state */ void setup(const int N, vectorField& V, vectorField& nextV, scalarField& P, scalarField& P_rhs, vectorField& advect, vectorField& force) { // A 1m x 1m x 1m domain spatialStep = 1.0 / (N - 1); geom = UniformCubicGeometry<3>(spatialStep); // Allocate arrays allocateArrays(shape(N,N,N), advect, V, nextV, force); // vector fields allocateArrays(shape(N,N,N), P, P_rhs); // scalar fields // Since incompressibility is assumed, pressure only shows up as // derivative terms in the equations. We choose airPressure = 0 // as an arbitrary datum. airPressure = 0; // Pa rho = 1000; // density of fluid, kg/m^3 recip_rho = 1.0 / rho; // inverse of density eta = 1.0e-6; // kinematic viscosity of fluid, m^2/s gravity = 9.81; // m/s^2 delta_t = 0.001; // initial time step, in seconds volume = pow3(spatialStep); // cubic volume associated with grid point // Kludge: Set eta high, so that the flow will spread faster. // This means the cube is filled with molasses, rather than water. eta *= 1000; // Initial conditions: quiescent V = 0.0; P_rhs = 0.0; advect = 0.0; nextV = 0.0; // Initial pressure condition: gravity causes a linear increase // in pressure with depth. Note that tensor::k means the index // associated with the z axis (they are labelled i, j, k). #ifdef NO_GRAVITY gravityPressureGradient = 0.0; P = 0.0; #else gravityPressureGradient = spatialStep * gravity * rho; #ifdef BZ_HAVE_NAMESPACES P = airPressure + tensor::k * gravityPressureGradient; #else P = airPressure + k * gravityPressureGradient; #endif #endif // Set up the forcing function: gravity plus a stirring force // at the bottom double gravity_z = gravity * rho; const int x = 0, y = 1, z = 2; force[x] = 0.0; force[y] = 0.0; #ifdef NO_GRAVITY force[z] = 0.0; #else force[z] = gravity_z; #endif #ifndef NO_STIRRING // Centre of the stirring int centrex = int(2 * N / 3.0); int centrey = int(2 * N / 3.0); int centrez = int(4 * N / 5.0); const double stirRadius = 1.0 / 3.0; vector3d zaxis(0,0,1); // Loop through the 2D slice where the stirring occurs for (int i=force.lbound(firstDim); i <= force.ubound(firstDim); ++i) { for (int j=force.lbound(secondDim); j <= force.ubound(secondDim); ++j) { // Vector from the centre of the stirring to the current // coordinate vector3d r((i-centrex) * spatialStep, (j-centrey) * spatialStep, 0.0); if (norm(r) < stirRadius) { // The cross product of the z-axis and the vector3d to this // coordinate yields the direction of the force. Multiply // by gravity to get a reasonable magnitude (max force = // 5 * gravity) force(i,j,centrez) += cross(zaxis, r) * (5 * gravity_z / stirRadius); } } } #endif // NO_STIRRING }
void CalculateDragForce ( cfdemCloud& sm, const volScalarField& alpf_, const volVectorField& Uf_, const volScalarField& rho_, const bool& verbose_, vectorField& DragForce_, const labelListList& particleList_ ) { // get viscosity field #ifdef comp const volScalarField nufField = sm.turbulence().mu()/rho_; #else const volScalarField& nufField = sm.turbulence().nu(); #endif // Local variables label cellI(-1); vector drag(0,0,0); vector Ufluid(0,0,0); vector position(0,0,0); scalar voidfraction(1); vector Up(0,0,0); vector Ur(0,0,0); scalar ds(0); scalar nuf(0); scalar rhof(0); vector WenYuDrag(0,0,0); interpolationCellPoint<scalar> voidfractionInterpolator_(alpf_); interpolationCellPoint<vector> UInterpolator_(Uf_); // //_AO_Parallel DragForce_.resize(particleList_.size()); for(int ii =0; ii < particleList_.size(); ii++) { int index = particleList_[ii][0]; cellI = sm.cellIDs()[index][0]; drag = vector(0,0,0); Ufluid = vector(0,0,0); WenYuDrag = vector(0,0,0); DragForce_[ii] = vector(0,0,0); if (cellI > -1) // particle Found { position = sm.position(index); if ( alpf_[cellI] > 1. ) Pout << " voidfraction > 1 " << alpf_[cellI] << endl; voidfraction = voidfractionInterpolator_.interpolate(position,cellI); Ufluid = UInterpolator_.interpolate(position,cellI); if ( voidfraction > 1. ) { Pout << " Int. voidfraction > 1 " << " value= " << voidfraction; voidfraction = alpf_[cellI]; Pout << " mod. value = " << voidfraction << endl; } Up = sm.velocity(index); Ur = Ufluid-Up; ds = 2*sm.radius(index); rhof = rho_[cellI]; nuf = nufField[cellI]; // Drag force WenYuDragForce(Ur,ds,rhof,nuf,voidfraction,WenYuDrag); if(verbose_ && index <= 1) { Info << "" << endl; Pout << " index = " << index << endl; Pout << " position = " << position << endl; Pout << " Up = " << Up << endl; Pout << " Ur = " << Ur << endl; Pout << " dp = " << ds << endl; Pout << " rho = " << rhof << endl; Pout << " nuf = " << nuf << endl; Pout << " voidfraction = " << voidfraction << endl; Pout << " drag = " << WenYuDrag << endl; Info << " " << endl; } } for(int j=0;j<3;j++) DragForce_[ii][j] = WenYuDrag[j]; } }
void Foam::waveAbsorptionVelocity2DFvPatchVectorField::updateCoeffs() { if (updated()) { return; } // PHC // Info << "3D_2D Absorption BC on patch " << this->patch().name() << endl; // 3D Variables const vector cMin = gMin(patch().patch().localPoints()); const vector cMax = gMax(patch().patch().localPoints()); const vector cSpan = cMax - cMin; scalar dMin = 0.0; scalar dSpan = 0.0; const scalarField patchD = patchDirection( cSpan, &dMin, &dSpan ); // Variables & constants const volScalarField& alpha = db().lookupObject<volScalarField>(alphaName()); const volVectorField& U = db().lookupObject<volVectorField>("U"); const fvMesh& mesh = alpha.mesh(); const word& patchName = this->patch().name(); const label patchID = mesh.boundaryMesh().findPatchID(patchName); const label nF = patch().faceCells().size(); const scalarField alphaCell = alpha.boundaryField()[patchID].patchInternalField(); const vectorField UCell = U.boundaryField()[patchID].patchInternalField(); scalarField UzCell = UCell.component(2); scalarField patchUc = Foam::scalarField(nF, 0.0); // Correction velocity scalarField patchVc = Foam::scalarField(nF, 0.0); // Correction velocity const scalarField patchHeight = patch().Cf().component(2)-cMin[2]; const scalar g = 9.81; // Check for errors - Just the first time if (!allCheck_) { // Check if the value of nPaddles is correct for the number of columns if (nPaddles_ < 1) { FatalError << "Check nPaddles value." << exit(FatalError); } if ( nPaddles_ > 1 ) { nPaddles_ = decreaseNPaddles( nPaddles_, patchD, dMin, dSpan ); reduce(nPaddles_, minOp<label>()); } // Check nEdges if ( nEdgeMin_ < 0 || nEdgeMax_ < 0 ) { FatalError << "Check nEdgeMin/Max value." << exit(FatalError); } if ( nEdgeMin_ + nEdgeMax_ > nPaddles_ ) { FatalError << "Check: nEdges > nPaddles." << exit(FatalError); } } // Grouping part labelList faceGroup = Foam::labelList(nF, 0); scalarList dBreakPoints = Foam::scalarList(nPaddles_+1, dMin); scalarList xGroup = Foam::scalarList(nPaddles_, 0.0); scalarList yGroup = Foam::scalarList(nPaddles_, 0.0); for (label i=0; i<nPaddles_; i++) { // Breakpoints, X & Y centre of the paddles dBreakPoints[i+1] = dMin + dSpan/(nPaddles_)*(i+1); xGroup[i] = cMin[0] + cSpan[0]/(2.0*nPaddles_) + cSpan[0]/(nPaddles_)*i; yGroup[i] = cMin[1] + cSpan[1]/(2.0*nPaddles_) + cSpan[1]/(nPaddles_)*i; } forAll(patchD, patchCells) { for (label i=0; i<nPaddles_; i++) { if ( (patchD[patchCells]>=dBreakPoints[i]) && (patchD[patchCells]<dBreakPoints[i+1]) ) { faceGroup[patchCells] = i+1; // Group of each face continue; } } } if (!allCheck_) { // Calculate Z bounds of the faces scalarField zSup, zInf; faceBoundsZ( &zSup, &zInf ); // Z-span paddlewise zSpanL_ = zSpanList( faceGroup, zInf, zSup ); //inlinePrint( "Z-span paddlewise", zSpanL_ ); // Calculate initial water depth if ( gMin(initialWaterDepths_) < 0.0 ) { initialWaterDepths_ = calcWL( alphaCell, faceGroup, zSpanL_ ); inlinePrint( "Initial water depths for absorption", initialWaterDepths_ ); } // Absorption direction part meanAngles_ = initialWaterDepths_; // Check if absorption is directional if ( absorptionDir_ > 360.0 ) // Automatic { meanAngles_ = meanPatchDirs( faceGroup ); } else // Fixed { meanAngles_ = absorptionDir_*PI()/180.0; } //inlinePrint( "Paddle angles", meanAngles_ ); allCheck_ = true; } // Calculate water measured levels scalarList measuredLevels = calcWL( alphaCell, faceGroup, zSpanL_ ); // Correction velocity: U = -sqrt(g/h)*corrL scalarList corrLevels = measuredLevels - initialWaterDepths_; inlinePrint( "Correction Levels", corrLevels ); scalarList Uc = -sqrt(g/max(initialWaterDepths_,0.1))*corrLevels; // Limit in-flux for(label i=0; i<=nPaddles_-1; i++) { if( (i <= nEdgeMin_-1) || (i > nPaddles_-1-nEdgeMax_) ) { if( pos(Uc[i]) ) { Uc[i] = 0.0; } } } forAll(patchUc, cellIndex) { patchUc[cellIndex] = pos(alphaCell[cellIndex]-0.9)* Uc[faceGroup[cellIndex]-1]*cos(meanAngles_[faceGroup[cellIndex]-1]); patchVc[cellIndex] = pos(alphaCell[cellIndex]-0.9)* Uc[faceGroup[cellIndex]-1]*sin(meanAngles_[faceGroup[cellIndex]-1]); UzCell[cellIndex] = pos(alphaCell[cellIndex]-0.9)*UzCell[cellIndex]; }
void Foam::coupledPolyPatch::calcTransformTensors ( const vectorField& Cf, const vectorField& Cr, const vectorField& nf, const vectorField& nr, const scalarField& smallDist, const scalar absTol ) const { if (debug) { Pout<< "coupledPolyPatch::calcTransformTensors : " << name() << endl << " (half)size:" << Cf.size() << nl << " absTol:" << absTol << nl << " sum(mag(nf & nr)):" << sum(mag(nf & nr)) << endl; } // Tolerance calculation. // - normal calculation: assume absTol is the absolute error in a // single normal/transformation calculation. Consists both of numerical // precision (on the order of SMALL and of writing precision // (from e.g. decomposition) // Then the overall error of summing the normals is sqrt(size())*absTol // - separation calculation: pass in from the outside an allowable error. if (size() == 0) { // Dummy geometry. separation_.setSize(0); forwardT_ = I; reverseT_ = I; } else { scalar error = absTol*Foam::sqrt(1.0*Cf.size()); if (debug) { Pout<< " error:" << error << endl; } if (sum(mag(nf & nr)) < Cf.size() - error) { // Rotation, no separation separation_.setSize(0); forwardT_.setSize(Cf.size()); reverseT_.setSize(Cf.size()); forAll (forwardT_, facei) { forwardT_[facei] = rotationTensor(-nr[facei], nf[facei]); reverseT_[facei] = rotationTensor(nf[facei], -nr[facei]); } if (debug) { Pout<< " sum(mag(forwardT_ - forwardT_[0])):" << sum(mag(forwardT_ - forwardT_[0])) << endl; } if (sum(mag(forwardT_ - forwardT_[0])) < error) { forwardT_.setSize(1); reverseT_.setSize(1); if (debug) { Pout<< " difference in rotation less than" << " local tolerance " << error << ". Assuming uniform rotation." << endl; } } }