<commit_before>// Filename: INSStaggeredStokesOperator.C
// Created on 29 Apr 2008 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "INSStaggeredStokesOperator.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBAMR_config
#include <IBAMR_config.h>
#define included_IBAMR_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBAMR INCLUDES
#include <ibamr/INSStaggeredPressureBcCoef.h>
#include <ibamr/namespaces.h>

// IBTK INCLUDES
#include <ibtk/CellNoCornersFillPattern.h>
#include <ibtk/SideNoCornersFillPattern.h>

// C++ STDLIB INCLUDES
#include <limits>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBAMR
{
/////////////////////////////// STATIC ///////////////////////////////////////

namespace
{
// Number of ghosts cells used for each variable quantity.
static const int CELLG = (USING_LARGE_GHOST_CELL_WIDTH ? 2 : 1);
static const int SIDEG = (USING_LARGE_GHOST_CELL_WIDTH ? 2 : 1);

// Type of coarsening to perform prior to setting coarse-fine boundary and
// physical boundary ghost cell values.
static const std::string DATA_COARSEN_TYPE = "CUBIC_COARSEN";

// Type of extrapolation to use at physical boundaries.
static const std::string BDRY_EXTRAP_TYPE = "LINEAR";

// Whether to enforce consistent interpolated values at Type 2 coarse-fine
// interface ghost cells.
static const bool CONSISTENT_TYPE_2_BDRY = false;

// Timers.
static Pointer<Timer> t_apply;
static Pointer<Timer> t_initialize_operator_state;
static Pointer<Timer> t_deallocate_operator_state;
}

/////////////////////////////// PUBLIC ///////////////////////////////////////

INSStaggeredStokesOperator::INSStaggeredStokesOperator(
    const INSCoefs& problem_coefs,
    const std::vector<RobinBcCoefStrategy<NDIM>*>& U_bc_coefs,
    Pointer<INSStaggeredPhysicalBoundaryHelper> U_bc_helper,
    RobinBcCoefStrategy<NDIM>* P_bc_coef,
    Pointer<HierarchyMathOps> hier_math_ops)
    : d_is_initialized(false),
      d_current_time(std::numeric_limits<double>::quiet_NaN()),
      d_new_time(std::numeric_limits<double>::quiet_NaN()),
      d_dt(std::numeric_limits<double>::quiet_NaN()),
      d_problem_coefs(problem_coefs),
      d_helmholtz_spec("INSStaggeredStokesOperator::helmholtz_spec"),
      d_hier_math_ops(hier_math_ops),
      d_homogeneous_bc(false),
      d_correcting_rhs(false),
      d_U_bc_coefs(U_bc_coefs),
      d_U_bc_helper(U_bc_helper),
      d_P_bc_coef(P_bc_coef),
      d_U_P_bdry_fill_op(Pointer<HierarchyGhostCellInterpolation>(NULL)),
      d_no_fill_op(Pointer<HierarchyGhostCellInterpolation>(NULL)),
      d_x_scratch(NULL)
{
    // Setup Timers.
    static bool timers_need_init = true;
    if (timers_need_init)
    {
        t_apply                     = TimerManager::getManager()->getTimer("IBAMR::INSStaggeredStokesOperator::apply()");
        t_initialize_operator_state = TimerManager::getManager()->getTimer("IBAMR::INSStaggeredStokesOperator::initializeOperatorState()");
        t_deallocate_operator_state = TimerManager::getManager()->getTimer("IBAMR::INSStaggeredStokesOperator::deallocateOperatorState()");
        timers_need_init = false;
    }
    return;
}// INSStaggeredStokesOperator

INSStaggeredStokesOperator::~INSStaggeredStokesOperator()
{
    deallocateOperatorState();
    return;
}// ~INSStaggeredStokesOperator

void
INSStaggeredStokesOperator::setHomogeneousBc(
    const bool homogeneous_bc)
{
    d_homogeneous_bc = homogeneous_bc;
    return;
}// setHomogeneousBc

void
INSStaggeredStokesOperator::setTimeInterval(
    const double current_time,
    const double new_time)
{
    const double rho    = d_problem_coefs.getRho();
    const double mu     = d_problem_coefs.getMu();
    const double lambda = d_problem_coefs.getLambda();
    d_current_time = current_time;
    d_new_time = new_time;
    d_dt = d_new_time-d_current_time;
    d_helmholtz_spec.setCConstant((rho/d_dt)+0.5*lambda);
    d_helmholtz_spec.setDConstant(          -0.5*mu    );
    return;
}// setTimeInterval

void
INSStaggeredStokesOperator::modifyRhsForInhomogeneousBc(
    SAMRAIVectorReal<NDIM,double>& y)
{
    // Set y := y - A*0, i.e., shift the right-hand-side vector to account for
    // inhomogeneous boundary conditions.
    if (!d_homogeneous_bc)
    {
        d_correcting_rhs = true;

        Pointer<SAMRAIVectorReal<NDIM,double> > x = y.cloneVector("");
        x->allocateVectorData();
        x->setToScalar(0.0);

        Pointer<SAMRAIVectorReal<NDIM,double> > b = y.cloneVector("");
        b->allocateVectorData();
        b->setToScalar(0.0);

        apply(*x,*b);
        y.subtract(Pointer<SAMRAIVectorReal<NDIM,double> >(&y, false), b);

        x->freeVectorComponents();
        x.setNull();

        b->freeVectorComponents();
        b.setNull();

        d_correcting_rhs = false;
    }
    return;
}// modifyRhsForInhomogeneousBc

void
INSStaggeredStokesOperator::apply(
    const bool homogeneous_bc,
    SAMRAIVectorReal<NDIM,double>& x,
    SAMRAIVectorReal<NDIM,double>& y)
{
    t_apply->start();

    // Get the vector components.
//  const int U_in_idx       =            x.getComponentDescriptorIndex(0);
//  const int P_in_idx       =            x.getComponentDescriptorIndex(1);
    const int U_out_idx      =            y.getComponentDescriptorIndex(0);
    const int P_out_idx      =            y.getComponentDescriptorIndex(1);
    const int U_scratch_idx  = d_x_scratch->getComponentDescriptorIndex(0);
    const int P_scratch_idx  = d_x_scratch->getComponentDescriptorIndex(1);

    const Pointer<Variable<NDIM> >& U_out_var = y.getComponentVariable(0);
    const Pointer<Variable<NDIM> >& P_out_var = y.getComponentVariable(1);

    Pointer<SideVariable<NDIM,double> > U_out_sc_var = U_out_var;
    Pointer<CellVariable<NDIM,double> > P_out_cc_var = P_out_var;

    const Pointer<Variable<NDIM> >& U_scratch_var = d_x_scratch->getComponentVariable(0);
    const Pointer<Variable<NDIM> >& P_scratch_var = d_x_scratch->getComponentVariable(1);

    Pointer<SideVariable<NDIM,double> > U_scratch_sc_var = U_scratch_var;
    Pointer<CellVariable<NDIM,double> > P_scratch_cc_var = P_scratch_var;

    d_x_scratch->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&x,false));

    // Reset the interpolation operators and fill the data.
    Pointer<VariableFillPattern<NDIM> > sc_fill_pattern = new SideNoCornersFillPattern(SIDEG, false, true);
    Pointer<VariableFillPattern<NDIM> > cc_fill_pattern = new CellNoCornersFillPattern(CELLG, false, true);
    typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent;
    InterpolationTransactionComponent U_scratch_component(U_scratch_idx, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_U_bc_coefs, sc_fill_pattern);
    InterpolationTransactionComponent P_scratch_component(P_scratch_idx, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_P_bc_coef , cc_fill_pattern);
    std::vector<InterpolationTransactionComponent> U_P_components(2);
    U_P_components[0] = U_scratch_component;
    U_P_components[1] = P_scratch_component;
    INSStaggeredPressureBcCoef* P_bc_coef = dynamic_cast<INSStaggeredPressureBcCoef*>(d_P_bc_coef);
    P_bc_coef->setVelocityNewPatchDataIndex(U_scratch_idx);
    d_U_P_bdry_fill_op->setHomogeneousBc(homogeneous_bc);
    d_U_P_bdry_fill_op->resetTransactionComponents(U_P_components);
    d_U_P_bdry_fill_op->fillData(d_new_time);

    // Compute the action of the operator:
    //      A*[u;p] = [((rho/dt)*I-0.5*mu*L)*u + grad p; -div u].
    static const bool cf_bdry_synch = true;
    d_hier_math_ops->grad(
        U_out_idx, U_out_sc_var,
        cf_bdry_synch,
        1.0, P_scratch_idx, P_scratch_cc_var, d_no_fill_op, d_new_time);
    d_hier_math_ops->laplace(
        U_out_idx, U_out_sc_var,
        d_helmholtz_spec,
        U_scratch_idx, U_scratch_sc_var, d_no_fill_op, d_new_time,
        1.0,
        U_out_idx, U_out_sc_var);
    d_U_bc_helper->zeroValuesAtDirichletBoundaries(U_out_idx);

    d_hier_math_ops->div(
        P_out_idx, P_out_cc_var,
        -1.0, U_scratch_idx, U_scratch_sc_var, d_no_fill_op, d_new_time,
        cf_bdry_synch);

    t_apply->stop();
    return;
}// apply

void
INSStaggeredStokesOperator::apply(
    SAMRAIVectorReal<NDIM,double>& x,
    SAMRAIVectorReal<NDIM,double>& y)
{
    apply(d_correcting_rhs ? d_homogeneous_bc : true,x,y);
    return;
}// apply

void
INSStaggeredStokesOperator::initializeOperatorState(
    const SAMRAIVectorReal<NDIM,double>& in,
    const SAMRAIVectorReal<NDIM,double>& out)
{
    t_initialize_operator_state->start();

    if (d_is_initialized) deallocateOperatorState();

    d_x_scratch = in.cloneVector("INSStaggeredStokesOperator::x_scratch");
    d_x_scratch->allocateVectorData();

    Pointer<VariableFillPattern<NDIM> > sc_fill_pattern = new SideNoCornersFillPattern(SIDEG, false, true);
    Pointer<VariableFillPattern<NDIM> > cc_fill_pattern = new CellNoCornersFillPattern(CELLG, false, true);
    typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent;
    InterpolationTransactionComponent U_scratch_component(d_x_scratch->getComponentDescriptorIndex(0), DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_U_bc_coefs, sc_fill_pattern);
    InterpolationTransactionComponent P_scratch_component(d_x_scratch->getComponentDescriptorIndex(1), DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_P_bc_coef , cc_fill_pattern);

    std::vector<InterpolationTransactionComponent> U_P_components(2);
    U_P_components[0] = U_scratch_component;
    U_P_components[1] = P_scratch_component;

    d_U_P_bdry_fill_op = new HierarchyGhostCellInterpolation();
    d_U_P_bdry_fill_op->initializeOperatorState(U_P_components, d_x_scratch->getPatchHierarchy());

    d_is_initialized = true;

    t_initialize_operator_state->stop();
    return;
}// initializeOperatorState

void
INSStaggeredStokesOperator::deallocateOperatorState()
{
    if (!d_is_initialized) return;

    t_deallocate_operator_state->start();

    d_x_scratch->freeVectorComponents();
    d_x_scratch.setNull();

    d_is_initialized = false;

    t_deallocate_operator_state->stop();
    return;
}// deallocateOperatorState

void
INSStaggeredStokesOperator::enableLogging(
    bool enabled)
{
    // intentionally blank
    return;
}// enableLogging

