BoundaryBox<NDIM> PhysicalBoundaryUtilities::trimBoundaryCodim1Box(const BoundaryBox<NDIM>& bdry_box, const Patch<NDIM>& patch) { #if !defined(NDEBUG) TBOX_ASSERT(bdry_box.getBoundaryType() == 1); #endif // Trim a boundary box so it does not stick out past the corners of a patch. const Box<NDIM>& b_box = bdry_box.getBox(); const Box<NDIM>& patch_box = patch.getBox(); const unsigned int bdry_normal_axis = bdry_box.getLocationIndex() / 2; Box<NDIM> trimmed_b_box = b_box; for (unsigned int d = 0; d < NDIM; ++d) { if (d != bdry_normal_axis) { trimmed_b_box.lower()[d] = std::max(b_box.lower()[d], patch_box.lower()[d]); trimmed_b_box.upper()[d] = std::min(b_box.upper()[d], patch_box.upper()[d]); } } const BoundaryBox<NDIM> trimmed_bdry_box( trimmed_b_box, bdry_box.getBoundaryType(), bdry_box.getLocationIndex()); return trimmed_bdry_box; } // trimBoundaryCodim1Box
Box<NDIM> PhysicalBoundaryUtilities::makeSideBoundaryCodim1Box(const BoundaryBox<NDIM>& bdry_box) { #if !defined(NDEBUG) TBOX_ASSERT(bdry_box.getBoundaryType() == 1); #endif // Make surface box on boundary. Box<NDIM> side_bdry_box = bdry_box.getBox(); const unsigned int location_index = bdry_box.getLocationIndex(); const unsigned int bdry_normal_axis = location_index / 2; const bool bdry_lower_side = (location_index % 2) == 0; if (bdry_lower_side) { // On the lower side of a patch, the side indices are one higher than // the boundary cell indices in the direction normal to the boundary. side_bdry_box.shift(bdry_normal_axis, 1); } return side_bdry_box; } // makeSideBoundaryCodim1Box
void Handle::drawBoundaryBox(const BoundaryBox& bb) { const Point& min = bb.getMinimum(); const Point& max = bb.getMaximum(); glColor3f(1.0f, 1.0f, 1.0f); glEnable(GL_LINE_STIPPLE); glLineStipple(1, 0xAAAA); glBegin(GL_LINE_LOOP); glVertex3f(max.x, max.y, min.z); glVertex3f(min.x, max.y, min.z); glVertex3f(min.x, min.y, min.z); glVertex3f(max.x, min.y, min.z); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(max.x, min.y, max.z); glVertex3f(max.x, max.y, max.z); glVertex3f(min.x, max.y, max.z); glVertex3f(min.x, min.y, max.z); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(max.x, max.y, min.z); glVertex3f(max.x, max.y, max.z); glVertex3f(min.x, max.y, max.z); glVertex3f(min.x, max.y, min.z); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(max.x, min.y, max.z); glVertex3f(min.x, min.y, max.z); glVertex3f(min.x, min.y, min.z); glVertex3f(max.x, min.y, min.z); glEnd(); glDisable(GL_LINE_STIPPLE); }
void INSCollocatedVelocityBcCoef::setBcCoefs(Pointer<ArrayData<NDIM, double> >& acoef_data, Pointer<ArrayData<NDIM, double> >& bcoef_data, Pointer<ArrayData<NDIM, double> >& gcoef_data, const Pointer<Variable<NDIM> >& variable, const Patch<NDIM>& patch, const BoundaryBox<NDIM>& bdry_box, double fill_time) const { #if !defined(NDEBUG) for (unsigned int d = 0; d < NDIM; ++d) { TBOX_ASSERT(d_bc_coefs[d]); } #endif // Set the unmodified velocity bc coefs. d_bc_coefs[d_comp_idx]->setBcCoefs( acoef_data, bcoef_data, gcoef_data, variable, patch, bdry_box, fill_time); // We do not make any further modifications to the values of acoef_data and // bcoef_data beyond this point. if (!gcoef_data) return; #if !defined(NDEBUG) TBOX_ASSERT(acoef_data); TBOX_ASSERT(bcoef_data); #endif // Ensure homogeneous boundary conditions are enforced. if (d_homogeneous_bc) gcoef_data->fillAll(0.0); // Where appropriate, update boundary condition coefficients. // // Dirichlet boundary conditions are not modified. // // Neumann boundary conditions on the normal component of the velocity are // interpreted as "open" boundary conditions, and we set du/dn = 0. // // Neumann boundary conditions on the tangential component of the velocity // are interpreted as traction (stress) boundary conditions, and we update // the boundary condition coefficients accordingly. const unsigned int location_index = bdry_box.getLocationIndex(); const unsigned int bdry_normal_axis = location_index / 2; const bool is_lower = location_index % 2 == 0; const Box<NDIM>& bc_coef_box = acoef_data->getBox(); #if !defined(NDEBUG) TBOX_ASSERT(bc_coef_box == acoef_data->getBox()); TBOX_ASSERT(bc_coef_box == bcoef_data->getBox()); TBOX_ASSERT(bc_coef_box == gcoef_data->getBox()); #endif const double mu = d_problem_coefs->getMu(); for (Box<NDIM>::Iterator it(bc_coef_box); it; it++) { const Index<NDIM>& i = it(); double& alpha = (*acoef_data)(i, 0); double& beta = (*bcoef_data)(i, 0); double& gamma = (*gcoef_data)(i, 0); const bool velocity_bc = MathUtilities<double>::equalEps(alpha, 1.0); const bool traction_bc = MathUtilities<double>::equalEps(beta, 1.0); #if !defined(NDEBUG) TBOX_ASSERT((velocity_bc || traction_bc) && !(velocity_bc && traction_bc)); #endif if (velocity_bc) { alpha = 1.0; beta = 0.0; } else if (traction_bc) { if (d_comp_idx == bdry_normal_axis) { // Set du/dn = 0. // // NOTE: We would prefer to determine the ghost cell value of // the normal velocity so that div u = 0 in the ghost cell. // This could be done here, but it is more convenient to do so // as a post-processing step after the tangential velocity ghost // cell values have all been set. alpha = 0.0; beta = 1.0; gamma = 0.0; } else { switch (d_traction_bc_type) { case PSEUDO_TRACTION: // mu*du_tan/dx_norm = g. { alpha = 0.0; beta = 1.0; gamma = (is_lower ? -1.0 : +1.0) * (gamma / mu); break; } default: { TBOX_ERROR( "INSCollocatedVelocityBcCoef::setBcCoefs(): unrecognized or " "unsupported " "traction boundary condition type: " << enum_to_string<TractionBcType>(d_traction_bc_type) << "\n"); } } } } else { TBOX_ERROR("this statement should not be reached!\n"); } } return; } // setBcCoefs
bool InstanceSurfaceScatterBuilder::testPositionPickAndAddObject(Scene& scene, const Point& position, RNG& rng, TestPosInfo& posInfo) { Ray occlusionRay(position, Normal(0.0f, -1.0f, 0.0f), RAY_ALL); // BVH intersectors depend on signed inf values resulting from div-by-0 for axis-aligned rays... occlusionRay.calculateInverseDirection(); HitResult hitResult; float t = 1000.0f; if (scene.didHitObject(occlusionRay, t, hitResult)) { if (hitResult.hitPoint.y < m_minimumCutoff) return false; Object* pSrcObject = posInfo.pCurrentSelectedObject; Point newPoint = position; newPoint.y -= t; unsigned int randomIndex = 0; if (posInfo.randomlyPickObject) { // TODO: Given that we're picking a random index AND a random location, we don't get the best // distribution here... if (posInfo.doSwitchover) { if (posInfo.switchCount < m_lastObjectSwitchover) { randomIndex = rng.randomInt(posInfo.numSelectedItems - 1); pSrcObject = SelectionManager::instance().getSelection().getSelectedObjectAtIndex(randomIndex); } else { // pick the last object randomIndex = posInfo.numSelectedItems - 1; pSrcObject = SelectionManager::instance().getSelection().getSelectedObjectAtIndex(randomIndex); } } else { // just randomly pick... randomIndex = rng.randomInt(posInfo.numSelectedItems); pSrcObject = SelectionManager::instance().getSelection().getSelectedObjectAtIndex(randomIndex); } // need to update the height of the object BoundaryBox shapeBBox = pSrcObject->getTransformedBoundaryBox(); posInfo.heightOffset = shapeBBox.getExtent().y * 0.5f; } float scaleVariation = 1.0f; if (posInfo.scaleVariation) { // scale variation can be larger or smaller than current object, split around the middle float halfVariation = m_uniformScaleVariation * 0.5f; scaleVariation = 1.0f - halfVariation + (m_uniformScaleVariation * rng.randomFloat()); } float localHeightOffset = posInfo.heightOffset; if (posInfo.scaleVariation) { localHeightOffset *= scaleVariation; } newPoint.y += localHeightOffset; // centre the object's bbox on the surface that was hit // TODO: an option to ratio this based on the surface flatness amount, so that objects on a flat surface // don't have as much as an offset, whereas objects on a steep incline (trees for example) have more of an offset newPoint.y += m_surfaceYOffset; Object* pNewObject = NULL; if (!posInfo.shouldMakeBakedInstances) { pNewObject = pSrcObject->clone(); if (m_alternatingMaterials) { Material* pMat = posInfo.aMaterials[posInfo.altMaterialIndex]; pNewObject->setMaterial(pMat); posInfo.altMaterialIndex++; if (posInfo.altMaterialIndex >= m_numMaterials) posInfo.altMaterialIndex = 0; } } else { if (posInfo.randomlyPickObject) { pNewObject = new CompoundInstance(posInfo.aMultipleSrcCO[randomIndex]); } else { pNewObject = new CompoundInstance(posInfo.pSrcCOForBakedInstances); } } pNewObject->setPosition(Vector(newPoint.x, newPoint.y, newPoint.z)); if (posInfo.scaleVariation) { float currentUScale = pNewObject->transform().getUniformScale(); pNewObject->transform().setUniformScale(currentUScale * scaleVariation); } if (m_alignToSurface) { // work out what the rotation should be to make it roughly flat on the surface - this won't be physically-accurate, but it's // a good starting point Quaternion rotateQ = Quaternion::fromDirections(Normal(0.0f, 1.0f, 0.0f), hitResult.geometryNormal); Matrix4 rotateM = rotateQ.toMatrix(); Vector rotation = rotateM.getRotationYXZ(); if (m_randomYRotation) { rotation.y = rng.randomFloat() * 360.0f; } pNewObject->setRotation(rotation); } else { if (m_randomYRotation) { pNewObject->setRotation(Vector(0.0f, rng.randomFloat() * 360.0f, 0.0f)); } } if (m_drawAsBBox) pNewObject->setDisplayType(eBoundaryBox); sprintf(posInfo.szName, "ScatteredOb_%d", posInfo.createdCount); // calling function needs to increment this pNewObject->setName(posInfo.szName, false); if (m_addToGroup) { posInfo.pNewCO->addObject(pNewObject, false); } else { addObject(scene, pNewObject); } } return true; }
void muParserRobinBcCoefs::setBcCoefs(Pointer<ArrayData<NDIM, double> >& acoef_data, Pointer<ArrayData<NDIM, double> >& bcoef_data, Pointer<ArrayData<NDIM, double> >& gcoef_data, const Pointer<Variable<NDIM> >& /*variable*/, const Patch<NDIM>& patch, const BoundaryBox<NDIM>& bdry_box, double fill_time) const { const Box<NDIM>& patch_box = patch.getBox(); const Index<NDIM>& patch_lower = patch_box.lower(); Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch.getPatchGeometry(); const double* const x_lower = pgeom->getXLower(); const double* const dx = pgeom->getDx(); // Loop over the boundary box and set the coefficients. const unsigned int location_index = bdry_box.getLocationIndex(); const unsigned int bdry_normal_axis = location_index / 2; const Box<NDIM>& bc_coef_box = (acoef_data ? acoef_data->getBox() : bcoef_data ? bcoef_data->getBox() : gcoef_data ? gcoef_data->getBox() : Box<NDIM>()); #if !defined(NDEBUG) TBOX_ASSERT(!acoef_data || bc_coef_box == acoef_data->getBox()); TBOX_ASSERT(!bcoef_data || bc_coef_box == bcoef_data->getBox()); TBOX_ASSERT(!gcoef_data || bc_coef_box == gcoef_data->getBox()); #endif const mu::Parser& acoef_parser = d_acoef_parsers[location_index]; const mu::Parser& bcoef_parser = d_bcoef_parsers[location_index]; const mu::Parser& gcoef_parser = d_gcoef_parsers[location_index]; *d_parser_time = fill_time; for (Box<NDIM>::Iterator b(bc_coef_box); b; b++) { const Index<NDIM>& i = b(); for (unsigned int d = 0; d < NDIM; ++d) { if (d != bdry_normal_axis) { (*d_parser_posn)[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d)) + 0.5); } else { (*d_parser_posn)[d] = x_lower[d] + dx[d] * (static_cast<double>(i(d) - patch_lower(d))); } } try { if (acoef_data) (*acoef_data)(i, 0) = acoef_parser.Eval(); if (bcoef_data) (*bcoef_data)(i, 0) = bcoef_parser.Eval(); if (gcoef_data) (*gcoef_data)(i, 0) = gcoef_parser.Eval(); } catch (mu::ParserError& e) { TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n" << " error: " << e.GetMsg() << "\n" << " in: " << e.GetExpr() << "\n"); } catch (...) { TBOX_ERROR("muParserRobinBcCoefs::setDataOnPatch():\n" << " unrecognized exception generated by muParser library.\n"); } } return; } // setBcCoefs
void INSStaggeredPressureBcCoef::setBcCoefs(Pointer<ArrayData<NDIM, double> >& acoef_data, Pointer<ArrayData<NDIM, double> >& bcoef_data, Pointer<ArrayData<NDIM, double> >& gcoef_data, const Pointer<Variable<NDIM> >& variable, const Patch<NDIM>& patch, const BoundaryBox<NDIM>& bdry_box, double /*fill_time*/) const { #if !defined(NDEBUG) for (unsigned int d = 0; d < NDIM; ++d) { TBOX_ASSERT(d_bc_coefs[d]); } TBOX_ASSERT(acoef_data); TBOX_ASSERT(bcoef_data); #endif Box<NDIM> bc_coef_box = acoef_data->getBox(); #if !defined(NDEBUG) TBOX_ASSERT(bc_coef_box == acoef_data->getBox()); TBOX_ASSERT(bc_coef_box == bcoef_data->getBox()); TBOX_ASSERT(!gcoef_data || (bc_coef_box == gcoef_data->getBox())); #endif // Set the unmodified velocity bc coefs. const unsigned int location_index = bdry_box.getLocationIndex(); const unsigned int bdry_normal_axis = location_index / 2; const bool is_lower = location_index % 2 == 0; const double half_time = d_fluid_solver->getIntegratorTime() + 0.5 * d_fluid_solver->getCurrentTimeStepSize(); d_bc_coefs[bdry_normal_axis]->setBcCoefs( acoef_data, bcoef_data, gcoef_data, variable, patch, bdry_box, half_time); // Ensure homogeneous boundary conditions are enforced. if (d_homogeneous_bc && gcoef_data) gcoef_data->fillAll(0.0); // Get the target velocity data. Pointer<SideData<NDIM, double> > u_target_data; if (d_u_target_data_idx >= 0) u_target_data = patch.getPatchData(d_u_target_data_idx); else if (d_target_data_idx >= 0) u_target_data = patch.getPatchData(d_target_data_idx); #if !defined(NDEBUG) TBOX_ASSERT(u_target_data); #endif Pointer<SideData<NDIM, double> > u_current_data = patch.getPatchData( d_fluid_solver->getVelocityVariable(), d_fluid_solver->getCurrentContext()); #if !defined(NDEBUG) TBOX_ASSERT(u_current_data); #endif const Box<NDIM> ghost_box = u_target_data->getGhostBox() * u_current_data->getGhostBox(); for (unsigned int d = 0; d < NDIM; ++d) { if (d != bdry_normal_axis) { bc_coef_box.lower(d) = std::max(bc_coef_box.lower(d), ghost_box.lower(d)); bc_coef_box.upper(d) = std::min(bc_coef_box.upper(d), ghost_box.upper(d)); } } // Update the boundary condition coefficients. Normal velocity boundary // conditions are converted into Neumann conditions for the pressure, and // normal traction boundary conditions are converted into Dirichlet // conditions for the pressure. const double mu = d_fluid_solver->getStokesSpecifications()->getMu(); Pointer<CartesianPatchGeometry<NDIM> > pgeom = patch.getPatchGeometry(); const double* const dx = pgeom->getDx(); for (Box<NDIM>::Iterator it(bc_coef_box); it; it++) { const Index<NDIM>& i = it(); double dummy_val; double& alpha = acoef_data ? (*acoef_data)(i, 0) : dummy_val; double& beta = bcoef_data ? (*bcoef_data)(i, 0) : dummy_val; double& gamma = gcoef_data ? (*gcoef_data)(i, 0) : dummy_val; const bool velocity_bc = MathUtilities<double>::equalEps(alpha, 1.0); const bool traction_bc = MathUtilities<double>::equalEps(beta, 1.0); #if !defined(NDEBUG) TBOX_ASSERT((velocity_bc || traction_bc) && !(velocity_bc && traction_bc)); #endif if (velocity_bc) { alpha = 0.0; beta = 1.0; gamma = 0.0; } else if (traction_bc) { switch (d_traction_bc_type) { case TRACTION: // -p + 2*mu*du_n/dx_n = g. { // Place i_i in the interior cell abutting the boundary, and // place i_g in the ghost cell abutting the boundary. Index<NDIM> i_i(i), i_g(i); if (is_lower) { i_g(bdry_normal_axis) -= 1; } else { i_i(bdry_normal_axis) -= 1; } // The boundary condition is -p + 2*mu*du_n/dx_n = g. // // Because p is centered about t^{n+1/2}, we compute this // as: // // p^{n+1/2} = mu*du_n/dx_n^{n} + mu*du_n/dx_n^{n+1} - g^{n+1/2}. static const int NVALS = 3; double u_current[NVALS], u_new[NVALS]; SideIndex<NDIM> i_s(i_i, bdry_normal_axis, is_lower ? SideIndex<NDIM>::Lower : SideIndex<NDIM>::Upper); for (int k = 0; k < NVALS; ++k, i_s(bdry_normal_axis) += (is_lower ? 1 : -1)) { u_current[k] = (*u_current_data)(i_s); u_new[k] = (*u_target_data)(i_s); } const double h = dx[bdry_normal_axis]; const double du_norm_current_dx_norm = (is_lower ? +1.0 : -1.0) * (2.0 * u_current[1] - 1.5 * u_current[0] - 0.5 * u_current[2]) / h; const double du_norm_new_dx_norm = (is_lower ? +1.0 : -1.0) * (2.0 * u_new[1] - 1.5 * u_new[0] - 0.5 * u_new[2]) / h; alpha = 1.0; beta = 0.0; gamma = (d_homogeneous_bc ? 0.0 : mu * du_norm_current_dx_norm) + mu * du_norm_new_dx_norm - gamma; break; } case PSEUDO_TRACTION: // -p = g. { alpha = 1.0; beta = 0.0; gamma = -gamma; break; } default: { TBOX_ERROR( "INSStaggeredPressureBcCoef::setBcCoefs(): unrecognized or unsupported " "traction boundary condition type: " << enum_to_string<TractionBcType>(d_traction_bc_type) << "\n"); } } } else { TBOX_ERROR("this statement should not be reached!\n"); } } return; } // setBcCoefs