Пример #1
0
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
Пример #2
0
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
Пример #3
0
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;
}
Пример #6
0
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