/////////////////////////////// PROTECTED ////////////////////////////////////

/////////////////////////////// PRIVATE //////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

}// namespace IBAMR

/////////////////////// TEMPLATE INSTANTIATION ///////////////////////////////

#include <tbox/Pointer.C>
template class Pointer<IBAMR::INSStaggeredStokesOperator>;

//////////////////////////////////////////////////////////////////////////////
<commit_msg>updated INSStaggeredStokesOperator.C to work with NULL BC objects<commit_after>// Filename: INSStaggeredStokesOperator.C
// Created on 29 Apr 2008 by Boyce Griffith
//
// Copyright (c) 2002-2010, Boyce Griffith
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//    * Neither the name of New York University nor the names of its
//      contributors may be used to endorse or promote products derived from
//      this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "INSStaggeredStokesOperator.h"

/////////////////////////////// INCLUDES /////////////////////////////////////

#ifndef included_IBAMR_config
#include <IBAMR_config.h>
#define included_IBAMR_config
#endif

#ifndef included_SAMRAI_config
#include <SAMRAI_config.h>
#define included_SAMRAI_config
#endif

// IBAMR INCLUDES
#include <ibamr/INSStaggeredPressureBcCoef.h>
#include <ibamr/namespaces.h>

// IBTK INCLUDES
#include <ibtk/CellNoCornersFillPattern.h>
#include <ibtk/SideNoCornersFillPattern.h>

// C++ STDLIB INCLUDES
#include <limits>

/////////////////////////////// NAMESPACE ////////////////////////////////////

namespace IBAMR
{
/////////////////////////////// STATIC ///////////////////////////////////////

namespace
{
// Number of ghosts cells used for each variable quantity.
static const int CELLG = (USING_LARGE_GHOST_CELL_WIDTH ? 2 : 1);
static const int SIDEG = (USING_LARGE_GHOST_CELL_WIDTH ? 2 : 1);

// Type of coarsening to perform prior to setting coarse-fine boundary and
// physical boundary ghost cell values.
static const std::string DATA_COARSEN_TYPE = "CUBIC_COARSEN";

// Type of extrapolation to use at physical boundaries.
static const std::string BDRY_EXTRAP_TYPE = "LINEAR";

// Whether to enforce consistent interpolated values at Type 2 coarse-fine
// interface ghost cells.
static const bool CONSISTENT_TYPE_2_BDRY = false;

// Timers.
static Pointer<Timer> t_apply;
static Pointer<Timer> t_initialize_operator_state;
static Pointer<Timer> t_deallocate_operator_state;
}

/////////////////////////////// PUBLIC ///////////////////////////////////////

INSStaggeredStokesOperator::INSStaggeredStokesOperator(
    const INSCoefs& problem_coefs,
    const std::vector<RobinBcCoefStrategy<NDIM>*>& U_bc_coefs,
    Pointer<INSStaggeredPhysicalBoundaryHelper> U_bc_helper,
    RobinBcCoefStrategy<NDIM>* P_bc_coef,
    Pointer<HierarchyMathOps> hier_math_ops)
    : d_is_initialized(false),
      d_current_time(std::numeric_limits<double>::quiet_NaN()),
      d_new_time(std::numeric_limits<double>::quiet_NaN()),
      d_dt(std::numeric_limits<double>::quiet_NaN()),
      d_problem_coefs(problem_coefs),
      d_helmholtz_spec("INSStaggeredStokesOperator::helmholtz_spec"),
      d_hier_math_ops(hier_math_ops),
      d_homogeneous_bc(false),
      d_correcting_rhs(false),
      d_U_bc_coefs(U_bc_coefs),
      d_U_bc_helper(U_bc_helper),
      d_P_bc_coef(P_bc_coef),
      d_U_P_bdry_fill_op(Pointer<HierarchyGhostCellInterpolation>(NULL)),
      d_no_fill_op(Pointer<HierarchyGhostCellInterpolation>(NULL)),
      d_x_scratch(NULL)
{
    // Setup Timers.
    static bool timers_need_init = true;
    if (timers_need_init)
    {
        t_apply                     = TimerManager::getManager()->getTimer("IBAMR::INSStaggeredStokesOperator::apply()");
        t_initialize_operator_state = TimerManager::getManager()->getTimer("IBAMR::INSStaggeredStokesOperator::initializeOperatorState()");
        t_deallocate_operator_state = TimerManager::getManager()->getTimer("IBAMR::INSStaggeredStokesOperator::deallocateOperatorState()");
        timers_need_init = false;
    }
    return;
}// INSStaggeredStokesOperator

INSStaggeredStokesOperator::~INSStaggeredStokesOperator()
{
    deallocateOperatorState();
    return;
}// ~INSStaggeredStokesOperator

void
INSStaggeredStokesOperator::setHomogeneousBc(
    const bool homogeneous_bc)
{
    d_homogeneous_bc = homogeneous_bc;
    return;
}// setHomogeneousBc

void
INSStaggeredStokesOperator::setTimeInterval(
    const double current_time,
    const double new_time)
{
    const double rho    = d_problem_coefs.getRho();
    const double mu     = d_problem_coefs.getMu();
    const double lambda = d_problem_coefs.getLambda();
    d_current_time = current_time;
    d_new_time = new_time;
    d_dt = d_new_time-d_current_time;
    d_helmholtz_spec.setCConstant((rho/d_dt)+0.5*lambda);
    d_helmholtz_spec.setDConstant(          -0.5*mu    );
    return;
}// setTimeInterval

void
INSStaggeredStokesOperator::modifyRhsForInhomogeneousBc(
    SAMRAIVectorReal<NDIM,double>& y)
{
    // Set y := y - A*0, i.e., shift the right-hand-side vector to account for
    // inhomogeneous boundary conditions.
    if (!d_homogeneous_bc)
    {
        d_correcting_rhs = true;

        Pointer<SAMRAIVectorReal<NDIM,double> > x = y.cloneVector("");
        x->allocateVectorData();
        x->setToScalar(0.0);

        Pointer<SAMRAIVectorReal<NDIM,double> > b = y.cloneVector("");
        b->allocateVectorData();
        b->setToScalar(0.0);

        apply(*x,*b);
        y.subtract(Pointer<SAMRAIVectorReal<NDIM,double> >(&y, false), b);

        x->freeVectorComponents();
        x.setNull();

        b->freeVectorComponents();
        b.setNull();

        d_correcting_rhs = false;
    }
    return;
}// modifyRhsForInhomogeneousBc

void
INSStaggeredStokesOperator::apply(
    const bool homogeneous_bc,
    SAMRAIVectorReal<NDIM,double>& x,
    SAMRAIVectorReal<NDIM,double>& y)
{
    t_apply->start();

    // Get the vector components.
//  const int U_in_idx       =            x.getComponentDescriptorIndex(0);
//  const int P_in_idx       =            x.getComponentDescriptorIndex(1);
    const int U_out_idx      =            y.getComponentDescriptorIndex(0);
    const int P_out_idx      =            y.getComponentDescriptorIndex(1);
    const int U_scratch_idx  = d_x_scratch->getComponentDescriptorIndex(0);
    const int P_scratch_idx  = d_x_scratch->getComponentDescriptorIndex(1);

    const Pointer<Variable<NDIM> >& U_out_var = y.getComponentVariable(0);
    const Pointer<Variable<NDIM> >& P_out_var = y.getComponentVariable(1);

    Pointer<SideVariable<NDIM,double> > U_out_sc_var = U_out_var;
    Pointer<CellVariable<NDIM,double> > P_out_cc_var = P_out_var;

    const Pointer<Variable<NDIM> >& U_scratch_var = d_x_scratch->getComponentVariable(0);
    const Pointer<Variable<NDIM> >& P_scratch_var = d_x_scratch->getComponentVariable(1);

    Pointer<SideVariable<NDIM,double> > U_scratch_sc_var = U_scratch_var;
    Pointer<CellVariable<NDIM,double> > P_scratch_cc_var = P_scratch_var;

    d_x_scratch->copyVector(Pointer<SAMRAIVectorReal<NDIM,double> >(&x,false));

    // Reset the interpolation operators and fill the data.
    Pointer<VariableFillPattern<NDIM> > sc_fill_pattern = new SideNoCornersFillPattern(SIDEG, false, true);
    Pointer<VariableFillPattern<NDIM> > cc_fill_pattern = new CellNoCornersFillPattern(CELLG, false, true);
    typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent;
    InterpolationTransactionComponent U_scratch_component(U_scratch_idx, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_U_bc_coefs, sc_fill_pattern);
    InterpolationTransactionComponent P_scratch_component(P_scratch_idx, DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_P_bc_coef , cc_fill_pattern);
    std::vector<InterpolationTransactionComponent> U_P_components(2);
    U_P_components[0] = U_scratch_component;
    U_P_components[1] = P_scratch_component;
    INSStaggeredPressureBcCoef* P_bc_coef = dynamic_cast<INSStaggeredPressureBcCoef*>(d_P_bc_coef);
    if (P_bc_coef != NULL) P_bc_coef->setVelocityNewPatchDataIndex(U_scratch_idx);
    d_U_P_bdry_fill_op->setHomogeneousBc(homogeneous_bc);
    d_U_P_bdry_fill_op->resetTransactionComponents(U_P_components);
    d_U_P_bdry_fill_op->fillData(d_new_time);

    // Compute the action of the operator:
    //      A*[u;p] = [((rho/dt)*I-0.5*mu*L)*u + grad p; -div u].
    static const bool cf_bdry_synch = true;
    d_hier_math_ops->grad(
        U_out_idx, U_out_sc_var,
        cf_bdry_synch,
        1.0, P_scratch_idx, P_scratch_cc_var, d_no_fill_op, d_new_time);
    d_hier_math_ops->laplace(
        U_out_idx, U_out_sc_var,
        d_helmholtz_spec,
        U_scratch_idx, U_scratch_sc_var, d_no_fill_op, d_new_time,
        1.0,
        U_out_idx, U_out_sc_var);
    if (!d_U_bc_helper.isNull()) d_U_bc_helper->zeroValuesAtDirichletBoundaries(U_out_idx);

    d_hier_math_ops->div(
        P_out_idx, P_out_cc_var,
        -1.0, U_scratch_idx, U_scratch_sc_var, d_no_fill_op, d_new_time,
        cf_bdry_synch);

    t_apply->stop();
    return;
}// apply

void
INSStaggeredStokesOperator::apply(
    SAMRAIVectorReal<NDIM,double>& x,
    SAMRAIVectorReal<NDIM,double>& y)
{
    apply(d_correcting_rhs ? d_homogeneous_bc : true,x,y);
    return;
}// apply

void
INSStaggeredStokesOperator::initializeOperatorState(
    const SAMRAIVectorReal<NDIM,double>& in,
    const SAMRAIVectorReal<NDIM,double>& out)
{
    t_initialize_operator_state->start();

    if (d_is_initialized) deallocateOperatorState();

    d_x_scratch = in.cloneVector("INSStaggeredStokesOperator::x_scratch");
    d_x_scratch->allocateVectorData();

    Pointer<VariableFillPattern<NDIM> > sc_fill_pattern = new SideNoCornersFillPattern(SIDEG, false, true);
    Pointer<VariableFillPattern<NDIM> > cc_fill_pattern = new CellNoCornersFillPattern(CELLG, false, true);
    typedef HierarchyGhostCellInterpolation::InterpolationTransactionComponent InterpolationTransactionComponent;
    InterpolationTransactionComponent U_scratch_component(d_x_scratch->getComponentDescriptorIndex(0), DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_U_bc_coefs, sc_fill_pattern);
    InterpolationTransactionComponent P_scratch_component(d_x_scratch->getComponentDescriptorIndex(1), DATA_COARSEN_TYPE, BDRY_EXTRAP_TYPE, CONSISTENT_TYPE_2_BDRY, d_P_bc_coef , cc_fill_pattern);

    std::vector<InterpolationTransactionComponent> U_P_components(2);
    U_P_components[0] = U_scratch_component;
    U_P_components[1] = P_scratch_component;

    d_U_P_bdry_fill_op = new HierarchyGhostCellInterpolation();
    d_U_P_bdry_fill_op->initializeOperatorState(U_P_components, d_x_scratch->getPatchHierarchy());

    d_is_initialized = true;

    t_initialize_operator_state->stop();
    return;
}// initializeOperatorState

void
INSStaggeredStokesOperator::deallocateOperatorState()
{
    if (!d_is_initialized) return;

    t_deallocate_operator_state->start();

    d_x_scratch->freeVectorComponents();
    d_x_scratch.setNull();

    d_is_initialized = false;

    t_deallocate_operator_state->stop();
    return;
}// deallocateOperatorState

void
INSStaggeredStokesOperator::enableLogging(
    bool enabled)
{
    // intentionally blank
    return;
}// enableLogging

/////////////////////////////// PROTECTED ////////////////////////////////////

/////////////////////////////// PRIVATE //////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////

}// namespace IBAMR

/////////////////////// TEMPLATE INSTANTIATION ///////////////////////////////

#include <tbox/Pointer.C>
template class Pointer<IBAMR::INSStaggeredStokesOperator>;

//////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "NeighborCoupleable.h"

#include "FEProblem.h"
#include "MooseError.h" // mooseDeprecated
#include "MooseVariableFE.h"
#include "Problem.h"
#include "SubProblem.h"

NeighborCoupleable::NeighborCoupleable(const MooseObject * moose_object,
                                       bool nodal,
                                       bool neighbor_nodal,
                                       bool is_fv)
  : Coupleable(moose_object, nodal, is_fv), _neighbor_nodal(neighbor_nodal)
{
}

const VariableValue &
NeighborCoupleable::coupledNeighborValue(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return (_c_is_implicit) ? var->dofValuesNeighbor() : var->dofValuesOldNeighbor();
  else
    return (_c_is_implicit) ? var->slnNeighbor() : var->slnOldNeighbor();
}

std::vector<const VariableValue *>
NeighborCoupleable::coupledNeighborValues(const std::string & var_name) const
{
  auto func = [this, &var_name](unsigned int comp) {
    return &coupledNeighborValue(var_name, comp);
  };
  return coupledVectorHelper<const VariableValue *>(var_name, func);
}

const ADVariableValue &
NeighborCoupleable::adCoupledNeighborValue(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVarHelper<MooseVariableField<Real>>(var_name, comp);

  if (!var)
    return *getADDefaultValue(var_name);

  if (_neighbor_nodal)
    mooseError("adCoupledNeighborValue cannot be used for nodal compute objects at this time");
  if (!_c_is_implicit)
    mooseError("adCoupledNeighborValue returns a data structure with derivatives. Explicit schemes "
               "use old solution data which do not have derivatives so adCoupledNeighborValue is "
               "not appropriate. Please use coupledNeighborValue instead");

  return var->adSlnNeighbor();
}

std::vector<const ADVariableValue *>
NeighborCoupleable::adCoupledNeighborValues(const std::string & var_name) const
{
  auto func = [this, &var_name](unsigned int comp) {
    return &adCoupledNeighborValue(var_name, comp);
  };
  return coupledVectorHelper<const ADVariableValue *>(var_name, func);
}

const ADVectorVariableValue &
NeighborCoupleable::adCoupledVectorNeighborValue(const std::string & var_name,
                                                 unsigned int comp) const
{
  auto var = getVarHelper<MooseVariableField<RealVectorValue>>(var_name, comp);

  if (!var)
    return *getADDefaultVectorValue(var_name);

  if (_neighbor_nodal)
    mooseError(
        "adCoupledVectorNeighborValue cannot be used for nodal compute objects at this time");
  if (!_c_is_implicit)
    mooseError(
        "adCoupledVectorNeighborValue returns a data structure with derivatives. Explicit schemes "
        "use old solution data which do not have derivatives so adCoupledVectorNeighborValue is "
        "not appropriate. Please use coupledNeighborValue instead");

  return var->adSlnNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueDot(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return var->dofValuesDotNeighbor();
  else
    return var->uDotNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueDotDu(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return var->dofValuesDuDotDuNeighbor();
  else
    return var->duDotDuNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueOld(const std::string & var_name, unsigned int comp) const
{
  validateExecutionerType(var_name, "coupledNeighborValueOld");

  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return (_c_is_implicit) ? var->dofValuesOldNeighbor() : var->dofValuesOlderNeighbor();
  else
    return (_c_is_implicit) ? var->slnOldNeighbor() : var->slnOlderNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueOlder(const std::string & var_name, unsigned int comp) const
{
  validateExecutionerType(var_name, "coupledNeighborValueOlder");

  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
  {
    if (_c_is_implicit)
      return var->dofValuesOlderNeighbor();
    else
      mooseError("Older values not available for explicit schemes");
  }
  else
  {
    if (_c_is_implicit)
      return var->slnOlderNeighbor();
    else
      mooseError("Older values not available for explicit schemes");
  }
}

const VariableGradient &
NeighborCoupleable::coupledNeighborGradient(const std::string & var_name, unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have gradients");

  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnNeighbor() : var->gradSlnOldNeighbor();
}

const VariableGradient &
NeighborCoupleable::coupledNeighborGradientOld(const std::string & var_name,
                                               unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have gradients");

  validateExecutionerType(var_name, "coupledNeighborGradientOld");
  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnOldNeighbor() : var->gradSlnOlderNeighbor();
}

const VariableGradient &
NeighborCoupleable::coupledNeighborGradientOlder(const std::string & var_name,
                                                 unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have gradients");

  validateExecutionerType(var_name, "coupledNeighborGradientOlder");
  const auto * var = getVar(var_name, comp);
  if (_c_is_implicit)
    return var->gradSlnOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradient(const std::string & var_name,
                                                  unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  const auto * var = getVectorVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnNeighbor() : var->gradSlnOldNeighbor();
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradientOld(const std::string & var_name,
                                                     unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledVectorNeighborGradientOld");
  const auto * var = getVectorVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnOldNeighbor() : var->gradSlnOlderNeighbor();
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradientOlder(const std::string & var_name,
                                                       unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledVectorNeighborGradientOlder");
  const auto * var = getVectorVar(var_name, comp);
  if (_c_is_implicit)
    return var->gradSlnOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}

const ArrayVariableValue &
NeighborCoupleable::coupledArrayNeighborValue(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getArrayVar(var_name, comp);
  if (_neighbor_nodal)
    return (_c_is_implicit) ? var->dofValuesNeighbor() : var->dofValuesOldNeighbor();
  else
    return (_c_is_implicit) ? var->slnNeighbor() : var->slnOldNeighbor();
}

const ArrayVariableGradient &
NeighborCoupleable::coupledArrayNeighborGradient(const std::string & var_name,
                                                 unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  const auto * var = getArrayVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnNeighbor() : var->gradSlnOldNeighbor();
}

const ArrayVariableGradient &
NeighborCoupleable::coupledArrayNeighborGradientOld(const std::string & var_name,
                                                    unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledArrayNeighborGradientOld");
  const auto * var = getArrayVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnOldNeighbor() : var->gradSlnOlderNeighbor();
}

const ArrayVariableGradient &
NeighborCoupleable::coupledArrayNeighborGradientOlder(const std::string & var_name,
                                                      unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledArrayNeighborGradientOlder");
  const auto * var = getArrayVar(var_name, comp);
  if (_c_is_implicit)
    return var->gradSlnOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}

const VariableSecond &
NeighborCoupleable::coupledNeighborSecond(const std::string & var_name, unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have second derivatives");

  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->secondSlnNeighbor() : var->secondSlnOldNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborDofValues(const std::string & var_name, unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("nodal objects should not call coupledDofValues");

  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->dofValuesNeighbor() : var->dofValuesOldNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborDofValuesOld(const std::string & var_name,
                                                unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("nodal objects should not call coupledDofValuesOld");

  validateExecutionerType(var_name, "coupledNeighborDofValuesOld");
  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->dofValuesOldNeighbor() : var->dofValuesOlderNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborDofValuesOlder(const std::string & var_name,
                                                  unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("nodal objects should not call coupledDofValuesOlder");

  validateExecutionerType(var_name, "coupledNeighborDofValuesOlder");
  const auto * var = getVar(var_name, comp);
  if (_c_is_implicit)
    return var->dofValuesOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}
<commit_msg>Allow use of FV variables with neighborCoupledValue/Gradient<commit_after>//* This file is part of the MOOSE framework
//* https://www.mooseframework.org
//*
//* All rights reserved, see COPYRIGHT for full restrictions
//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
//*
//* Licensed under LGPL 2.1, please see LICENSE for details
//* https://www.gnu.org/licenses/lgpl-2.1.html

#include "NeighborCoupleable.h"

#include "FEProblem.h"
#include "MooseError.h" // mooseDeprecated
#include "MooseVariableFE.h"
#include "Problem.h"
#include "SubProblem.h"

NeighborCoupleable::NeighborCoupleable(const MooseObject * moose_object,
                                       bool nodal,
                                       bool neighbor_nodal,
                                       bool is_fv)
  : Coupleable(moose_object, nodal, is_fv), _neighbor_nodal(neighbor_nodal)
{
}

const VariableValue &
NeighborCoupleable::coupledNeighborValue(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVarHelper<MooseVariableField<Real>>(var_name, comp);
  if (_neighbor_nodal)
    return (_c_is_implicit) ? var->dofValuesNeighbor() : var->dofValuesOldNeighbor();
  else
    return (_c_is_implicit) ? var->slnNeighbor() : var->slnOldNeighbor();
}

std::vector<const VariableValue *>
NeighborCoupleable::coupledNeighborValues(const std::string & var_name) const
{
  auto func = [this, &var_name](unsigned int comp) {
    return &coupledNeighborValue(var_name, comp);
  };
  return coupledVectorHelper<const VariableValue *>(var_name, func);
}

const ADVariableValue &
NeighborCoupleable::adCoupledNeighborValue(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVarHelper<MooseVariableField<Real>>(var_name, comp);

  if (!var)
    return *getADDefaultValue(var_name);

  if (_neighbor_nodal)
    mooseError("adCoupledNeighborValue cannot be used for nodal compute objects at this time");
  if (!_c_is_implicit)
    mooseError("adCoupledNeighborValue returns a data structure with derivatives. Explicit schemes "
               "use old solution data which do not have derivatives so adCoupledNeighborValue is "
               "not appropriate. Please use coupledNeighborValue instead");

  return var->adSlnNeighbor();
}

std::vector<const ADVariableValue *>
NeighborCoupleable::adCoupledNeighborValues(const std::string & var_name) const
{
  auto func = [this, &var_name](unsigned int comp) {
    return &adCoupledNeighborValue(var_name, comp);
  };
  return coupledVectorHelper<const ADVariableValue *>(var_name, func);
}

const ADVectorVariableValue &
NeighborCoupleable::adCoupledVectorNeighborValue(const std::string & var_name,
                                                 unsigned int comp) const
{
  auto var = getVarHelper<MooseVariableField<RealVectorValue>>(var_name, comp);

  if (!var)
    return *getADDefaultVectorValue(var_name);

  if (_neighbor_nodal)
    mooseError(
        "adCoupledVectorNeighborValue cannot be used for nodal compute objects at this time");
  if (!_c_is_implicit)
    mooseError(
        "adCoupledVectorNeighborValue returns a data structure with derivatives. Explicit schemes "
        "use old solution data which do not have derivatives so adCoupledVectorNeighborValue is "
        "not appropriate. Please use coupledNeighborValue instead");

  return var->adSlnNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueDot(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return var->dofValuesDotNeighbor();
  else
    return var->uDotNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueDotDu(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return var->dofValuesDuDotDuNeighbor();
  else
    return var->duDotDuNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueOld(const std::string & var_name, unsigned int comp) const
{
  validateExecutionerType(var_name, "coupledNeighborValueOld");

  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
    return (_c_is_implicit) ? var->dofValuesOldNeighbor() : var->dofValuesOlderNeighbor();
  else
    return (_c_is_implicit) ? var->slnOldNeighbor() : var->slnOlderNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborValueOlder(const std::string & var_name, unsigned int comp) const
{
  validateExecutionerType(var_name, "coupledNeighborValueOlder");

  const auto * var = getVar(var_name, comp);
  if (_neighbor_nodal)
  {
    if (_c_is_implicit)
      return var->dofValuesOlderNeighbor();
    else
      mooseError("Older values not available for explicit schemes");
  }
  else
  {
    if (_c_is_implicit)
      return var->slnOlderNeighbor();
    else
      mooseError("Older values not available for explicit schemes");
  }
}

const VariableGradient &
NeighborCoupleable::coupledNeighborGradient(const std::string & var_name, unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have gradients");

  const auto * var = getVarHelper<MooseVariableField<Real>>(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnNeighbor() : var->gradSlnOldNeighbor();
}

const VariableGradient &
NeighborCoupleable::coupledNeighborGradientOld(const std::string & var_name,
                                               unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have gradients");

  validateExecutionerType(var_name, "coupledNeighborGradientOld");
  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnOldNeighbor() : var->gradSlnOlderNeighbor();
}

const VariableGradient &
NeighborCoupleable::coupledNeighborGradientOlder(const std::string & var_name,
                                                 unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have gradients");

  validateExecutionerType(var_name, "coupledNeighborGradientOlder");
  const auto * var = getVar(var_name, comp);
  if (_c_is_implicit)
    return var->gradSlnOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradient(const std::string & var_name,
                                                  unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  const auto * var = getVectorVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnNeighbor() : var->gradSlnOldNeighbor();
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradientOld(const std::string & var_name,
                                                     unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledVectorNeighborGradientOld");
  const auto * var = getVectorVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnOldNeighbor() : var->gradSlnOlderNeighbor();
}

const VectorVariableGradient &
NeighborCoupleable::coupledVectorNeighborGradientOlder(const std::string & var_name,
                                                       unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledVectorNeighborGradientOlder");
  const auto * var = getVectorVar(var_name, comp);
  if (_c_is_implicit)
    return var->gradSlnOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}

const ArrayVariableValue &
NeighborCoupleable::coupledArrayNeighborValue(const std::string & var_name, unsigned int comp) const
{
  const auto * var = getArrayVar(var_name, comp);
  if (_neighbor_nodal)
    return (_c_is_implicit) ? var->dofValuesNeighbor() : var->dofValuesOldNeighbor();
  else
    return (_c_is_implicit) ? var->slnNeighbor() : var->slnOldNeighbor();
}

const ArrayVariableGradient &
NeighborCoupleable::coupledArrayNeighborGradient(const std::string & var_name,
                                                 unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  const auto * var = getArrayVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnNeighbor() : var->gradSlnOldNeighbor();
}

const ArrayVariableGradient &
NeighborCoupleable::coupledArrayNeighborGradientOld(const std::string & var_name,
                                                    unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledArrayNeighborGradientOld");
  const auto * var = getArrayVar(var_name, comp);
  return (_c_is_implicit) ? var->gradSlnOldNeighbor() : var->gradSlnOlderNeighbor();
}

const ArrayVariableGradient &
NeighborCoupleable::coupledArrayNeighborGradientOlder(const std::string & var_name,
                                                      unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Gradients are non-sensical with nodal compute objects");

  validateExecutionerType(var_name, "coupledArrayNeighborGradientOlder");
  const auto * var = getArrayVar(var_name, comp);
  if (_c_is_implicit)
    return var->gradSlnOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}

const VariableSecond &
NeighborCoupleable::coupledNeighborSecond(const std::string & var_name, unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("Nodal variables do not have second derivatives");

  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->secondSlnNeighbor() : var->secondSlnOldNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborDofValues(const std::string & var_name, unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("nodal objects should not call coupledDofValues");

  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->dofValuesNeighbor() : var->dofValuesOldNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborDofValuesOld(const std::string & var_name,
                                                unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("nodal objects should not call coupledDofValuesOld");

  validateExecutionerType(var_name, "coupledNeighborDofValuesOld");
  const auto * var = getVar(var_name, comp);
  return (_c_is_implicit) ? var->dofValuesOldNeighbor() : var->dofValuesOlderNeighbor();
}

const VariableValue &
NeighborCoupleable::coupledNeighborDofValuesOlder(const std::string & var_name,
                                                  unsigned int comp) const
{
  if (_neighbor_nodal)
    mooseError("nodal objects should not call coupledDofValuesOlder");

  validateExecutionerType(var_name, "coupledNeighborDofValuesOlder");
  const auto * var = getVar(var_name, comp);
  if (_c_is_implicit)
    return var->dofValuesOlderNeighbor();
  else
    mooseError("Older values not available for explicit schemes");
}
<|endoftext|>


<commit_before>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2011 New Dream Network
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "common/simple_spin.h"

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>

void simple_spin_lock(simple_spinlock_t *lock)
{
  static uint32_t bar = 13;
  static uint32_t *foo = &bar;

  while(1) {
    __sync_synchronize();
    uint32_t oldval = *lock;
    if (oldval == 0) {
      if (__sync_bool_compare_and_swap(lock, 0, 1))
	return;
    }
    // delay
    for (int i = 0; i < 100000; i++) {
      *foo = (*foo * 33) + 17;
    }
  }
}

void simple_spin_unlock(simple_spinlock_t *lock)
{
  __sync_bool_compare_and_swap(lock, 1, 0);
}
<commit_msg>simple_spin: use file-scope global not function<commit_after>// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2011 New Dream Network
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software
 * Foundation.  See file COPYING.
 *
 */

#include "common/simple_spin.h"

#include <stdio.h>
#include <stdint.h>
#include <pthread.h>

static uint32_t bar = 13;
static uint32_t *foo = &bar;

void simple_spin_lock(simple_spinlock_t *lock)
{
  while(1) {
    __sync_synchronize();
    uint32_t oldval = *lock;
    if (oldval == 0) {
      if (__sync_bool_compare_and_swap(lock, 0, 1))
	return;
    }
    // delay
    for (int i = 0; i < 100000; i++) {
      *foo = (*foo * 33) + 17;
    }
  }
}

void simple_spin_unlock(simple_spinlock_t *lock)
{
  __sync_bool_compare_and_swap(lock, 1, 0);
}
<|endoftext|>


<commit_before>// win32_handmade.cpp
// compiles with -doc -FC -Zi win32_handmade.cpp user32.lib gdi32.lib
// see: build.bat for switches used in compilation
/* ========================================================================
$File: $
$Date: $
$Revision: 0.1.d4.b(build#) $
$Creator: Sebastian Meier zu Biesen $
$Notice: (C) Copyright 2000-2016 by Joker Solutions, All Rights Reserved. $
======================================================================== */

#include <Windows.h>
#include <stdint.h>
#include "win32_handmade.h"

global_variable bool Running;
global_variable bool Debug = 0;
global_variable BITMAPINFO BitmapInfo;
global_variable void *BitmapMemory;

global_variable int BytesPerPixel = 4;
global_variable int BitmapWidth;
global_variable int BitmapHeight;

internal void Win32RenderGradient(int XOffset, int YOffset) {
	int Pitch = BitmapWidth*BytesPerPixel;
	uint8 *Row = (uint8 *)BitmapMemory;
	for (int Y = 0; Y < BitmapHeight; ++Y) {
		uint32 *Pixel = (uint32 *)Row;
		for (int X = 0; X < BitmapWidth; ++X) {
			uint8 Blue = (X + XOffset);
			uint8 Green = (Y + YOffset);
			uint8 Red = (X + XOffset);
			*Pixel++ = ((Red << 16) | (Green << 8) | (Blue));
		}
		Row += Pitch;
	}
}

internal void Win32ResizeDIBSection(int Width, int Height) {
	if (BitmapMemory) {
		VirtualFree(BitmapMemory,0,MEM_RELEASE);
	}
	BitmapWidth = Width;
	BitmapHeight = Height;
	BitmapInfo.bmiHeader.biSize = sizeof(BitmapInfo.bmiHeader);
	BitmapInfo.bmiHeader.biWidth = BitmapWidth;
	BitmapInfo.bmiHeader.biHeight = -BitmapHeight;
	BitmapInfo.bmiHeader.biPlanes = 1;
	BitmapInfo.bmiHeader.biBitCount = 32;
	BitmapInfo.bmiHeader.biCompression = BI_RGB;

	int BitmapMemorySize = (BitmapWidth*BitmapHeight)*BytesPerPixel;
	BitmapMemory = VirtualAlloc(0, BitmapMemorySize, MEM_COMMIT, PAGE_READWRITE);
}

internal void Win32UpdateWindow(HDC DeviceContext, RECT *WindowRect, int X, int Y, int Width, int Height) {
	int WindowWidth = WindowRect->right - WindowRect->left;
	int WindowHeight = WindowRect->bottom - WindowRect->top;
	StretchDIBits(DeviceContext, 0, 0, BitmapWidth, BitmapHeight, 0, 0, WindowWidth, WindowHeight, BitmapMemory, &BitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}

LRESULT CALLBACK Win32MainWindowCallback(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
	LRESULT Result = 0;
	switch (Message) {
		case WM_SIZE:
		{
			RECT WindowRect;
			GetClientRect(Window,&WindowRect);
			int Width = WindowRect.right - WindowRect.left;
			int Height = WindowRect.bottom - WindowRect.top;
			Win32ResizeDIBSection(Width, Height);
			if (Debug) { OutputDebugStringA("WM_SIZE\n"); }
		} break;
		case WM_DESTROY:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_DESTROY\n"); }
		} break;
		case WM_CLOSE:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_CLOSE\n"); }
		} break;
		case WM_QUIT:
		{
			if (Debug) { OutputDebugStringA("WM_QUIT\n"); }
		} break;
		case WM_ACTIVATEAPP:
		{
			if (Debug) { OutputDebugStringA("WM_ACTIVATEAPP\n"); }
		} break;
		case WM_PAINT:
		{
			PAINTSTRUCT Paint;
			HDC DeviceContext = BeginPaint(Window, &Paint);
			int X = Paint.rcPaint.left;
			int Y = Paint.rcPaint.top;
			int Width = Paint.rcPaint.right - Paint.rcPaint.left;
			int Height = Paint.rcPaint.bottom - Paint.rcPaint.top;
			RECT WindowRect;
			GetClientRect(Window, &WindowRect);
			Win32UpdateWindow(DeviceContext, &WindowRect, X, Y, Width, Height);
			EndPaint(Window,&Paint);
			if (Debug) { OutputDebugStringA("WM_PAINT\n"); }
		} break;
		default:
		{
			Result = DefWindowProc(Window,Message,WParam,LParam);
			//OutputDebugStringA("default\n");
		} break;
	}

	return(Result);
}

int CALLBACK WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR CommandLine, int ShowCode) {
	WNDCLASS WindowClass = {};
	WindowClass.style = CS_HREDRAW|CS_VREDRAW|CS_OWNDC;
	WindowClass.lpfnWndProc = Win32MainWindowCallback;
	WindowClass.hInstance = Instance;
	//WindowClass.hIcon = ;
	//WindowClass.hCursor = ;
	WindowClass.lpszClassName = "hmhWindowClass";
	if (RegisterClass(&WindowClass))
	{
		HWND WindowHandle = CreateWindowEx(
			0,
			WindowClass.lpszClassName,
			"Handmade Hero v0.1",
			WS_OVERLAPPEDWINDOW|WS_VISIBLE,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			0,
			0,
			Instance,
			0);
		if (WindowHandle)
		{
			int XOffset = 0;
			int YOffset = 0;
			Running = true;
			while(Running)
			{
				MSG Message;
				while (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
					if (Message.message == WM_QUIT) {
						Running = false;
					}
					TranslateMessage(&Message);
					DispatchMessage(&Message);
				}
				Win32RenderGradient(XOffset, YOffset);

				HDC DeviceContext = GetDC(WindowHandle);
				RECT WindowRect;
				GetClientRect(WindowHandle, &WindowRect);
				int WindowWidth = WindowRect.right - WindowRect.left;
				int WindowHeight = WindowRect.bottom - WindowRect.top;
				Win32UpdateWindow(DeviceContext,&WindowRect,0,0,WindowWidth,WindowHeight);
				ReleaseDC(WindowHandle, DeviceContext);
				++XOffset;
			}

		}
		else
		{
			//TODO(smzb): Log this event
		}
	}
	else {
		//TODO(smzb): log this event
	}
	if (Debug) { MessageBox(0, "This is Handmade Hero", "Handmade Hero v0.1", MB_OK | MB_ICONINFORMATION); }
	return 0;
}
<commit_msg>moved Bitmap related global vars into their own struct + some code cleanup<commit_after>// win32_handmade.cpp
// compiles with -doc -FC -Zi win32_handmade.cpp user32.lib gdi32.lib
// see: build.bat for switches used in compilation
/* ========================================================================
$File: $
$Date: $
$Revision: 0.1.d4.b(build#) $
$Creator: Sebastian Meier zu Biesen $
$Notice: (C) Copyright 2000-2016 by Joker Solutions, All Rights Reserved. $
======================================================================== */

#include <Windows.h>
#include <stdint.h>
#include "win32_handmade.h"

struct win32_offscreen_buffer {
	BITMAPINFO Info;
	void *Memory;
	int BytesPerPixel = 4;
	int Width;
	int Height;
	int Pitch;
};

global_variable bool Running;
global_variable bool Debug = 0;
global_variable win32_offscreen_buffer GlobalBackBuffer;

internal void Win32RenderGradient(win32_offscreen_buffer Buffer, int XOffset, int YOffset) {
	uint8 *Row = (uint8 *)Buffer.Memory;
	for (int Y = 0; Y < Buffer.Height; ++Y) {
		uint32 *Pixel = (uint32 *)Row;
		for (int X = 0; X < Buffer.Width; ++X) {
			uint8 Blue = (X + XOffset);
			uint8 Green = (Y + YOffset);
			uint8 Red = (X + XOffset);
			*Pixel++ = ((Red << 16) | (Green << 8) | (Blue));
		}
		Row += Buffer.Pitch;
	}
}

internal void Win32ResizeDIBSection(win32_offscreen_buffer *Buffer, int Width, int Height) {
	if (Buffer->Memory) {
		VirtualFree(Buffer->Memory,0,MEM_RELEASE);
	}
	Buffer->Width = Width;
	Buffer->Height = Height;
	Buffer->Info.bmiHeader.biSize = sizeof(Buffer->Info.bmiHeader);
	Buffer->Info.bmiHeader.biWidth = Buffer->Width;
	Buffer->Info.bmiHeader.biHeight = -Buffer->Height;
	Buffer->Info.bmiHeader.biPlanes = 1;
	Buffer->Info.bmiHeader.biBitCount = 32;
	Buffer->Info.bmiHeader.biCompression = BI_RGB;

	int BitmapMemorySize = (Buffer->Width*Buffer->Height)*Buffer->BytesPerPixel;
	Buffer->Memory = VirtualAlloc(0, BitmapMemorySize, MEM_COMMIT, PAGE_READWRITE);
	Buffer->Pitch = Buffer->Width*Buffer->BytesPerPixel;
}

internal void Win32DisplayBufferInWindow(HDC DeviceContext, RECT WindowRect, win32_offscreen_buffer Buffer, int X, int Y, int Width, int Height) {
	int WindowWidth = WindowRect.right - WindowRect.left;
	int WindowHeight = WindowRect.bottom - WindowRect.top;
	StretchDIBits(DeviceContext, 0, 0, Buffer.Width, Buffer.Height, 0, 0, WindowWidth, WindowHeight, Buffer.Memory, &Buffer.Info, DIB_RGB_COLORS, SRCCOPY);
}

LRESULT CALLBACK Win32MainWindowCallback(HWND Window, UINT Message, WPARAM WParam, LPARAM LParam)
{
	LRESULT Result = 0;
	switch (Message) {
		case WM_SIZE:
		{
			RECT WindowRect;
			GetClientRect(Window,&WindowRect);
			int Width = WindowRect.right - WindowRect.left;
			int Height = WindowRect.bottom - WindowRect.top;
			Win32ResizeDIBSection(&GlobalBackBuffer, Width, Height);
			if (Debug) { OutputDebugStringA("WM_SIZE\n"); }
		} break;
		case WM_DESTROY:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_DESTROY\n"); }
		} break;
		case WM_CLOSE:
		{
			Running = false;
			if (Debug) { OutputDebugStringA("WM_CLOSE\n"); }
		} break;
		case WM_QUIT:
		{
			if (Debug) { OutputDebugStringA("WM_QUIT\n"); }
		} break;
		case WM_ACTIVATEAPP:
		{
			if (Debug) { OutputDebugStringA("WM_ACTIVATEAPP\n"); }
		} break;
		case WM_PAINT:
		{
			PAINTSTRUCT Paint;
			HDC DeviceContext = BeginPaint(Window, &Paint);
			int X = Paint.rcPaint.left;
			int Y = Paint.rcPaint.top;
			int Width = Paint.rcPaint.right - Paint.rcPaint.left;
			int Height = Paint.rcPaint.bottom - Paint.rcPaint.top;
			RECT WindowRect;
			GetClientRect(Window, &WindowRect);
			Win32DisplayBufferInWindow(DeviceContext, WindowRect, GlobalBackBuffer , X, Y, Width, Height);
			EndPaint(Window,&Paint);
			if (Debug) { OutputDebugStringA("WM_PAINT\n"); }
		} break;
		default:
		{
			Result = DefWindowProc(Window,Message,WParam,LParam);
			//OutputDebugStringA("default\n");
		} break;
	}

	return(Result);
}

int CALLBACK WinMain(HINSTANCE Instance, HINSTANCE hPrevInstance, LPSTR CommandLine, int ShowCode) {
	WNDCLASS WindowClass = {};
	WindowClass.style = CS_HREDRAW|CS_VREDRAW;
	WindowClass.lpfnWndProc = Win32MainWindowCallback;
	WindowClass.hInstance = Instance;
	//WindowClass.hIcon = ;
	//WindowClass.hCursor = ;
	WindowClass.lpszClassName = "hmhWindowClass";
	if (RegisterClass(&WindowClass))
	{
		HWND WindowHandle = CreateWindowEx(
			0,
			WindowClass.lpszClassName,
			"Handmade Hero v0.1",
			WS_OVERLAPPEDWINDOW|WS_VISIBLE,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			0,
			0,
			Instance,
			0);
		if (WindowHandle)
		{
			int XOffset = 0;
			int YOffset = 0;
			Running = true;
			while(Running)
			{
				MSG Message;
				while (PeekMessage(&Message, 0, 0, 0, PM_REMOVE)) {
					if (Message.message == WM_QUIT) {
						Running = false;
					}
					TranslateMessage(&Message);
					DispatchMessage(&Message);
				}
				Win32RenderGradient(GlobalBackBuffer, XOffset, YOffset);

				HDC DeviceContext = GetDC(WindowHandle);
				RECT WindowRect;
				GetClientRect(WindowHandle, &WindowRect);
				int WindowWidth = WindowRect.right - WindowRect.left;
				int WindowHeight = WindowRect.bottom - WindowRect.top;
				Win32DisplayBufferInWindow(DeviceContext, WindowRect, GlobalBackBuffer, 0, 0, WindowWidth, WindowHeight);
				ReleaseDC(WindowHandle, DeviceContext);
				++XOffset;
			}

		}
		else
		{
			//TODO(smzb): Log this event
		}
	}
	else {
		//TODO(smzb): log this event
	}
	if (Debug) { MessageBox(0, "This is Handmade Hero", "Handmade Hero v0.1", MB_OK | MB_ICONINFORMATION); }
	return 0;
}
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "cpprefactoringchanges.h"

using namespace CPlusPlus;
using namespace CppTools;
using namespace TextEditor;

CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot,
                                             CppModelManagerInterface *modelManager)
    : m_snapshot(snapshot)
    , m_modelManager(modelManager)
    , m_workingCopy(modelManager->workingCopy())
{
    Q_ASSERT(modelManager);
}

QStringList CppRefactoringChanges::apply()
{
    const QStringList changedFiles = TextEditor::RefactoringChanges::apply();
    m_modelManager->updateSourceFiles(changedFiles);
    return changedFiles;
}

Document::Ptr CppRefactoringChanges::parsedDocumentForFile(const QString &fileName) const
{
    Document::Ptr doc = m_snapshot.document(fileName);

    QString source;
    if (m_workingCopy.contains(fileName)) {
        QPair<QString, unsigned> workingCopy = m_workingCopy.get(fileName);
        if (doc && doc->editorRevision() == workingCopy.second)
            return doc;
        else
            source = workingCopy.first;
    } else {
        QFile file(fileName);
        if (! file.open(QFile::ReadOnly))
            return Document::Ptr();

        source = QTextStream(&file).readAll(); // ### FIXME read bytes, and remove the convert below
        file.close();
    }

    doc = m_snapshot.documentFromSource(source.toLatin1(), fileName);
    doc->check();
    return doc;
}
<commit_msg>Preprocess the source file.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "cpprefactoringchanges.h"

using namespace CPlusPlus;
using namespace CppTools;
using namespace TextEditor;

CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot,
                                             CppModelManagerInterface *modelManager)
    : m_snapshot(snapshot)
    , m_modelManager(modelManager)
    , m_workingCopy(modelManager->workingCopy())
{
    Q_ASSERT(modelManager);
}

QStringList CppRefactoringChanges::apply()
{
    const QStringList changedFiles = TextEditor::RefactoringChanges::apply();
    m_modelManager->updateSourceFiles(changedFiles);
    return changedFiles;
}

Document::Ptr CppRefactoringChanges::parsedDocumentForFile(const QString &fileName) const
{
    Document::Ptr doc = m_snapshot.document(fileName);

    QString source;
    if (m_workingCopy.contains(fileName)) {
        QPair<QString, unsigned> workingCopy = m_workingCopy.get(fileName);
        if (doc && doc->editorRevision() == workingCopy.second)
            return doc;
        else
            source = workingCopy.first;
    } else {
        QFile file(fileName);
        if (! file.open(QFile::ReadOnly))
            return Document::Ptr();

        source = QTextStream(&file).readAll(); // ### FIXME read bytes, and remove the convert below
        file.close();
    }

    const QByteArray contents = m_snapshot.preprocessedCode(source, fileName);
    doc = m_snapshot.documentFromSource(contents, fileName);
    doc->check();
    return doc;
}
<|endoftext|>


<commit_before>#define _POSIX_SOURCE

#include "afs.h"
#include "condor_common.h"
#include "condor_config.h"
#include "condor_debug.h"
#include "condor_constants.h"
#include "subproc.h"
#include <string.h>

static char *_FileName_ = __FILE__;     // Used by EXCEPT (see condor_debug.h)

AFS_Info::AFS_Info()
{
	char	*tmp;

	my_cell_name = 0;

		// find out if we're running AFS here
	if( (tmp=param("HAS_AFS")) == NULL ) {
		has_afs = FALSE;
		return;
	}
	if( tmp[0] == 't' || tmp[0] == 'T' ) {
		has_afs = TRUE;
	} else {
		free( tmp );	/* BUG FIXED : Ashish */
		has_afs = FALSE;
		return;
	}
	free( tmp );	/* BUG FIXED : Ashish */

		// get pathname for the "fs" program
	if( (tmp=param("FS_PATHNAME")) == NULL ) {
		EXCEPT( "FS_PATHNAME not defined" );
	}
	strcpy( fs_pathname, tmp );
	free( tmp );	 /* BUG FIXED : Ashish */

		// get pathname for the "vos" program
	if( (tmp=param("VOS_PATHNAME")) == NULL ) {
		EXCEPT( "VOS_PATHNAME not defined" );
	}
	strcpy( vos_pathname, tmp );
	free( tmp );	/* BUG FIXED : Ashish */

	my_cell_name = 0;
}

AFS_Info::~AFS_Info()
{
	delete [] my_cell_name;
}

void
AFS_Info::display()
{
	if( !has_afs ) {
		dprintf( D_ALWAYS, "This machine doesn't run AFS\n" );
		return;
	}
	dprintf( D_ALWAYS, "fs_pathname: \"%s\"\n", fs_pathname );
	dprintf( D_ALWAYS, "vos_pathname: \"%s\"\n", vos_pathname );
	if( my_cell_name ) {
		dprintf( D_ALWAYS, "my_cell_name: \"%s\"\n", my_cell_name );
	} else {
		dprintf( D_ALWAYS, "my_cell_name: \"%s\"\n", "(NULL)" );
	}
}

char *
AFS_Info::my_cell()
{
	char	*ptr;

	if( !my_cell_name ) {

			// find out what AFS cell we're in
		if( (ptr=find_my_cell()) == NULL ) {
			return NULL;
		}
		my_cell_name = new char[ strlen(ptr) + 1 ];
		strcpy( my_cell_name, ptr );
	}
	return my_cell_name;
}

/*
  Use the "fs wscell" command to find the AFS cell of this host.
*/
char *
AFS_Info::find_my_cell()
{
	char 	*answer;
	char	buf[_POSIX_PATH_MAX ];
	FILE	*fp;
	char	*ptr;
	SubProc	p( fs_pathname, "wscell", "r" );

	if( !has_afs ) {
		return NULL;
	}
	return p.parse_output( "belongs to cell", "'", "'" );
}

/*
  Use the "fs whichcell" command to find the AFS cell of the given pathname.
*/
char *
AFS_Info::which_cell( const char *path )
{
	char 	*answer;
	char	args[ _POSIX_PATH_MAX ];
	FILE	*fp;
	SubProc	*fs;

	if( !has_afs ) {
		return NULL;
	}

	sprintf( args, "whichcell %s", path );
	fs = new SubProc( fs_pathname, args, "r" );
	answer = fs->parse_output("in cell", "'", "'" );
	delete fs;
	return answer;
}

/*
  Use the "fs examine" command to find the AFS volume of the given pathname.
*/
char *
AFS_Info::which_vol( const char *path )
{
	char 	*answer;
	char	args[ _POSIX_PATH_MAX ];
	FILE	*fp;
	char	*ptr;
	SubProc	*fs;

	if( !has_afs ) {
		return NULL;
	}

	sprintf( args, "examine %s", path );
	fs = new SubProc( fs_pathname, args, "r" );
	answer = fs->parse_output( "Volume status", "named ", "\n" );
	delete fs;
	return answer;
}

char *
AFS_Info::which_srvr( const char *path )
{
	SubProc	*vos;
	char	*answer;
	char	args[ _POSIX_PATH_MAX ];
	char	*vol;

	if( !has_afs ) {
		return NULL;
	}

	vol = which_vol( path );

	sprintf( args, "examine %s", vol );
	vos = new SubProc( vos_pathname, args, "r" );
	answer = vos->parse_output( "   server", "server ", " partition" );
	delete vos;
	return answer;
}

/*
  The following routines provide a simple C interface to this class.
*/

static AFS_Info *MyInfo;

extern "C" {

char *
get_host_cell()
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}

	return MyInfo->my_cell();
}

char *get_file_cell( const char *pathname )
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}
	return MyInfo->which_cell( pathname );
}

char *get_file_vol( const char *pathname )
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}
	return MyInfo->which_vol( pathname );
}

char *get_file_srvr( const char *pathname )
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}
	return MyInfo->which_srvr( pathname );
}

} /* end of extern "C" */
<commit_msg>if file doesn't exist, check to see if directory is on AFS<commit_after>#define _POSIX_SOURCE

#include "afs.h"
#include "condor_common.h"
#include "condor_config.h"
#include "condor_debug.h"
#include "condor_constants.h"
#include "subproc.h"
#include <string.h>

static char *_FileName_ = __FILE__;     // Used by EXCEPT (see condor_debug.h)

AFS_Info::AFS_Info()
{
	char	*tmp;

	my_cell_name = 0;

		// find out if we're running AFS here
	if( (tmp=param("HAS_AFS")) == NULL ) {
		has_afs = FALSE;
		return;
	}
	if( tmp[0] == 't' || tmp[0] == 'T' ) {
		has_afs = TRUE;
	} else {
		free( tmp );	/* BUG FIXED : Ashish */
		has_afs = FALSE;
		return;
	}
	free( tmp );	/* BUG FIXED : Ashish */

		// get pathname for the "fs" program
	if( (tmp=param("FS_PATHNAME")) == NULL ) {
		EXCEPT( "FS_PATHNAME not defined" );
	}
	strcpy( fs_pathname, tmp );
	free( tmp );	 /* BUG FIXED : Ashish */

		// get pathname for the "vos" program
	if( (tmp=param("VOS_PATHNAME")) == NULL ) {
		EXCEPT( "VOS_PATHNAME not defined" );
	}
	strcpy( vos_pathname, tmp );
	free( tmp );	/* BUG FIXED : Ashish */

	my_cell_name = 0;
}

AFS_Info::~AFS_Info()
{
	delete [] my_cell_name;
}

void
AFS_Info::display()
{
	if( !has_afs ) {
		dprintf( D_ALWAYS, "This machine doesn't run AFS\n" );
		return;
	}
	dprintf( D_ALWAYS, "fs_pathname: \"%s\"\n", fs_pathname );
	dprintf( D_ALWAYS, "vos_pathname: \"%s\"\n", vos_pathname );
	if( my_cell_name ) {
		dprintf( D_ALWAYS, "my_cell_name: \"%s\"\n", my_cell_name );
	} else {
		dprintf( D_ALWAYS, "my_cell_name: \"%s\"\n", "(NULL)" );
	}
}

char *
AFS_Info::my_cell()
{
	char	*ptr;

	if( !my_cell_name ) {

			// find out what AFS cell we're in
		if( (ptr=find_my_cell()) == NULL ) {
			return NULL;
		}
		my_cell_name = new char[ strlen(ptr) + 1 ];
		strcpy( my_cell_name, ptr );
	}
	return my_cell_name;
}

/*
  Use the "fs wscell" command to find the AFS cell of this host.
*/
char *
AFS_Info::find_my_cell()
{
	char 	*answer;
	char	buf[_POSIX_PATH_MAX ];
	FILE	*fp;
	char	*ptr;
	SubProc	p( fs_pathname, "wscell", "r" );

	if( !has_afs ) {
		return NULL;
	}
	return p.parse_output( "belongs to cell", "'", "'" );
}

/*
  Use the "fs whichcell" command to find the AFS cell of the given pathname.
*/
char *
AFS_Info::which_cell( const char *path )
{
	char 	*answer;
	char	args[ _POSIX_PATH_MAX ];
	FILE	*fp;
	SubProc	*fs;

	if( !has_afs ) {
		return NULL;
	}

	sprintf( args, "whichcell %s", path );
	fs = new SubProc( fs_pathname, args, "r" );
	answer = fs->parse_output("in cell", "'", "'" );
	delete fs;

	// file might not be created yet; if answer is NULL, try to find
	// directory on AFS
	if (answer == NULL) {
		int i;
		for (i = strlen(args); i >= 0 && args[i] != '/'; i--);
		if (i >= 0) {
			args[i] = '\0';
			fs = new SubProc( fs_pathname, args, "r" );
			answer = fs->parse_output("in cell", "'", "'" );
			delete fs;
		}
	}

	return answer;
}

/*
  Use the "fs examine" command to find the AFS volume of the given pathname.
*/
char *
AFS_Info::which_vol( const char *path )
{
	char 	*answer;
	char	args[ _POSIX_PATH_MAX ];
	FILE	*fp;
	char	*ptr;
	SubProc	*fs;

	if( !has_afs ) {
		return NULL;
	}

	sprintf( args, "examine %s", path );
	fs = new SubProc( fs_pathname, args, "r" );
	answer = fs->parse_output( "Volume status", "named ", "\n" );
	delete fs;

	// file might not be created yet; if answer is NULL, try to find
	// directory on AFS
	if (answer == NULL) {
		int i;
		for (i = strlen(args); i >= 0 && args[i] != '/'; i--);
		if (i >= 0) {
			args[i] = '\0';
			fs = new SubProc( fs_pathname, args, "r" );
			answer = fs->parse_output("in cell", "'", "'" );
			delete fs;
		}
	}

	return answer;
}

char *
AFS_Info::which_srvr( const char *path )
{
	SubProc	*vos;
	char	*answer;
	char	args[ _POSIX_PATH_MAX ];
	char	*vol;

	if( !has_afs ) {
		return NULL;
	}

	vol = which_vol( path );

	sprintf( args, "examine %s", vol );
	vos = new SubProc( vos_pathname, args, "r" );
	answer = vos->parse_output( "   server", "server ", " partition" );
	delete vos;
	return answer;
}

/*
  The following routines provide a simple C interface to this class.
*/

static AFS_Info *MyInfo;

extern "C" {

char *
get_host_cell()
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}

	return MyInfo->my_cell();
}

char *get_file_cell( const char *pathname )
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}
	return MyInfo->which_cell( pathname );
}

char *get_file_vol( const char *pathname )
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}
	return MyInfo->which_vol( pathname );
}

char *get_file_srvr( const char *pathname )
{
	if( !MyInfo ) {
		MyInfo = new AFS_Info();
	}
	return MyInfo->which_srvr( pathname );
}

} /* end of extern "C" */
<|endoftext|>


<commit_before>#define LUMIX_NO_CUSTOM_CRT

#include "../model.h"
#include "../renderer.h"
#include "../render_scene.h"
#include "editor/studio_app.h"
#include "editor/world_editor.h"
#include "engine/core.h"
#include "engine/engine.h"
#include "engine/universe.h"
#include "imgui/imgui.h"
#include "spline_geometry_plugin.h"

namespace Lumix {

static const ComponentType SPLINE_GEOMETRY_TYPE = reflection::getComponentType("spline_geometry");
static const ComponentType SPLINE_TYPE = reflection::getComponentType("spline");

struct SplineIterator {
	SplineIterator(Span<const Vec3> points) : points(points) {}

	void move(float delta) { t += delta; }
	bool isEnd() { return u32(t) >= points.length() - 2; }
	Vec3 getDir() {
		const u32 segment = u32(t);
		float rel_t = t - segment;
		Vec3 p0 = points[segment + 0];
		Vec3 p1 = points[segment + 1];
		Vec3 p2 = points[segment + 2];
		return lerp(p1 - p0, p2 - p1, rel_t);
	}

	Vec3 getPosition() {
		const u32 segment = u32(t);
		float rel_t = t - segment;
		Vec3 p0 = points[segment + 0];
		Vec3 p1 = points[segment + 1];
		Vec3 p2 = points[segment + 2];
		p0 = (p1 + p0) * 0.5f;
		p2 = (p1 + p2) * 0.5f;

		return lerp(lerp(p0, p1, rel_t), lerp(p1, p2, rel_t), rel_t);
	}

	float t = 0;

	Span<const Vec3> points;
};

SplineGeometryPlugin::SplineGeometryPlugin(StudioApp& app)
	: m_app(app)
{}

void SplineGeometryPlugin::paint(const DVec3& pos, const Universe& universe, EntityRef entity, ProceduralGeometry& pg, Renderer& renderer) const {
	if (pg.vertex_data.size() == 0) return;

	// TODO undo/redo

	const Transform tr = universe.getTransform(entity);
	const Vec3 center(tr.inverted().transform(pos));

	const float R2 = m_brush_size * m_brush_size;

	const u8* end = pg.vertex_data.data() + pg.vertex_data.size();
	const u32 stride = pg.vertex_decl.getStride();
	ASSERT(stride != 0);
	const u32 offset = 20 + m_brush_channel; // TODO
	for (u8* iter = pg.vertex_data.getMutableData(); iter < end; iter += stride) {
		Vec3 p;
		memcpy(&p, iter, sizeof(p));

		if (squaredLength(p - center) < R2) {
			*(iter + offset) = m_brush_value;
		}
	}

	if (pg.vertex_buffer) renderer.destroy(pg.vertex_buffer);
	const Renderer::MemRef mem = renderer.copy(pg.vertex_data.data(), (u32)pg.vertex_data.size());
	pg.vertex_buffer = renderer.createBuffer(mem, gpu::BufferFlags::IMMUTABLE);
}

bool SplineGeometryPlugin::paint(UniverseView& view, i32 x, i32 y) {
	WorldEditor& editor = view.getEditor();
	const Array<EntityRef>& selected = editor.getSelectedEntities();
	if (selected.size() != 1) return false;

	const Universe& universe = *editor.getUniverse();
	const bool is_spline = universe.hasComponent(selected[0], SPLINE_GEOMETRY_TYPE);
	if (!is_spline) return false;

	RenderScene* scene = (RenderScene*)universe.getScene(SPLINE_GEOMETRY_TYPE);
	DVec3 origin;
	Vec3 dir;
	view.getViewport().getRay({(float)x, (float)y}, origin, dir);
	const RayCastModelHit hit = scene->castRayProceduralGeometry(origin, dir);
	if (!hit.is_hit) return false;
	if (hit.entity != selected[0]) return false;

	Renderer* renderer = (Renderer*)editor.getEngine().getPluginManager().getPlugin("renderer");
	ASSERT(renderer);

	ProceduralGeometry& pg = scene->getProceduralGeometry(selected[0]);
	paint(hit.origin + hit.t * hit.dir, universe, selected[0], pg, *renderer);

	return true;
}

bool SplineGeometryPlugin::onMouseDown(UniverseView& view, int x, int y) {
	return paint(view, x, y);
}

void SplineGeometryPlugin::onMouseUp(UniverseView& view, int x, int y, os::MouseButton button) {
}

void SplineGeometryPlugin::onMouseMove(UniverseView& view, int x, int y, int rel_x, int rel_y) {
	paint(view, x, y);
}

void SplineGeometryPlugin::drawCursor(WorldEditor& editor, EntityRef entity) const {
	const UniverseView& view = editor.getView();
	const Vec2 mp = view.getMousePos();
	Universe& universe = *editor.getUniverse();

	RenderScene* scene = static_cast<RenderScene*>(universe.getScene(SPLINE_GEOMETRY_TYPE));
	DVec3 origin;
	Vec3 dir;
	editor.getView().getViewport().getRay(mp, origin, dir);
	const RayCastModelHit hit = scene->castRayProceduralGeometry(origin, dir);

	if (hit.is_hit) {
		const DVec3 center = hit.origin + hit.dir * hit.t;
		drawCursor(editor, *scene, entity, center);
		return;
	}
}

void SplineGeometryPlugin::drawCursor(WorldEditor& editor, RenderScene& scene, EntityRef entity, const DVec3& center) const {
	UniverseView& view = editor.getView();
	addCircle(view, center, m_brush_size, Vec3(0, 1, 0), Color::GREEN);
	const ProceduralGeometry& pg = scene.getProceduralGeometry(entity);

	if (pg.vertex_data.size() == 0) return;

	const u8* data = pg.vertex_data.data();
	const u32 stride = pg.vertex_decl.getStride();

	const float R2 = m_brush_size * m_brush_size;

	const Transform tr = scene.getUniverse().getTransform(entity);
	const Vec3 center_local = Vec3(tr.inverted().transform(center));

	for (u32 i = 0, c = pg.getIndexCount(); i < c; ++i) {
		Vec3 p;
		memcpy(&p, data + stride * i, sizeof(p));
		if (squaredLength(center_local - p) < R2) {
			addCircle(view, tr.transform(p), 0.1f, Vec3(0, 1, 0), Color::BLUE);
		}
	}
}

void SplineGeometryPlugin::onGUI(PropertyGrid& grid, ComponentUID cmp, WorldEditor& editor) {
	if (cmp.type != SPLINE_GEOMETRY_TYPE) return;

	const EntityRef e = *cmp.entity;
	Universe& universe = cmp.scene->getUniverse();
	if (!universe.hasComponent(*cmp.entity, SPLINE_TYPE)) {
		ImGui::TextUnformatted("There's no spline component");
		if (ImGui::Button("Create spline component")) {
			editor.addComponent(Span(&e, 1), SPLINE_TYPE);
		}
	}
	else {
		RenderScene* render_scene = (RenderScene*)universe.getScene(SPLINE_GEOMETRY_TYPE);
		CoreScene* core_scene = (CoreScene*)universe.getScene(SPLINE_TYPE);
		const Spline& spline = core_scene->getSpline(e);
		const SplineGeometry& sg = render_scene->getSplineGeometry(e);
		const ProceduralGeometry& pg = render_scene->getProceduralGeometry(e);

		drawCursor(editor, *cmp.entity);

		ImGuiEx::Label("Triangles");
		ImGui::Text("%d", pg.index_data.size() / (pg.index_type == gpu::DataType::U16 ? 2 : 4) / 3);

		ImGuiEx::Label("Brush size");
		ImGui::DragFloat("##bs", &m_brush_size, 0.1f, 0, FLT_MAX);

		if (sg.num_user_channels > 1) {
			ImGuiEx::Label("Paint channel");
			ImGui::SliderInt("##pc", (int*)&m_brush_channel, 0, sg.num_user_channels - 1);
		}

		ImGuiEx::Label("Paint value");
		ImGui::SliderInt("##pv", (int*)&m_brush_value, 0, 255);

		if (ImGui::Button("Generate geometry")) {
			if (!spline.points.empty()) {
				const float width = sg.width;
				SplineIterator iterator(spline.points);
				gpu::VertexDecl decl;
				decl.addAttribute(0, 0, 3, gpu::AttributeType::FLOAT, 0);

				OutputMemoryStream vertices(m_app.getAllocator());
				OutputMemoryStream indices(m_app.getAllocator());
				vertices.reserve(16 * 1024);
				if (sg.flags.isSet(SplineGeometry::HAS_UVS)) {
					decl.addAttribute(1, 12, 2, gpu::AttributeType::FLOAT, 0);
					struct Vertex {
						Vec3 position;
						Vec2 uv;
					};

					auto write_vertex = [&](const Vertex& v){
						vertices.write(v);
						if (sg.num_user_channels > 0) {
							u32 tmp = 0;
							vertices.write(&tmp, sg.num_user_channels);
						}
					};

					float u = 0;
					u32 rows = 0;
					Vec3 prev_p = spline.points[0];
					const u32 u_density = sg.u_density;
					while (!iterator.isEnd()) {
						++rows;
						const Vec3 p = iterator.getPosition();
						const Vec3 dir = iterator.getDir();
						const Vec3 side = normalize(cross(Vec3(0, 1, 0), dir)) * width;
						u += length(p - prev_p);

						const Vec3 p0 = p - side;
						for (u32 i = 0; i < u_density; ++i) {

							Vertex v;
							v.position = p0 + 2 * side * (i / float(u_density - 1));
							v.uv.x = u;
							v.uv.y = i / float(u_density - 1) * width;

							write_vertex(v);
						}

						iterator.move(sg.v_density);
						prev_p = p;
					}

					for (u32 row = 0; row < rows - 1; ++row) {
						for (u32 i = 0; i < u_density - 1; ++i) {
							indices.write(u16(u_density * row + i));
							indices.write(u16(u_density * row + i + 1));
							indices.write(u16(u_density * (row + 1) + i));

							indices.write(u16(u_density * row + i + 1));
							indices.write(u16(u_density * (row + 1) + i));
							indices.write(u16(u_density * (row + 1) + i + 1));
						}
					}

					if (sg.num_user_channels > 0) {
						decl.addAttribute(2, 20, sg.num_user_channels, gpu::AttributeType::U8, gpu::Attribute::NORMALIZED);
					}
				}
				else {
					while (!iterator.isEnd()) {
						const Vec3 p = iterator.getPosition();
						const Vec3 dir = iterator.getDir();
						const Vec3 side = normalize(cross(Vec3(0, 1, 0), dir)) * width;
						const Vec3 v0 = p + side;
						const Vec3 v1 = p - side;
						vertices.write(v0);
						if (sg.num_user_channels > 0) {
							u32 tmp = 0;
							vertices.write(&tmp, sg.num_user_channels);
						}
						vertices.write(v1);
						if (sg.num_user_channels > 0) {
							u32 tmp = 0;
							vertices.write(&tmp, sg.num_user_channels);
						}
						iterator.move(0.1f);
					}
					if (sg.num_user_channels > 0) {
						decl.addAttribute(1, 12, sg.num_user_channels, gpu::AttributeType::U8, gpu::Attribute::NORMALIZED);
					}
				}

				render_scene->setProceduralGeometry(e, vertices, decl, gpu::PrimitiveType::TRIANGLES, indices, gpu::DataType::U16);
			}
		}
	}
}

} // namespace Lumix<commit_msg>fixed linux build<commit_after>#define LUMIX_NO_CUSTOM_CRT

#include "../model.h"
#include "../renderer.h"
#include "../render_scene.h"
#include "editor/studio_app.h"
#include "editor/world_editor.h"
#include "engine/core.h"
#include "engine/engine.h"
#include "engine/universe.h"
#include "imgui/imgui.h"
#include "spline_geometry_plugin.h"

namespace Lumix {

static const ComponentType SPLINE_GEOMETRY_TYPE = reflection::getComponentType("spline_geometry");
static const ComponentType SPLINE_TYPE = reflection::getComponentType("spline");

struct SplineIterator {
	SplineIterator(Span<const Vec3> points) : points(points) {}

	void move(float delta) { t += delta; }
	bool isEnd() { return u32(t) >= points.length() - 2; }
	Vec3 getDir() {
		const u32 segment = u32(t);
		float rel_t = t - segment;
		Vec3 p0 = points[segment + 0];
		Vec3 p1 = points[segment + 1];
		Vec3 p2 = points[segment + 2];
		return lerp(p1 - p0, p2 - p1, rel_t);
	}

	Vec3 getPosition() {
		const u32 segment = u32(t);
		float rel_t = t - segment;
		Vec3 p0 = points[segment + 0];
		Vec3 p1 = points[segment + 1];
		Vec3 p2 = points[segment + 2];
		p0 = (p1 + p0) * 0.5f;
		p2 = (p1 + p2) * 0.5f;

		return lerp(lerp(p0, p1, rel_t), lerp(p1, p2, rel_t), rel_t);
	}

	float t = 0;

	Span<const Vec3> points;
};

SplineGeometryPlugin::SplineGeometryPlugin(StudioApp& app)
	: m_app(app)
{}

void SplineGeometryPlugin::paint(const DVec3& pos, const Universe& universe, EntityRef entity, ProceduralGeometry& pg, Renderer& renderer) const {
	if (pg.vertex_data.size() == 0) return;

	// TODO undo/redo

	const Transform tr = universe.getTransform(entity);
	const Vec3 center(tr.inverted().transform(pos));

	const float R2 = m_brush_size * m_brush_size;

	const u8* end = pg.vertex_data.data() + pg.vertex_data.size();
	const u32 stride = pg.vertex_decl.getStride();
	ASSERT(stride != 0);
	const u32 offset = 20 + m_brush_channel; // TODO
	for (u8* iter = pg.vertex_data.getMutableData(); iter < end; iter += stride) {
		Vec3 p;
		memcpy(&p, iter, sizeof(p));

		if (squaredLength(p - center) < R2) {
			*(iter + offset) = m_brush_value;
		}
	}

	if (pg.vertex_buffer) renderer.destroy(pg.vertex_buffer);
	const Renderer::MemRef mem = renderer.copy(pg.vertex_data.data(), (u32)pg.vertex_data.size());
	pg.vertex_buffer = renderer.createBuffer(mem, gpu::BufferFlags::IMMUTABLE);
}

bool SplineGeometryPlugin::paint(UniverseView& view, i32 x, i32 y) {
	WorldEditor& editor = view.getEditor();
	const Array<EntityRef>& selected = editor.getSelectedEntities();
	if (selected.size() != 1) return false;

	const Universe& universe = *editor.getUniverse();
	const bool is_spline = universe.hasComponent(selected[0], SPLINE_GEOMETRY_TYPE);
	if (!is_spline) return false;

	RenderScene* scene = (RenderScene*)universe.getScene(SPLINE_GEOMETRY_TYPE);
	DVec3 origin;
	Vec3 dir;
	view.getViewport().getRay({(float)x, (float)y}, origin, dir);
	const RayCastModelHit hit = scene->castRayProceduralGeometry(origin, dir);
	if (!hit.is_hit) return false;
	if (hit.entity != selected[0]) return false;

	Renderer* renderer = (Renderer*)editor.getEngine().getPluginManager().getPlugin("renderer");
	ASSERT(renderer);

	ProceduralGeometry& pg = scene->getProceduralGeometry(selected[0]);
	paint(hit.origin + hit.t * hit.dir, universe, selected[0], pg, *renderer);

	return true;
}

bool SplineGeometryPlugin::onMouseDown(UniverseView& view, int x, int y) {
	return paint(view, x, y);
}

void SplineGeometryPlugin::onMouseUp(UniverseView& view, int x, int y, os::MouseButton button) {
}

void SplineGeometryPlugin::onMouseMove(UniverseView& view, int x, int y, int rel_x, int rel_y) {
	paint(view, x, y);
}

void SplineGeometryPlugin::drawCursor(WorldEditor& editor, EntityRef entity) const {
	const UniverseView& view = editor.getView();
	const Vec2 mp = view.getMousePos();
	Universe& universe = *editor.getUniverse();

	RenderScene* scene = static_cast<RenderScene*>(universe.getScene(SPLINE_GEOMETRY_TYPE));
	DVec3 origin;
	Vec3 dir;
	editor.getView().getViewport().getRay(mp, origin, dir);
	const RayCastModelHit hit = scene->castRayProceduralGeometry(origin, dir);

	if (hit.is_hit) {
		const DVec3 center = hit.origin + hit.dir * hit.t;
		drawCursor(editor, *scene, entity, center);
		return;
	}
}

void SplineGeometryPlugin::drawCursor(WorldEditor& editor, RenderScene& scene, EntityRef entity, const DVec3& center) const {
	UniverseView& view = editor.getView();
	addCircle(view, center, m_brush_size, Vec3(0, 1, 0), Color::GREEN);
	const ProceduralGeometry& pg = scene.getProceduralGeometry(entity);

	if (pg.vertex_data.size() == 0) return;

	const u8* data = pg.vertex_data.data();
	const u32 stride = pg.vertex_decl.getStride();

	const float R2 = m_brush_size * m_brush_size;

	const Transform tr = scene.getUniverse().getTransform(entity);
	const Vec3 center_local = Vec3(tr.inverted().transform(center));

	for (u32 i = 0, c = pg.getIndexCount(); i < c; ++i) {
		Vec3 p;
		memcpy(&p, data + stride * i, sizeof(p));
		if (squaredLength(center_local - p) < R2) {
			addCircle(view, tr.transform(p), 0.1f, Vec3(0, 1, 0), Color::BLUE);
		}
	}
}

void SplineGeometryPlugin::onGUI(PropertyGrid& grid, ComponentUID cmp, WorldEditor& editor) {
	if (cmp.type != SPLINE_GEOMETRY_TYPE) return;

	const EntityRef e = *cmp.entity;
	Universe& universe = cmp.scene->getUniverse();
	if (!universe.hasComponent(*cmp.entity, SPLINE_TYPE)) {
		ImGui::TextUnformatted("There's no spline component");
		if (ImGui::Button("Create spline component")) {
			editor.addComponent(Span(&e, 1), SPLINE_TYPE);
		}
	}
	else {
		RenderScene* render_scene = (RenderScene*)universe.getScene(SPLINE_GEOMETRY_TYPE);
		CoreScene* core_scene = (CoreScene*)universe.getScene(SPLINE_TYPE);
		const Spline& spline = core_scene->getSpline(e);
		const SplineGeometry& sg = render_scene->getSplineGeometry(e);
		const ProceduralGeometry& pg = render_scene->getProceduralGeometry(e);

		drawCursor(editor, *cmp.entity);

		ImGuiEx::Label("Triangles");
		ImGui::Text("%d", u32(pg.index_data.size() / (pg.index_type == gpu::DataType::U16 ? 2 : 4) / 3));

		ImGuiEx::Label("Brush size");
		ImGui::DragFloat("##bs", &m_brush_size, 0.1f, 0, FLT_MAX);

		if (sg.num_user_channels > 1) {
			ImGuiEx::Label("Paint channel");
			ImGui::SliderInt("##pc", (int*)&m_brush_channel, 0, sg.num_user_channels - 1);
		}

		ImGuiEx::Label("Paint value");
		ImGui::SliderInt("##pv", (int*)&m_brush_value, 0, 255);

		if (ImGui::Button("Generate geometry")) {
			if (!spline.points.empty()) {
				const float width = sg.width;
				SplineIterator iterator(spline.points);
				gpu::VertexDecl decl;
				decl.addAttribute(0, 0, 3, gpu::AttributeType::FLOAT, 0);

				OutputMemoryStream vertices(m_app.getAllocator());
				OutputMemoryStream indices(m_app.getAllocator());
				vertices.reserve(16 * 1024);
				if (sg.flags.isSet(SplineGeometry::HAS_UVS)) {
					decl.addAttribute(1, 12, 2, gpu::AttributeType::FLOAT, 0);
					struct Vertex {
						Vec3 position;
						Vec2 uv;
					};

					auto write_vertex = [&](const Vertex& v){
						vertices.write(v);
						if (sg.num_user_channels > 0) {
							u32 tmp = 0;
							vertices.write(&tmp, sg.num_user_channels);
						}
					};

					float u = 0;
					u32 rows = 0;
					Vec3 prev_p = spline.points[0];
					const u32 u_density = sg.u_density;
					while (!iterator.isEnd()) {
						++rows;
						const Vec3 p = iterator.getPosition();
						const Vec3 dir = iterator.getDir();
						const Vec3 side = normalize(cross(Vec3(0, 1, 0), dir)) * width;
						u += length(p - prev_p);

						const Vec3 p0 = p - side;
						for (u32 i = 0; i < u_density; ++i) {

							Vertex v;
							v.position = p0 + 2 * side * (i / float(u_density - 1));
							v.uv.x = u;
							v.uv.y = i / float(u_density - 1) * width;

							write_vertex(v);
						}

						iterator.move(sg.v_density);
						prev_p = p;
					}

					for (u32 row = 0; row < rows - 1; ++row) {
						for (u32 i = 0; i < u_density - 1; ++i) {
							indices.write(u16(u_density * row + i));
							indices.write(u16(u_density * row + i + 1));
							indices.write(u16(u_density * (row + 1) + i));

							indices.write(u16(u_density * row + i + 1));
							indices.write(u16(u_density * (row + 1) + i));
							indices.write(u16(u_density * (row + 1) + i + 1));
						}
					}

					if (sg.num_user_channels > 0) {
						decl.addAttribute(2, 20, sg.num_user_channels, gpu::AttributeType::U8, gpu::Attribute::NORMALIZED);
					}
				}
				else {
					while (!iterator.isEnd()) {
						const Vec3 p = iterator.getPosition();
						const Vec3 dir = iterator.getDir();
						const Vec3 side = normalize(cross(Vec3(0, 1, 0), dir)) * width;
						const Vec3 v0 = p + side;
						const Vec3 v1 = p - side;
						vertices.write(v0);
						if (sg.num_user_channels > 0) {
							u32 tmp = 0;
							vertices.write(&tmp, sg.num_user_channels);
						}
						vertices.write(v1);
						if (sg.num_user_channels > 0) {
							u32 tmp = 0;
							vertices.write(&tmp, sg.num_user_channels);
						}
						iterator.move(0.1f);
					}
					if (sg.num_user_channels > 0) {
						decl.addAttribute(1, 12, sg.num_user_channels, gpu::AttributeType::U8, gpu::Attribute::NORMALIZED);
					}
				}

				render_scene->setProceduralGeometry(e, vertices, decl, gpu::PrimitiveType::TRIANGLES, indices, gpu::DataType::U16);
			}
		}
	}
}

} // namespace Lumix<|endoftext|>