<commit_before>///
/// @file   primecount-internal.hpp
/// @brief  primecount internal function definitions.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMECOUNT_INTERNAL_HPP
#define PRIMECOUNT_INTERNAL_HPP

#include <inttypes.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>

#include <stdint.h>
#include <algorithm>
#include <string>
#include <vector>

namespace primecount {

enum {
  /// Uses all CPU cores.
  MAX_THREADS = -1
};

class PhiCache;

std::string pi(const std::string& x, int threads);

int64_t pi(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi(int128_t x);

int128_t pi(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat(int128_t x);

int128_t pi_deleglise_rivat(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat1(int64_t x);

int64_t pi_deleglise_rivat2(int64_t x);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat3(int128_t x);

#endif

int64_t pi_deleglise_rivat_parallel1(int64_t x, int threads);

int64_t pi_deleglise_rivat_parallel2(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat_parallel3(int128_t x, int threads);

#endif

int64_t pi_legendre(int64_t x, int threads);

int64_t pi_lehmer(int64_t x, int threads);

int64_t pi_lehmer2(int64_t x, int threads);

int64_t pi_lmo(int64_t x, int threads);

int64_t pi_lmo1(int64_t x);

int64_t pi_lmo2(int64_t x);

int64_t pi_lmo3(int64_t x);

int64_t pi_lmo4(int64_t x);

int64_t pi_lmo5(int64_t x);

int64_t pi_lmo_parallel1(int64_t x, int threads);

int64_t pi_lmo_parallel2(int64_t x, int threads);

int64_t pi_lmo_parallel3(int64_t x, int threads);

int64_t pi_meissel(int64_t x, int threads);

int64_t pi_primesieve(int64_t x, int threads);

int64_t phi(int64_t x, int64_t a, int threads);

int64_t phi(int64_t x, int64_t a, PhiCache* phiCache);

int64_t Li(int64_t);

int64_t Li_inverse(int64_t);

#ifdef HAVE_INT128_T

int128_t Li(int128_t);

int128_t Li_inverse(int128_t);

#endif

int64_t nth_prime(int64_t n, int threads);

int64_t P2(int64_t x, int64_t y, int threads);

#ifdef HAVE_INT128_T

int128_t P2(int128_t x, int64_t y, int threads);

#endif

int64_t P2_lehmer(int64_t x, int64_t a, int threads);

int64_t P3(int64_t x, int64_t a, int threads);

double get_wtime();

int validate_threads(int threads);

int validate_threads(int threads, int64_t sieve_limit, int64_t thread_threshold = 100000);

void print_result(const std::string& str, maxint_t res, double time);

void print_seconds(double seconds);

bool print_status();

maxint_t to_maxint(const std::string& expr);

template <typename T>
int get_percent(T low, T limit)
{
  int percent = (int) (100.0 * low / std::max<T>(1, limit));
  return in_between(0, percent, 100);
}

template <typename T>
T S2_approx(T x, int64_t pi_y, T P2, T S1)
{
  T pix = Li(x);
  T S2 = pix - S1 - pi_y + 1 + P2;
  return S2;
}

} // namespace primecount

#endif
<commit_msg>Fix template code<commit_after>///
/// @file   primecount-internal.hpp
/// @brief  primecount internal function definitions.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMECOUNT_INTERNAL_HPP
#define PRIMECOUNT_INTERNAL_HPP

#include <inttypes.hpp>
#include <aligned_vector.hpp>
#include <pmath.hpp>

#include <stdint.h>
#include <algorithm>
#include <string>
#include <vector>

namespace primecount {

enum {
  /// Uses all CPU cores.
  MAX_THREADS = -1
};

class PhiCache;

std::string pi(const std::string& x, int threads);

int64_t pi(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi(int128_t x);

int128_t pi(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat(int128_t x);

int128_t pi_deleglise_rivat(int128_t x, int threads);

#endif

int64_t pi_deleglise_rivat1(int64_t x);

int64_t pi_deleglise_rivat2(int64_t x);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat3(int128_t x);

#endif

int64_t pi_deleglise_rivat_parallel1(int64_t x, int threads);

int64_t pi_deleglise_rivat_parallel2(int64_t x, int threads);

#ifdef HAVE_INT128_T

int128_t pi_deleglise_rivat_parallel3(int128_t x, int threads);

#endif

int64_t pi_legendre(int64_t x, int threads);

int64_t pi_lehmer(int64_t x, int threads);

int64_t pi_lehmer2(int64_t x, int threads);

int64_t pi_lmo(int64_t x, int threads);

int64_t pi_lmo1(int64_t x);

int64_t pi_lmo2(int64_t x);

int64_t pi_lmo3(int64_t x);

int64_t pi_lmo4(int64_t x);

int64_t pi_lmo5(int64_t x);

int64_t pi_lmo_parallel1(int64_t x, int threads);

int64_t pi_lmo_parallel2(int64_t x, int threads);

int64_t pi_lmo_parallel3(int64_t x, int threads);

int64_t pi_meissel(int64_t x, int threads);

int64_t pi_primesieve(int64_t x, int threads);

int64_t phi(int64_t x, int64_t a, int threads);

int64_t phi(int64_t x, int64_t a, PhiCache* phiCache);

int64_t Li(int64_t);

int64_t Li_inverse(int64_t);

#ifdef HAVE_INT128_T

int128_t Li(int128_t);

int128_t Li_inverse(int128_t);

#endif

int64_t nth_prime(int64_t n, int threads);

int64_t P2(int64_t x, int64_t y, int threads);

#ifdef HAVE_INT128_T

int128_t P2(int128_t x, int64_t y, int threads);

#endif

int64_t P2_lehmer(int64_t x, int64_t a, int threads);

int64_t P3(int64_t x, int64_t a, int threads);

double get_wtime();

int validate_threads(int threads);

int validate_threads(int threads, int64_t sieve_limit, int64_t thread_threshold = 100000);

void print_result(const std::string& str, maxint_t res, double time);

void print_seconds(double seconds);

bool print_status();

maxint_t to_maxint(const std::string& expr);

template <typename T>
T get_percent(T low, T limit)
{
  T percent = (T) (100.0 * low / std::max<T>(1, limit));
  return in_between(0, percent, 100);
}

template <typename T>
T S2_approx(T x, int64_t pi_y, T P2, T S1)
{
  T pix = Li(x);
  T S2 = pix - S1 - pi_y + 1 + P2;
  return S2;
}

} // namespace primecount

#endif
<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 OWNER 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.
 *
 ****************************************************************************/

/**
 * @file airspeed_calibration.cpp
 * Airspeed sensor calibration routine
 */

#include "airspeed_calibration.h"
#include "calibration_messages.h"
#include "commander_helper.h"

#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
#include <math.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_airspeed.h>
#include <uORB/topics/sensor_combined.h>
#include <uORB/topics/differential_pressure.h>
#include <mavlink/mavlink_log.h>
#include <systemlib/param/param.h>
#include <systemlib/err.h>
#include <systemlib/airspeed.h>

/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
#endif
static const int ERROR = -1;

static const char *sensor_name = "dpress";

int do_airspeed_calibration(int mavlink_fd)
{
	/* give directions */
	mavlink_log_info(mavlink_fd, CAL_STARTED_MSG, sensor_name);

	const unsigned calibration_count = 2000;

	int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
	struct differential_pressure_s diff_pres;

	float diff_pres_offset = 0.0f;

	/* Reset sensor parameters */
	struct airspeed_scale airscale = {
		diff_pres_offset,
		1.0f,
	};

	bool paramreset_successful = false;
	int  fd = open(AIRSPEED_DEVICE_PATH, 0);

	if (fd > 0) {
		if (OK == ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
			paramreset_successful = true;

		} else {
			mavlink_log_critical(mavlink_fd, "airspeed offset zero failed");
		}

		close(fd);
	}

	if (!paramreset_successful) {
		warn("FAILED to reset - assuming analog");
		mavlink_log_critical(mavlink_fd, "If analog sens, retry with [SENS_DPRES_ANSC=1000]");

		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			mavlink_log_critical(mavlink_fd, CAL_FAILED_SET_PARAMS_MSG);
			close(diff_pres_sub);
			return ERROR;
		}
	}

	unsigned calibration_counter = 0;

	mavlink_log_critical(mavlink_fd, "Ensure sensor is not measuring wind");
	usleep(500 * 1000);

	while (calibration_counter < calibration_count) {

		/* wait blocking for new data */
		struct pollfd fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			diff_pres_offset += diff_pres.differential_pressure_raw_pa;
			calibration_counter++;

			if (calibration_counter % (calibration_count / 20) == 0) {
				mavlink_log_info(mavlink_fd, CAL_PROGRESS_MSG, sensor_name, (calibration_counter * 80) / calibration_count);
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			mavlink_log_critical(mavlink_fd, CAL_FAILED_MSG, sensor_name);
			close(diff_pres_sub);
			return ERROR;
		}
	}

	diff_pres_offset = diff_pres_offset / calibration_count;

	if (isfinite(diff_pres_offset)) {

		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			mavlink_log_critical(mavlink_fd, CAL_FAILED_SET_PARAMS_MSG);
			close(diff_pres_sub);
			return ERROR;
		}

		/* auto-save to EEPROM */
		int save_ret = param_save_default();

		if (save_ret != 0) {
			warn("WARNING: auto-save of params to storage failed");
			mavlink_log_critical(mavlink_fd, CAL_FAILED_SAVE_PARAMS_MSG);
			close(diff_pres_sub);
			return ERROR;
		}

	} else {
		mavlink_log_info(mavlink_fd, CAL_FAILED_MSG, sensor_name);
		close(diff_pres_sub);
		return ERROR;
	}

	/* wait 500 ms to ensure parameter propagated through the system */
	usleep(500 * 1000);

	calibration_counter = 0;

	/* just take a few samples and make sure pitot tubes are not reversed */
	while (calibration_counter < 300) {

		/* wait blocking for new data */
		struct pollfd fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			float calibrated_pa = diff_pres.differential_pressure_raw_pa - diff_pres_offset;

			if (fabsf(calibrated_pa) < 50.0f) {
				if (calibration_counter % 20 == 0) {
					mavlink_log_critical(mavlink_fd, "Create airflow on pitot (%d Pa, #h101)",
					(int)calibrated_pa);
				}
				usleep(100 * 1000);
				calibration_counter++;
				continue;
			}

			/* do not allow negative values */
			if (calibrated_pa < 0.0f) {
				mavlink_log_critical(mavlink_fd, "%d Pa: swap static vs dynamic ports,restart", (int)calibrated_pa);
				close(diff_pres_sub);

				/* the user setup is wrong, wipe the calibration to force a proper re-calibration */

				diff_pres_offset = 0.0f;
				if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
					mavlink_log_critical(mavlink_fd, CAL_FAILED_SET_PARAMS_MSG);
					close(diff_pres_sub);
					return ERROR;
				}

				/* save */
				(void)param_save_default();

				close(diff_pres_sub);
				return ERROR;
			} else {
				mavlink_log_info(mavlink_fd, "positive pressure: OK (%d Pa)",
					(int)calibrated_pa);
				break;
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			mavlink_log_critical(mavlink_fd, CAL_FAILED_MSG, sensor_name);
			close(diff_pres_sub);
			return ERROR;
		}
	}

	mavlink_log_info(mavlink_fd, CAL_PROGRESS_MSG, sensor_name, 100);

	mavlink_log_info(mavlink_fd, CAL_DONE_MSG, sensor_name);
	tune_neutral(true);
	close(diff_pres_sub);
	return OK;
}
<commit_msg>Fix calibration counter usage, take every sample<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 * 3. Neither the name PX4 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 OWNER 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.
 *
 ****************************************************************************/

/**
 * @file airspeed_calibration.cpp
 * Airspeed sensor calibration routine
 */

#include "airspeed_calibration.h"
#include "calibration_messages.h"
#include "commander_helper.h"

#include <stdio.h>
#include <fcntl.h>
#include <poll.h>
#include <math.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_airspeed.h>
#include <uORB/topics/sensor_combined.h>
#include <uORB/topics/differential_pressure.h>
#include <mavlink/mavlink_log.h>
#include <systemlib/param/param.h>
#include <systemlib/err.h>
#include <systemlib/airspeed.h>

/* oddly, ERROR is not defined for c++ */
#ifdef ERROR
# undef ERROR
#endif
static const int ERROR = -1;

static const char *sensor_name = "dpress";

int do_airspeed_calibration(int mavlink_fd)
{
	/* give directions */
	mavlink_log_info(mavlink_fd, CAL_STARTED_MSG, sensor_name);

	const unsigned calibration_count = 2000;

	int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
	struct differential_pressure_s diff_pres;

	float diff_pres_offset = 0.0f;

	/* Reset sensor parameters */
	struct airspeed_scale airscale = {
		diff_pres_offset,
		1.0f,
	};

	bool paramreset_successful = false;
	int  fd = open(AIRSPEED_DEVICE_PATH, 0);

	if (fd > 0) {
		if (OK == ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
			paramreset_successful = true;

		} else {
			mavlink_log_critical(mavlink_fd, "airspeed offset zero failed");
		}

		close(fd);
	}

	if (!paramreset_successful) {
		warn("FAILED to reset - assuming analog");
		mavlink_log_critical(mavlink_fd, "If analog sens, retry with [SENS_DPRES_ANSC=1000]");

		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			mavlink_log_critical(mavlink_fd, CAL_FAILED_SET_PARAMS_MSG);
			close(diff_pres_sub);
			return ERROR;
		}
	}

	unsigned calibration_counter = 0;

	mavlink_log_critical(mavlink_fd, "Ensure sensor is not measuring wind");
	usleep(500 * 1000);

	while (calibration_counter < calibration_count) {

		/* wait blocking for new data */
		struct pollfd fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			diff_pres_offset += diff_pres.differential_pressure_raw_pa;
			calibration_counter++;

			if (calibration_counter % (calibration_count / 20) == 0) {
				mavlink_log_info(mavlink_fd, CAL_PROGRESS_MSG, sensor_name, (calibration_counter * 80) / calibration_count);
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			mavlink_log_critical(mavlink_fd, CAL_FAILED_MSG, sensor_name);
			close(diff_pres_sub);
			return ERROR;
		}
	}

	diff_pres_offset = diff_pres_offset / calibration_count;

	if (isfinite(diff_pres_offset)) {

		if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
			mavlink_log_critical(mavlink_fd, CAL_FAILED_SET_PARAMS_MSG);
			close(diff_pres_sub);
			return ERROR;
		}

		/* auto-save to EEPROM */
		int save_ret = param_save_default();

		if (save_ret != 0) {
			warn("WARNING: auto-save of params to storage failed");
			mavlink_log_critical(mavlink_fd, CAL_FAILED_SAVE_PARAMS_MSG);
			close(diff_pres_sub);
			return ERROR;
		}

	} else {
		mavlink_log_info(mavlink_fd, CAL_FAILED_MSG, sensor_name);
		close(diff_pres_sub);
		return ERROR;
	}

	/* wait 500 ms to ensure parameter propagated through the system */
	usleep(500 * 1000);

	calibration_counter = 0;

	/* just take a few samples and make sure pitot tubes are not reversed, timeout after ~30 seconds */
	while (calibration_counter < 1500) {

		/* wait blocking for new data */
		struct pollfd fds[1];
		fds[0].fd = diff_pres_sub;
		fds[0].events = POLLIN;

		int poll_ret = poll(fds, 1, 1000);

		if (poll_ret) {
			orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);

			float calibrated_pa = diff_pres.differential_pressure_raw_pa - diff_pres_offset;
			calibration_counter++;

			if (fabsf(calibrated_pa) < 50.0f) {
				if (calibration_counter % 100 == 0) {
					mavlink_log_critical(mavlink_fd, "Create airflow on pitot (%d Pa, #h101)",
					(int)calibrated_pa);
				}
				continue;
			}

			/* do not allow negative values */
			if (calibrated_pa < 0.0f) {
				mavlink_log_critical(mavlink_fd, "%d Pa: swap static vs dynamic ports,restart", (int)calibrated_pa);
				close(diff_pres_sub);

				/* the user setup is wrong, wipe the calibration to force a proper re-calibration */

				diff_pres_offset = 0.0f;
				if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
					mavlink_log_critical(mavlink_fd, CAL_FAILED_SET_PARAMS_MSG);
					close(diff_pres_sub);
					return ERROR;
				}

				/* save */
				(void)param_save_default();

				close(diff_pres_sub);
				return ERROR;
			} else {
				mavlink_log_info(mavlink_fd, "positive pressure: OK (%d Pa)",
					(int)calibrated_pa);
				break;
			}

		} else if (poll_ret == 0) {
			/* any poll failure for 1s is a reason to abort */
			mavlink_log_critical(mavlink_fd, CAL_FAILED_MSG, sensor_name);
			close(diff_pres_sub);
			return ERROR;
		}
	}

	mavlink_log_info(mavlink_fd, CAL_PROGRESS_MSG, sensor_name, 100);

	mavlink_log_info(mavlink_fd, CAL_DONE_MSG, sensor_name);
	tune_neutral(true);
	close(diff_pres_sub);
	return OK;
}
<|endoftext|>


<commit_before>// Filename: INSStaggeredVelocityBcCoef.C
// Last modified: <03.Oct.2008 17:39:55 griffith@box230.cims.nyu.edu>
// Created on 22 Jul 2008 by Boyce Griffith (griffith@box230.cims.nyu.edu)

#include "INSStaggeredVelocityBcCoef.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

// IBTK INCLUDES
#include <ibtk/PhysicalBoundaryUtilities.h>

// SAMRAI INCLUDES
#include <CartesianPatchGeometry.h>
#include <CellData.h>
#include <SideData.h>
#include <tbox/Utilities.h>

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

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

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

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

INSStaggeredVelocityBcCoef::INSStaggeredVelocityBcCoef(
    const int comp_idx,
    const INSCoefs& problem_coefs,
    const std::vector<SAMRAI::solv::RobinBcCoefStrategy<NDIM>*>& u_bc_coefs,
    const bool homogeneous_bc)
    : d_comp_idx(comp_idx),
      d_problem_coefs(problem_coefs),
      d_u_bc_coefs(NDIM,static_cast<SAMRAI::solv::RobinBcCoefStrategy<NDIM>*>(NULL)),
      d_current_time(std::numeric_limits<double>::quiet_NaN()),
      d_new_time(std::numeric_limits<double>::quiet_NaN()),
      d_target_idx(-1),
      d_homogeneous_bc(false)
{
    setVelocityPhysicalBcCoefs(u_bc_coefs);
    setHomogeneousBc(homogeneous_bc);
    return;
}// INSStaggeredVelocityBcCoef

INSStaggeredVelocityBcCoef::~INSStaggeredVelocityBcCoef()
{
    // intentionally blank
    return;
}// ~INSStaggeredVelocityBcCoef

void
INSStaggeredVelocityBcCoef::setVelocityPhysicalBcCoefs(
    const std::vector<SAMRAI::solv::RobinBcCoefStrategy<NDIM>*>& u_bc_coefs)
{
    if (u_bc_coefs.size() != NDIM)
    {
        TBOX_ERROR("INSStaggeredVelocityBcCoef::setVelocityPhysicalBcCoefs():\n"
                   << "  precisely NDIM boundary condition objects must be provided." << std::endl);
    }
    d_u_bc_coefs = u_bc_coefs;
    return;
}// setVelocityPhysicalBcCoefs

void
INSStaggeredVelocityBcCoef::setTimeInterval(
    const double current_time,
    const double new_time)
{
    d_current_time = current_time;
    d_new_time = new_time;
    return;
}// setTimeInterval

void
INSStaggeredVelocityBcCoef::setTargetPatchDataIndex(
    const int target_idx)
{
    d_target_idx = target_idx;
    return;
}// setTargetPatchDataIndex

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

void
INSStaggeredVelocityBcCoef::setBcCoefs(
    SAMRAI::tbox::Pointer<SAMRAI::pdat::ArrayData<NDIM,double> >& acoef_data,
    SAMRAI::tbox::Pointer<SAMRAI::pdat::ArrayData<NDIM,double> >& bcoef_data,
    SAMRAI::tbox::Pointer<SAMRAI::pdat::ArrayData<NDIM,double> >& gcoef_data,
    const SAMRAI::tbox::Pointer<SAMRAI::hier::Variable<NDIM> >& variable,
    const SAMRAI::hier::Patch<NDIM>& patch,
    const SAMRAI::hier::BoundaryBox<NDIM>& bdry_box,
    double fill_time) const
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_u_bc_coefs.size() == NDIM);
    for (unsigned l = 0; l < d_u_bc_coefs.size(); ++l)
    {
        TBOX_ASSERT(d_u_bc_coefs[l] != NULL);
    }
#endif
    // Set the unmodified velocity bc coefs.
    d_u_bc_coefs[d_comp_idx]->setBcCoefs(
        acoef_data, bcoef_data, gcoef_data, variable, patch, bdry_box, fill_time);

    // We do not make any further modifications to the values of acoef_data and
    // bcoef_data beyond this point.
    if (gcoef_data.isNull()) return;

    // Ensure homogeneous boundary conditions are enforced.
    if (d_homogeneous_bc) gcoef_data->fillAll(0.0);

    // Modify Neumann boundary conditions to correspond to traction (stress)
    // boundary conditions.
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(!acoef_data.isNull());
    TBOX_ASSERT(!bcoef_data.isNull());
    TBOX_ASSERT(!gcoef_data.isNull());
#endif
    const int location_index   = bdry_box.getLocationIndex();
    const int bdry_normal_axis = location_index/2;
    const bool is_lower        = location_index%2 == 0;
    const SAMRAI::hier::Box<NDIM>& bc_coef_box = acoef_data->getBox();
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(bc_coef_box == acoef_data->getBox());
    TBOX_ASSERT(bc_coef_box == bcoef_data->getBox());
    TBOX_ASSERT(bc_coef_box == gcoef_data->getBox());
#endif
    SAMRAI::tbox::Pointer<SAMRAI::pdat::SideData<NDIM,double> > u_data =
        patch.checkAllocated(d_target_idx)
        ? patch.getPatchData(d_target_idx)
        : SAMRAI::tbox::Pointer<SAMRAI::hier::PatchData<NDIM> >(NULL);
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(!u_data.isNull());
    TBOX_ASSERT(u_data->getGhostCellWidth().max() == u_data->getGhostCellWidth().min());
#endif
    const SAMRAI::hier::Box<NDIM>& ghost_box = u_data->getGhostBox();
    SAMRAI::tbox::Pointer<SAMRAI::geom::CartesianPatchGeometry<NDIM> > pgeom = patch.getPatchGeometry();
    const double* const dx = pgeom->getDx();
    const double mu = d_problem_coefs.getMu();
    for (SAMRAI::hier::Box<NDIM>::Iterator it(bc_coef_box); it; it++)
    {
        const SAMRAI::hier::Index<NDIM>& i = it();
        const double& alpha = (*acoef_data)(i,0);
        const double& beta  = (*bcoef_data)(i,0);
        double& gamma = (*gcoef_data)(i,0);

        const bool velocity_bc = SAMRAI::tbox::MathUtilities<double>::equalEps(alpha,1.0);
        const bool traction_bc = SAMRAI::tbox::MathUtilities<double>::equalEps(beta ,1.0);
#ifdef DEBUG_CHECK_ASSERTIONS
        TBOX_ASSERT((velocity_bc || traction_bc) && !(velocity_bc && traction_bc));
#endif
        if (velocity_bc)
        {
            // intentionally blank
        }
        else if (traction_bc)
        {
            if (d_comp_idx == bdry_normal_axis)
            {
                SAMRAI::hier::Index<NDIM> i_intr0 = i;
                SAMRAI::hier::Index<NDIM> i_intr1 = i;

                if (is_lower)
                {
                    i_intr0(bdry_normal_axis) += 0;
                    i_intr1(bdry_normal_axis) += 1;
                }
                else
                {
                    i_intr0(bdry_normal_axis) -= 1;
                    i_intr1(bdry_normal_axis) -= 2;
                }

                for (int d = 0; d < NDIM; ++d)
                {
                    if (d != bdry_normal_axis)
                    {
                        i_intr0(d) = std::max(i_intr0(d),ghost_box.lower()(d));
                        i_intr0(d) = std::min(i_intr0(d),ghost_box.upper()(d));

                        i_intr1(d) = std::max(i_intr1(d),ghost_box.lower()(d));
                        i_intr1(d) = std::min(i_intr1(d),ghost_box.upper()(d));
                    }
                }

                // Specify a Neumann boundary condition which corresponds to a
                // finite difference approximation to the divergence free
                // condition at the boundary of the domain using extrapolated
                // values of the tangential velocities.
                double du_norm_dn = 0.0;
                for (int axis = 0; axis < NDIM; ++axis)
                {
                    if (axis != bdry_normal_axis)
                    {
                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr0_upper(i_intr0, axis, SAMRAI::pdat::SideIndex<NDIM>::Upper);
                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr1_upper(i_intr1, axis, SAMRAI::pdat::SideIndex<NDIM>::Upper);
                        const double u_tan_upper = 1.5*(*u_data)(i_s_intr0_upper)-0.5*(*u_data)(i_s_intr1_upper);

                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr0_lower(i_intr0, axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr1_lower(i_intr1, axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                        const double u_tan_lower = 1.5*(*u_data)(i_s_intr0_lower)-0.5*(*u_data)(i_s_intr1_lower);

                        du_norm_dn += (is_lower ? +1.0 : -1.0)*(u_tan_upper-u_tan_lower)/dx[axis];
                    }
                }
                gamma = du_norm_dn;
            }
            else
            {
                // Compute the tangential derivative of the normal component of
                // the velocity at the boundary.
                SAMRAI::hier::Index<NDIM> i_lower(i), i_upper(i);
                i_lower(d_comp_idx) = std::max(ghost_box.lower()(d_comp_idx),i(d_comp_idx)-1);
                i_upper(d_comp_idx) = std::min(ghost_box.upper()(d_comp_idx),i(d_comp_idx)  );
                const SAMRAI::pdat::SideIndex<NDIM> i_s_lower(i_lower, bdry_normal_axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                const SAMRAI::pdat::SideIndex<NDIM> i_s_upper(i_upper, bdry_normal_axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                const double du_norm_dtan = (is_lower ? -1.0 : +1.0)*((*u_data)(i_s_upper)-(*u_data)(i_s_lower))/dx[d_comp_idx];

                // Correct the boundary condition value.
                gamma = gamma/mu - du_norm_dtan;
            }
        }
        else
        {
            TBOX_ERROR("this statement should not be reached!\n");
        }

        // XXXX
        SAMRAI::hier::Index<NDIM> i_intr = i;
        if (is_lower)
        {
            i_intr(bdry_normal_axis) += 0;
        }
        else
        {
            i_intr(bdry_normal_axis) -= 1;
        }
        if (i_intr == SAMRAI::hier::Index<NDIM>(0))
        {
            (*acoef_data)(i,0) = 0.0;
            (*bcoef_data)(i,0) = 1.0;
            (*gcoef_data)(i,0) = 0.0;
        }
        // XXXX
    }
    return;
}// setBcCoefs

SAMRAI::hier::IntVector<NDIM>
INSStaggeredVelocityBcCoef::numberOfExtensionsFillable() const
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_u_bc_coefs.size() == NDIM);
    for (unsigned l = 0; l < d_u_bc_coefs.size(); ++l)
    {
        TBOX_ASSERT(d_u_bc_coefs[l] != NULL);
    }
#endif
    SAMRAI::hier::IntVector<NDIM> ret_val(std::numeric_limits<int>::max());
    for (int d = 0; d < NDIM; ++d)
    {
        ret_val = SAMRAI::hier::IntVector<NDIM>::min(
            ret_val, d_u_bc_coefs[d]->numberOfExtensionsFillable());
    }
    return ret_val;
}// numberOfExtensionsFillable

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

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

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

}// namespace IBAMR

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

//////////////////////////////////////////////////////////////////////////////
<commit_msg><commit_after>// Filename: INSStaggeredVelocityBcCoef.C
// Last modified: <03.Oct.2008 17:45:29 griffith@box230.cims.nyu.edu>
// Created on 22 Jul 2008 by Boyce Griffith (griffith@box230.cims.nyu.edu)

#include "INSStaggeredVelocityBcCoef.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

// IBTK INCLUDES
#include <ibtk/PhysicalBoundaryUtilities.h>

// SAMRAI INCLUDES
#include <CartesianPatchGeometry.h>
#include <CellData.h>
#include <SideData.h>
#include <tbox/Utilities.h>

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

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

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

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

INSStaggeredVelocityBcCoef::INSStaggeredVelocityBcCoef(
    const int comp_idx,
    const INSCoefs& problem_coefs,
    const std::vector<SAMRAI::solv::RobinBcCoefStrategy<NDIM>*>& u_bc_coefs,
    const bool homogeneous_bc)
    : d_comp_idx(comp_idx),
      d_problem_coefs(problem_coefs),
      d_u_bc_coefs(NDIM,static_cast<SAMRAI::solv::RobinBcCoefStrategy<NDIM>*>(NULL)),
      d_current_time(std::numeric_limits<double>::quiet_NaN()),
      d_new_time(std::numeric_limits<double>::quiet_NaN()),
      d_target_idx(-1),
      d_homogeneous_bc(false)
{
    setVelocityPhysicalBcCoefs(u_bc_coefs);
    setHomogeneousBc(homogeneous_bc);
    return;
}// INSStaggeredVelocityBcCoef

INSStaggeredVelocityBcCoef::~INSStaggeredVelocityBcCoef()
{
    // intentionally blank
    return;
}// ~INSStaggeredVelocityBcCoef

void
INSStaggeredVelocityBcCoef::setVelocityPhysicalBcCoefs(
    const std::vector<SAMRAI::solv::RobinBcCoefStrategy<NDIM>*>& u_bc_coefs)
{
    if (u_bc_coefs.size() != NDIM)
    {
        TBOX_ERROR("INSStaggeredVelocityBcCoef::setVelocityPhysicalBcCoefs():\n"
                   << "  precisely NDIM boundary condition objects must be provided." << std::endl);
    }
    d_u_bc_coefs = u_bc_coefs;
    return;
}// setVelocityPhysicalBcCoefs

void
INSStaggeredVelocityBcCoef::setTimeInterval(
    const double current_time,
    const double new_time)
{
    d_current_time = current_time;
    d_new_time = new_time;
    return;
}// setTimeInterval

void
INSStaggeredVelocityBcCoef::setTargetPatchDataIndex(
    const int target_idx)
{
    d_target_idx = target_idx;
    return;
}// setTargetPatchDataIndex

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

void
INSStaggeredVelocityBcCoef::setBcCoefs(
    SAMRAI::tbox::Pointer<SAMRAI::pdat::ArrayData<NDIM,double> >& acoef_data,
    SAMRAI::tbox::Pointer<SAMRAI::pdat::ArrayData<NDIM,double> >& bcoef_data,
    SAMRAI::tbox::Pointer<SAMRAI::pdat::ArrayData<NDIM,double> >& gcoef_data,
    const SAMRAI::tbox::Pointer<SAMRAI::hier::Variable<NDIM> >& variable,
    const SAMRAI::hier::Patch<NDIM>& patch,
    const SAMRAI::hier::BoundaryBox<NDIM>& bdry_box,
    double fill_time) const
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_u_bc_coefs.size() == NDIM);
    for (unsigned l = 0; l < d_u_bc_coefs.size(); ++l)
    {
        TBOX_ASSERT(d_u_bc_coefs[l] != NULL);
    }
#endif
    // Set the unmodified velocity bc coefs.
    d_u_bc_coefs[d_comp_idx]->setBcCoefs(
        acoef_data, bcoef_data, gcoef_data, variable, patch, bdry_box, fill_time);

    // We do not make any further modifications to the values of acoef_data and
    // bcoef_data beyond this point.
    if (gcoef_data.isNull()) return;

    // Ensure homogeneous boundary conditions are enforced.
    if (d_homogeneous_bc) gcoef_data->fillAll(0.0);

    // Modify Neumann boundary conditions to correspond to traction (stress)
    // boundary conditions.
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(!acoef_data.isNull());
    TBOX_ASSERT(!bcoef_data.isNull());
    TBOX_ASSERT(!gcoef_data.isNull());
#endif
    const int location_index   = bdry_box.getLocationIndex();
    const int bdry_normal_axis = location_index/2;
    const bool is_lower        = location_index%2 == 0;
    const SAMRAI::hier::Box<NDIM>& bc_coef_box = acoef_data->getBox();
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(bc_coef_box == acoef_data->getBox());
    TBOX_ASSERT(bc_coef_box == bcoef_data->getBox());
    TBOX_ASSERT(bc_coef_box == gcoef_data->getBox());
#endif
    SAMRAI::tbox::Pointer<SAMRAI::pdat::SideData<NDIM,double> > u_data =
        patch.checkAllocated(d_target_idx)
        ? patch.getPatchData(d_target_idx)
        : SAMRAI::tbox::Pointer<SAMRAI::hier::PatchData<NDIM> >(NULL);
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(!u_data.isNull());
    TBOX_ASSERT(u_data->getGhostCellWidth().max() == u_data->getGhostCellWidth().min());
#endif
    const SAMRAI::hier::Box<NDIM>& ghost_box = u_data->getGhostBox();
    SAMRAI::tbox::Pointer<SAMRAI::geom::CartesianPatchGeometry<NDIM> > pgeom = patch.getPatchGeometry();
    const double* const dx = pgeom->getDx();
    const double mu = d_problem_coefs.getMu();
    for (SAMRAI::hier::Box<NDIM>::Iterator it(bc_coef_box); it; it++)
    {
        const SAMRAI::hier::Index<NDIM>& i = it();
        const double& alpha = (*acoef_data)(i,0);
        const double& beta  = (*bcoef_data)(i,0);
        double& gamma = (*gcoef_data)(i,0);

        const bool velocity_bc = SAMRAI::tbox::MathUtilities<double>::equalEps(alpha,1.0);
        const bool traction_bc = SAMRAI::tbox::MathUtilities<double>::equalEps(beta ,1.0);
#ifdef DEBUG_CHECK_ASSERTIONS
        TBOX_ASSERT((velocity_bc || traction_bc) && !(velocity_bc && traction_bc));
#endif
        if (velocity_bc)
        {
            // intentionally blank
        }
        else if (traction_bc)
        {
            if (d_comp_idx == bdry_normal_axis)
            {
                SAMRAI::hier::Index<NDIM> i_intr0 = i;
                SAMRAI::hier::Index<NDIM> i_intr1 = i;

                if (is_lower)
                {
                    i_intr0(bdry_normal_axis) += 0;
                    i_intr1(bdry_normal_axis) += 1;
                }
                else
                {
                    i_intr0(bdry_normal_axis) -= 1;
                    i_intr1(bdry_normal_axis) -= 2;
                }

                for (int d = 0; d < NDIM; ++d)
                {
                    if (d != bdry_normal_axis)
                    {
                        i_intr0(d) = std::max(i_intr0(d),ghost_box.lower()(d));
                        i_intr0(d) = std::min(i_intr0(d),ghost_box.upper()(d));

                        i_intr1(d) = std::max(i_intr1(d),ghost_box.lower()(d));
                        i_intr1(d) = std::min(i_intr1(d),ghost_box.upper()(d));
                    }
                }

                // Specify a Neumann boundary condition which corresponds to a
                // finite difference approximation to the divergence free
                // condition at the boundary of the domain using extrapolated
                // values of the tangential velocities.
                double du_norm_dn = 0.0;
                for (int axis = 0; axis < NDIM; ++axis)
                {
                    if (axis != bdry_normal_axis)
                    {
                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr0_upper(i_intr0, axis, SAMRAI::pdat::SideIndex<NDIM>::Upper);
                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr1_upper(i_intr1, axis, SAMRAI::pdat::SideIndex<NDIM>::Upper);
                        const double u_tan_upper = (*u_data)(i_s_intr0_upper); // XXXX 1.5*(*u_data)(i_s_intr0_upper)-0.5*(*u_data)(i_s_intr1_upper);

                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr0_lower(i_intr0, axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                        const SAMRAI::pdat::SideIndex<NDIM> i_s_intr1_lower(i_intr1, axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                        const double u_tan_lower = (*u_data)(i_s_intr0_lower); // XXXX 1.5*(*u_data)(i_s_intr0_lower)-0.5*(*u_data)(i_s_intr1_lower);

                        du_norm_dn += (is_lower ? +1.0 : -1.0)*(u_tan_upper-u_tan_lower)/dx[axis];
                    }
                }
                gamma = du_norm_dn;
            }
            else
            {
                // Compute the tangential derivative of the normal component of
                // the velocity at the boundary.
                SAMRAI::hier::Index<NDIM> i_lower(i), i_upper(i);
                i_lower(d_comp_idx) = std::max(ghost_box.lower()(d_comp_idx),i(d_comp_idx)-1);
                i_upper(d_comp_idx) = std::min(ghost_box.upper()(d_comp_idx),i(d_comp_idx)  );
                const SAMRAI::pdat::SideIndex<NDIM> i_s_lower(i_lower, bdry_normal_axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                const SAMRAI::pdat::SideIndex<NDIM> i_s_upper(i_upper, bdry_normal_axis, SAMRAI::pdat::SideIndex<NDIM>::Lower);
                const double du_norm_dtan = (is_lower ? -1.0 : +1.0)*((*u_data)(i_s_upper)-(*u_data)(i_s_lower))/dx[d_comp_idx];

                // Correct the boundary condition value.
                gamma = gamma/mu - du_norm_dtan;
            }
        }
        else
        {
            TBOX_ERROR("this statement should not be reached!\n");
        }

        // XXXX
        SAMRAI::hier::Index<NDIM> i_intr = i;
        if (is_lower)
        {
            i_intr(bdry_normal_axis) += 0;
        }
        else
        {
            i_intr(bdry_normal_axis) -= 1;
        }
        if (i_intr == SAMRAI::hier::Index<NDIM>(0))
        {
            (*acoef_data)(i,0) = 0.0;
            (*bcoef_data)(i,0) = 1.0;
            (*gcoef_data)(i,0) = 0.0;
        }
        // XXXX
    }
    return;
}// setBcCoefs

SAMRAI::hier::IntVector<NDIM>
INSStaggeredVelocityBcCoef::numberOfExtensionsFillable() const
{
#ifdef DEBUG_CHECK_ASSERTIONS
    TBOX_ASSERT(d_u_bc_coefs.size() == NDIM);
    for (unsigned l = 0; l < d_u_bc_coefs.size(); ++l)
    {
        TBOX_ASSERT(d_u_bc_coefs[l] != NULL);
    }
#endif
    SAMRAI::hier::IntVector<NDIM> ret_val(std::numeric_limits<int>::max());
    for (int d = 0; d < NDIM; ++d)
    {
        ret_val = SAMRAI::hier::IntVector<NDIM>::min(
            ret_val, d_u_bc_coefs[d]->numberOfExtensionsFillable());
    }
    return ret_val;
}// numberOfExtensionsFillable

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

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

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

}// namespace IBAMR

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

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


<commit_before>#ifndef _TOOLBOX_ARGV_PARSER_HPP_
#define _TOOLBOX_ARGV_PARSER_HPP_

#include <tuple>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <getopt.h>
#include <toolbox/cpp/tuple_for_each.hpp>
#include <toolbox/cpp/make_ref_tuple.hpp>
#include <toolbox/cpp/for_each_param.hpp>
#include <toolbox/argv/options.hpp>
#include <toolbox/argv/exceptions.hpp>

namespace toolbox
{
namespace argv
{

template<typename Options>
class parser
{
public:
	parser(Options &&options) :
		options_(std::move(options))
	{
		std::stringstream ss;
		cpp::tuple_for_each(
			options_,
			[&ss, this](auto& option) {
				ss << option.get_short();
				if (option.has_argument()) ss << ":";

				if (option.get_long().size() > 0) {
					::option o;
					o.name = option.get_long().c_str();
					o.has_arg = option.has_argument() ? required_argument : no_argument;
					o.flag = nullptr;
					o.val = option.get_short();

					options_arr_.push_back(o);
				}

				longest_name_ = std::max(longest_name_, option.get_long().size());
				longest_argname_ = std::max(longest_argname_, option.get_argument_name().size());
			}
		);

		opt_descriptor_ = ss.str();
	}

	void parse(int argc, char ** argv)
	{
		int c;
		int index;

		while (
			(c = getopt_long(
					argc,
					const_cast<char* const*>(argv),
					opt_descriptor_.c_str(),
					options_arr_.data(),
					&index))
				!= -1) {
			cpp::tuple_for_each(
				options_,
				[this, c](auto& option) {
					if (option.get_short() == c) {
						option.set_found(optarg);
					}
				}
			);
		}

		for (int i = optind; i < argc; i ++)
			non_options_.push_back(std::string(argv[i]));

		cpp::tuple_for_each(
			options_,
			[](auto &option) {
				option.transfer_to_storage();
			}
		);
	}

	const std::vector<std::string> &non_options() const
	{
		return non_options_;
	}

	void print_options(std::ostream &os) const
	{
		/* TODO: this is just a ugly draft - refactor */
		cpp::tuple_for_each(
			options_,
			[this, &os](auto &option) {
				std::stringstream p1;

				p1 << "  -" << option.get_short();
				if (option.get_long().size() > 0)
					p1 << ", --" << option.get_long();

				if (option.get_argument_name().size() > 0)
					p1 << " [" << option.get_argument_name() << "]";

				std::stringstream p2;
				p2 << std::setw(longest_argname_ + longest_name_ + 10) << std::left << p1.str();

				if (option.get_description().size() > 0)
					p2 << " - " << option.get_description();

				os << p2.str() << std::endl;
			}
		);
	}

	template<typename... RequiredOptions>
	void check_required(const RequiredOptions&... options) const
	{
		std::vector<std::pair<char, std::string>> not_found;
		cpp::for_each_param(
			[&not_found](auto &option) {
				if (option.found() == 0) {
					not_found.push_back(std::make_pair(option.get_short(), option.get_long()));
				}
			},
			options...
		);
		if (not_found.size() > 0)
			throw exceptions::missing_required(std::move(not_found));
	}

private:
	Options options_;
	std::vector<::option> options_arr_;
	std::string opt_descriptor_;
	std::vector<std::string> non_options_;
	std::size_t longest_name_ = 0;
	std::size_t longest_argname_ = 0;
};

template<typename... Options>
auto make_parser(Options&&... options)
{
	auto options_tuple = cpp::make_ref_tuple(options...);
	return parser<decltype(options_tuple)>(std::move(options_tuple));
}

} // namespace argv
} // namespace toolbox

#endif
<commit_msg>Properly initialize option in argv parser<commit_after>#ifndef _TOOLBOX_ARGV_PARSER_HPP_
#define _TOOLBOX_ARGV_PARSER_HPP_

#include <tuple>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <getopt.h>
#include <toolbox/cpp/tuple_for_each.hpp>
#include <toolbox/cpp/make_ref_tuple.hpp>
#include <toolbox/cpp/for_each_param.hpp>
#include <toolbox/argv/options.hpp>
#include <toolbox/argv/exceptions.hpp>

namespace toolbox
{
namespace argv
{

template<typename Options>
class parser
{
public:
	parser(Options &&options) :
		options_(std::move(options))
	{
		std::stringstream ss;
		cpp::tuple_for_each(
			options_,
			[&ss, this](auto& option) {
				ss << option.get_short();
				if (option.has_argument()) ss << ":";

				if (option.get_long().size() > 0) {
					::option o = {
						option.get_long().c_str(),
						option.has_argument() ? required_argument : no_argument,
						nullptr,
						option.get_short()
					};

					options_arr_.push_back(o);
				}

				longest_name_ = std::max(longest_name_, option.get_long().size());
				longest_argname_ = std::max(longest_argname_, option.get_argument_name().size());
			}
		);

		opt_descriptor_ = ss.str();
	}

	void parse(int argc, char ** argv)
	{
		int c;
		int index;

		while (
			(c = getopt_long(
					argc,
					const_cast<char* const*>(argv),
					opt_descriptor_.c_str(),
					options_arr_.data(),
					&index))
				!= -1) {
			cpp::tuple_for_each(
				options_,
				[this, c](auto& option) {
					if (option.get_short() == c) {
						option.set_found(optarg);
					}
				}
			);
		}

		for (int i = optind; i < argc; i ++)
			non_options_.push_back(std::string(argv[i]));

		cpp::tuple_for_each(
			options_,
			[](auto &option) {
				option.transfer_to_storage();
			}
		);
	}

	const std::vector<std::string> &non_options() const
	{
		return non_options_;
	}

	void print_options(std::ostream &os) const
	{
		/* TODO: this is just a ugly draft - refactor */
		cpp::tuple_for_each(
			options_,
			[this, &os](auto &option) {
				std::stringstream p1;

				p1 << "  -" << option.get_short();
				if (option.get_long().size() > 0)
					p1 << ", --" << option.get_long();

				if (option.get_argument_name().size() > 0)
					p1 << " [" << option.get_argument_name() << "]";

				std::stringstream p2;
				p2 << std::setw(longest_argname_ + longest_name_ + 10) << std::left << p1.str();

				if (option.get_description().size() > 0)
					p2 << " - " << option.get_description();

				os << p2.str() << std::endl;
			}
		);
	}

	template<typename... RequiredOptions>
	void check_required(const RequiredOptions&... options) const
	{
		std::vector<std::pair<char, std::string>> not_found;
		cpp::for_each_param(
			[&not_found](auto &option) {
				if (option.found() == 0) {
					not_found.push_back(std::make_pair(option.get_short(), option.get_long()));
				}
			},
			options...
		);
		if (not_found.size() > 0)
			throw exceptions::missing_required(std::move(not_found));
	}

private:
	Options options_;
	std::vector<::option> options_arr_;
	std::string opt_descriptor_;
	std::vector<std::string> non_options_;
	std::size_t longest_name_ = 0;
	std::size_t longest_argname_ = 0;
};

template<typename... Options>
auto make_parser(Options&&... options)
{
	auto options_tuple = cpp::make_ref_tuple(options...);
	return parser<decltype(options_tuple)>(std::move(options_tuple));
}

} // namespace argv
} // namespace toolbox

#endif
<|endoftext|>


<commit_before>#pragma once

#include <charconv>

#include <vili/parser/grammar.hpp>
#include <vili/parser/parser_state.hpp>

namespace vili::parser
{
    template <typename Rule> struct action
    {
    };

    template <> struct action<rules::string_content>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(in.string());
        }
    };

    template <> struct action<rules::number>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            const std::string_view data_in = in.string_view();
            state.push(utils::string::to_double(in.string_view()));
        }
    };

    template <> struct action<rules::integer>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(utils::string::to_long(in.string_view()));
        }
    };

    template <> struct action<rules::boolean>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push((in.string_view() == "true" ? true : false));
        }
    };

    template <> struct action<rules::template_usage>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            try
            {
                state.push(state.get_template(in.string()));
            }
            catch (exceptions::unknown_template& e)
            {
                throw exceptions::parsing_error(in.position().source, in.position().line,
                    in.position().byte_in_line, EXC_INFO)
                    .nest(e);
            }
        }
    };

    template <> struct action<rules::identifier>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.set_active_identifier(in.string());
        }
    };

    template <> struct action<rules::open_array>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(vili::array {});
        }
    };

    template <> struct action<rules::close_array>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.close_block();
        }
    };

    template <> struct action<rules::open_object>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(vili::object {});
        }
    };

    template <> struct action<rules::close_object>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.close_block();
        }
    };

    template <> struct action<rules::indent_based_object>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(vili::object {});
            state.use_indent();
        }
    };

    template <> struct action<rules::indent>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.set_indent(in.string_view().size());
        }
    };

    template <> struct action<rules::template_keyword>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.set_indent(0);
        }
    };

    template <> struct action<rules::template_decl>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push_template();
        }
    };
}<commit_msg>Removed unnecessary includes<commit_after>#pragma once

#include <vili/parser/grammar.hpp>
#include <vili/parser/parser_state.hpp>

namespace vili::parser
{
    template <typename Rule> struct action
    {
    };

    template <> struct action<rules::string_content>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(in.string());
        }
    };

    template <> struct action<rules::number>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            const std::string_view data_in = in.string_view();
            state.push(utils::string::to_double(in.string_view()));
        }
    };

    template <> struct action<rules::integer>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(utils::string::to_long(in.string_view()));
        }
    };

    template <> struct action<rules::boolean>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push((in.string_view() == "true" ? true : false));
        }
    };

    template <> struct action<rules::template_usage>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            try
            {
                state.push(state.get_template(in.string()));
            }
            catch (exceptions::unknown_template& e)
            {
                throw exceptions::parsing_error(in.position().source, in.position().line,
                    in.position().byte_in_line, EXC_INFO)
                    .nest(e);
            }
        }
    };

    template <> struct action<rules::identifier>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.set_active_identifier(in.string());
        }
    };

    template <> struct action<rules::open_array>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(vili::array {});
        }
    };

    template <> struct action<rules::close_array>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.close_block();
        }
    };

    template <> struct action<rules::open_object>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(vili::object {});
        }
    };

    template <> struct action<rules::close_object>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.close_block();
        }
    };

    template <> struct action<rules::indent_based_object>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push(vili::object {});
            state.use_indent();
        }
    };

    template <> struct action<rules::indent>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.set_indent(in.string_view().size());
        }
    };

    template <> struct action<rules::template_keyword>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.set_indent(0);
        }
    };

    template <> struct action<rules::template_decl>
    {
        template <class ParseInput> static void apply(const ParseInput& in, state& state)
        {
            state.push_template();
        }
    };
}<|endoftext|>


<commit_before>/** Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Roland Olbricht et al.
 *
 * This file is part of Overpass_API.
 *
 * Overpass_API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Overpass_API is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iomanip>
#include <iostream>
#include <sstream>
#include "../../template_db/block_backend.h"
#include "../core/settings.h"
#include "../output_formats/output_xml.h"
#include "bbox_query.h"
#include "print.h"

void perform_bbox_print(std::string south, std::string north, std::string west, std::string east,
			Transaction& transaction)
{
  Parsed_Query global_settings;
  global_settings.set_output_handler(Output_Handler_Parser::get_format_parser("xml"), 0, 0);
  try
  {
    // Select a bbox from the testset that contains one quarter
    // of only one bbox.
    Resource_Manager rman(transaction, &global_settings);
    {
      const char* attributes[] =
          { "s", south.c_str(), "n", north.c_str(),
            "w", west.c_str(), "e", east.c_str(), 0 };
      Bbox_Query_Statement* stmt1 = new Bbox_Query_Statement(0, convert_c_pairs(attributes), global_settings);
      stmt1->execute(rman);
    }
    {
      const char* attributes[] = { "mode", "body", "order", "id", 0 };
      Print_Statement* stmt1 = new Print_Statement(0, convert_c_pairs(attributes), global_settings);
      stmt1->execute(rman);
    }
  }
  catch (File_Error e)
  {
    std::cerr<<"File error caught: "
    <<e.error_number<<' '<<e.filename<<' '<<e.origin<<'\n';
  }
}

int main(int argc, char* args[])
{
  Parsed_Query global_settings;
  if (argc < 4)
  {
    std::cout<<"Usage: "<<args[0]<<" test_to_execute pattern_size db_dir\n";
    return 0;
  }
  std::string test_to_execute = args[1];
  uint pattern_size = 0;
  pattern_size = atoi(args[2]);

  Nonsynced_Transaction transaction(false, false, args[3], "");

  std::cout<<
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<osm>\n";

  if ((test_to_execute == "") || (test_to_execute == "1"))
    perform_bbox_print("-10.0", "8.0", "-15.0", "9.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "2"))
    perform_bbox_print("-10.0", "-1.0", "-15.0", "-3.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "3"))
    perform_bbox_print("-10.0", "-1.0", "93.0", "105.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "4"))
    perform_bbox_print("-10.0", "-1.0", "93.0", "-3.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "5"))
    perform_bbox_print("-10.0", "-1.0", "-15.0", "-15.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "6"))
  {
    double lon_offset = (105.0-(-15.0))/pattern_size/2;
    std::ostringstream west_ss;
    west_ss<<std::fixed<<std::setprecision(7)<<(-15.0 + lon_offset);
    perform_bbox_print("-10.0", "-1.0", west_ss.str(), west_ss.str(), transaction);
  }
  if ((test_to_execute == "") || (test_to_execute == "7"))
    perform_bbox_print("-10.0", "-10.0", "-15.0", "-3.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "8"))
  {
    double lat_offset = (80.0-(-10.0))/pattern_size/2;
    std::ostringstream south_ss;
    south_ss<<std::fixed<<std::setprecision(7)<<(-10.0 + lat_offset);
    perform_bbox_print(south_ss.str(), south_ss.str(), "-15.0", "-3.0", transaction);
  }

  std::cout<<"</osm>\n";
  return 0;
}

// Test cases are:
// - bbox with positive lon, with negative lon, both, lon wrap
//   ew line, ns line, point
<commit_msg>Fix memory leak in bbox_query.test<commit_after>/** Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Roland Olbricht et al.
 *
 * This file is part of Overpass_API.
 *
 * Overpass_API is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Overpass_API is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with Overpass_API.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <iomanip>
#include <iostream>
#include <sstream>
#include "../../template_db/block_backend.h"
#include "../core/settings.h"
#include "../output_formats/output_xml.h"
#include "bbox_query.h"
#include "print.h"

void perform_bbox_print(std::string south, std::string north, std::string west, std::string east,
			Transaction& transaction)
{
  Parsed_Query global_settings;
  global_settings.set_output_handler(Output_Handler_Parser::get_format_parser("xml"), 0, 0);
  try
  {
    // Select a bbox from the testset that contains one quarter
    // of only one bbox.
    Resource_Manager rman(transaction, &global_settings);
    {
      const char* attributes[] =
          { "s", south.c_str(), "n", north.c_str(),
            "w", west.c_str(), "e", east.c_str(), 0 };
      Bbox_Query_Statement* stmt1 = new Bbox_Query_Statement(0, convert_c_pairs(attributes), global_settings);
      stmt1->execute(rman);
      delete stmt1;
    }
    {
      const char* attributes[] = { "mode", "body", "order", "id", 0 };
      Print_Statement* stmt1 = new Print_Statement(0, convert_c_pairs(attributes), global_settings);
      stmt1->execute(rman);
      delete stmt1;
    }
  }
  catch (File_Error e)
  {
    std::cerr<<"File error caught: "
    <<e.error_number<<' '<<e.filename<<' '<<e.origin<<'\n';
  }
}

int main(int argc, char* args[])
{
  Parsed_Query global_settings;
  if (argc < 4)
  {
    std::cout<<"Usage: "<<args[0]<<" test_to_execute pattern_size db_dir\n";
    return 0;
  }
  std::string test_to_execute = args[1];
  uint pattern_size = 0;
  pattern_size = atoi(args[2]);

  Nonsynced_Transaction transaction(false, false, args[3], "");

  std::cout<<
  "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
  "<osm>\n";

  if ((test_to_execute == "") || (test_to_execute == "1"))
    perform_bbox_print("-10.0", "8.0", "-15.0", "9.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "2"))
    perform_bbox_print("-10.0", "-1.0", "-15.0", "-3.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "3"))
    perform_bbox_print("-10.0", "-1.0", "93.0", "105.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "4"))
    perform_bbox_print("-10.0", "-1.0", "93.0", "-3.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "5"))
    perform_bbox_print("-10.0", "-1.0", "-15.0", "-15.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "6"))
  {
    double lon_offset = (105.0-(-15.0))/pattern_size/2;
    std::ostringstream west_ss;
    west_ss<<std::fixed<<std::setprecision(7)<<(-15.0 + lon_offset);
    perform_bbox_print("-10.0", "-1.0", west_ss.str(), west_ss.str(), transaction);
  }
  if ((test_to_execute == "") || (test_to_execute == "7"))
    perform_bbox_print("-10.0", "-10.0", "-15.0", "-3.0", transaction);
  if ((test_to_execute == "") || (test_to_execute == "8"))
  {
    double lat_offset = (80.0-(-10.0))/pattern_size/2;
    std::ostringstream south_ss;
    south_ss<<std::fixed<<std::setprecision(7)<<(-10.0 + lat_offset);
    perform_bbox_print(south_ss.str(), south_ss.str(), "-15.0", "-3.0", transaction);
  }

  std::cout<<"</osm>\n";
  return 0;
}

// Test cases are:
// - bbox with positive lon, with negative lon, both, lon wrap
//   ew line, ns line, point
<|endoftext|>


<commit_before>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#pragma once
#include "ork/memory.hpp"
#include "ork/private/text_includes.hpp"
#include "ork/string_utils.hpp"
#include "ork/type_traits.hpp"

#include "glm/fwd.hpp"

namespace ork {

// Serialization tag: basis for a child node
struct tagged {
private:
    ork::bstring _tag;

public:
    ORK_INLINE tagged(const ork::bstring& tag)
        : _tag{tag}
    {}
    ORK_MOVEABLE(tagged);

public:
    ORK_INLINE const ork::bstring& tag() const
    {
        return _tag;
    }
};

#define ORK_OI_DECL_(SUFFIX) \
    class ORK_ORK_API exportable { \
    public: \
        virtual ~exportable() {} \
\
    public: \
        virtual void ORK_CAT(to_, SUFFIX)(node&) const = 0; \
    }; \
    class ORK_ORK_API importable { \
    public: \
        virtual ~importable() {} \
\
    public: \
        virtual void ORK_CAT(from_, SUFFIX)(const node&) = 0; \
    }; \
    class ORK_ORK_API serializable \
        : public exportable \
        , public importable { \
    public: \
        virtual ~serializable() {} \
    };

namespace json {

#if ORK_USE_JSON

using node = Json::Value;
ORK_OI_DECL_(json)

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const node& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, node& root);
ORK_ORK_EXT(node) load_and_parse(bi_stream& fin);

#endif // ORK_USE_JSON

} // namespace json
namespace xml {

#if ORK_USE_PUGI

using node = pugi::xml_node;
ORK_OI_DECL_(xml)

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object, const bstring& root_tag);
ORK_ORK_EXT(void)
export_file_permissive(const string& path_to_file, const bstring& root_tag, const exportable& object);
ORK_ORK_EXT(void)
load_and_parse(bi_stream& fin, pugi::xml_document& root); // Just create a file with error checking
ORK_ORK_EXT(void)
load_and_parse_permissive(const file::path& path_to_file, const bstring& root_tag, importable& object);

/*
These are permissive interfaces
*/
template<typename T>
void value_to_attribute(node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_attribute(tag.c_str()).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set attribute ") << ORK_BYTE_2_STR(node.name())
            << ORK(":") << ORK_BYTE_2_STR(tag) << ORK(", ") << e.what();
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting attribute ")
            << ORK_BYTE_2_STR(node.name()) << ORK(":") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_child(tag.c_str())
            .append_child(pugi::node_pcdata)
            .set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(tag) << ORK(": ")
            << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting tag ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(node& node, ORK_CPARAM_T value)
{
    try {
        node.append_child(pugi::node_pcdata).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened setting tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}

template<typename T>
void value_from_attribute(const node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.attribute(tag.c_str()).value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read parameter ") << ORK_BYTE_2_STR(tag)
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading parameter ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value(tag.c_str()));
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(tag) << ORK(": ")
            << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading tag ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const node& node, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened reading tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}

// Overloads to eliminate dependency definitions
#    define ORK_XML_SERIALIZE_DECL_(API, TYPE) \
        API(void) \
        to_xml(ork::xml::node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value); \
        API(void) \
        to_attribute( \
            ork::xml::node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value); \
        API(void) \
        from_xml(const ork::xml::node& node, const ork::bstring& tag, ORK_REF(TYPE) value); \
        API(void) \
        from_attribute( \
            const ork::xml::node& node, const ork::bstring& tag, ORK_REF(TYPE) value)

#    define ORK_XML_SERIALIZE_DECL(TYPE) ORK_XML_SERIALIZE_DECL_(ORK_EXT, TYPE)
#    define ORK_ORK_XML_SERIALIZE_DECL(TYPE) \
        ORK_XML_SERIALIZE_DECL_(ORK_ORK_EXT, TYPE)

ORK_ORK_XML_SERIALIZE_DECL(int);
ORK_ORK_XML_SERIALIZE_DECL(unsigned);
ORK_ORK_XML_SERIALIZE_DECL(size_t);
ORK_ORK_XML_SERIALIZE_DECL(float);
ORK_ORK_XML_SERIALIZE_DECL(double);
ORK_ORK_XML_SERIALIZE_DECL(bstring);
ORK_ORK_XML_SERIALIZE_DECL(wstring);

#    define ORK_XML_SERIALIZE_DEF(TYPE) \
        void to_xml(node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value) \
        { \
            ork::xml::value_to_xml<TYPE>(node, tag, value); \
        } \
        void to_attribute(node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value) \
        { \
            ork::xml::value_to_attribute<TYPE>(node, tag, value); \
        } \
        void from_xml(const node& node, const ork::bstring& tag, ORK_REF(TYPE) value) \
        { \
            ork::xml::value_from_xml<TYPE>(node, tag, value); \
        } \
        void from_attribute( \
            const node& node, const ork::bstring& tag, ORK_REF(TYPE) value) \
        { \
            ork::xml::value_from_xml<TYPE>(node, tag, value); \
        }

#endif // ORK_USE_PUGI

} // namespace xml
namespace yaml {

#if ORK_USE_YAML

using node = YAML::Node;
ORK_OI_DECL_(yaml)

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const node& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, node& root);
ORK_ORK_EXT(node) load_and_parse(bi_stream& fin);

#endif // ORK_USE_YAML

} // namespace yaml
} // namespace ork
<commit_msg>Combined value xml templates<commit_after>/*
This file is part of the ORK library.
Full copyright and license terms can be found in the LICENSE.txt file.
*/
#pragma once
#include "ork/memory.hpp"
#include "ork/private/text_includes.hpp"
#include "ork/string_utils.hpp"
#include "ork/type_traits.hpp"

#include "glm/fwd.hpp"

namespace ork {

// Serialization tag: basis for a child node
struct tagged {
private:
    ork::bstring _tag;

public:
    ORK_INLINE tagged(const ork::bstring& tag)
        : _tag{tag}
    {}
    ORK_MOVEABLE(tagged);

public:
    ORK_INLINE const ork::bstring& tag() const
    {
        return _tag;
    }
};

#define ORK_OI_DECL_(SUFFIX) \
    class ORK_ORK_API exportable { \
    public: \
        virtual ~exportable() {} \
\
    public: \
        virtual void ORK_CAT(to_, SUFFIX)(node&) const = 0; \
    }; \
    class ORK_ORK_API importable { \
    public: \
        virtual ~importable() {} \
\
    public: \
        virtual void ORK_CAT(from_, SUFFIX)(const node&) = 0; \
    }; \
    class ORK_ORK_API serializable \
        : public exportable \
        , public importable { \
    public: \
        virtual ~serializable() {} \
    };

namespace json {

#if ORK_USE_JSON

using node = Json::Value;
ORK_OI_DECL_(json)

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const node& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, node& root);
ORK_ORK_EXT(node) load_and_parse(bi_stream& fin);

#endif // ORK_USE_JSON

} // namespace json
namespace xml {

#if ORK_USE_PUGI

using node = pugi::xml_node;
ORK_OI_DECL_(xml)

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object, const bstring& root_tag);
ORK_ORK_EXT(void)
export_file_permissive(const string& path_to_file, const bstring& root_tag, const exportable& object);
ORK_ORK_EXT(void)
load_and_parse(bi_stream& fin, pugi::xml_document& root); // Just create a file with error checking
ORK_ORK_EXT(void)
load_and_parse_permissive(const file::path& path_to_file, const bstring& root_tag, importable& object);

/*
These are permissive interfaces
*/
template<typename T>
void value_to_attribute(node& node, const bstring& tag, ORK_CPARAM_T value)
{
    try {
        node.append_attribute(tag.c_str()).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set attribute ") << ORK_BYTE_2_STR(node.name())
            << ORK(":") << ORK_BYTE_2_STR(tag) << ORK(", ") << e.what();
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened setting attribute ")
            << ORK_BYTE_2_STR(node.name()) << ORK(":") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_to_xml(node& node, ORK_CPARAM_T value)
{
    try {
        node.append_child(pugi::node_pcdata).set_value(to_bstring(value).c_str());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to set tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened setting tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}
template<typename T>
void value_to_xml(node& node, const bstring& tag, ORK_CPARAM_T value)
{
    auto n = node.child(tag.c_str());
    value_to_xml<T>(n, value);
}

template<typename T>
void value_from_attribute(const node& node, const bstring& tag, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.attribute(tag.c_str()).value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read parameter ") << ORK_BYTE_2_STR(tag)
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error)
            << ORK("Something happened reading parameter ") << ORK_BYTE_2_STR(tag);
    }
}
template<typename T>
void value_from_xml(const node& node, ORK_REF_T value)
{
    try {
        value = from_string<ORK_VAL_T>(node.child_value());
    }
    catch(std::exception& e) {
        ORK_LOG(severity_level::error)
            << ORK("Failed to read tag ") << ORK_BYTE_2_STR(node.name())
            << ORK(": ") << ORK_BYTE_2_STR(e.what());
    }
    catch(...) {
        ORK_LOG(severity_level::error) << ORK("Something happened reading tag ")
                                       << ORK_BYTE_2_STR(node.name());
    }
}
template<typename T>
void value_from_xml(const node& node, const bstring& tag, ORK_REF_T value)
{
    auto n = node.child(tag.c_str());
    value_from_xml<T>(n, value);
}

// Overloads to eliminate dependency definitions
#    define ORK_XML_SERIALIZE_DECL_(API, TYPE) \
        API(void) \
        to_xml(ork::xml::node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value); \
        API(void) \
        to_attribute( \
            ork::xml::node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value); \
        API(void) \
        from_xml(const ork::xml::node& node, const ork::bstring& tag, ORK_REF(TYPE) value); \
        API(void) \
        from_attribute( \
            const ork::xml::node& node, const ork::bstring& tag, ORK_REF(TYPE) value)

#    define ORK_XML_SERIALIZE_DECL(TYPE) ORK_XML_SERIALIZE_DECL_(ORK_EXT, TYPE)
#    define ORK_ORK_XML_SERIALIZE_DECL(TYPE) \
        ORK_XML_SERIALIZE_DECL_(ORK_ORK_EXT, TYPE)

ORK_ORK_XML_SERIALIZE_DECL(int);
ORK_ORK_XML_SERIALIZE_DECL(unsigned);
ORK_ORK_XML_SERIALIZE_DECL(size_t);
ORK_ORK_XML_SERIALIZE_DECL(float);
ORK_ORK_XML_SERIALIZE_DECL(double);
ORK_ORK_XML_SERIALIZE_DECL(bstring);
ORK_ORK_XML_SERIALIZE_DECL(wstring);

#    define ORK_XML_SERIALIZE_DEF(TYPE) \
        void to_xml(node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value) \
        { \
            ork::xml::value_to_xml<TYPE>(node, tag, value); \
        } \
        void to_attribute(node& node, const ork::bstring& tag, ORK_CPARAM(TYPE) value) \
        { \
            ork::xml::value_to_attribute<TYPE>(node, tag, value); \
        } \
        void from_xml(const node& node, const ork::bstring& tag, ORK_REF(TYPE) value) \
        { \
            ork::xml::value_from_xml<TYPE>(node, tag, value); \
        } \
        void from_attribute( \
            const node& node, const ork::bstring& tag, ORK_REF(TYPE) value) \
        { \
            ork::xml::value_from_xml<TYPE>(node, tag, value); \
        }

#endif // ORK_USE_PUGI

} // namespace xml
namespace yaml {

#if ORK_USE_YAML

using node = YAML::Node;
ORK_OI_DECL_(yaml)

ORK_ORK_EXT(void)
export_file(const string& path_to_file, const node& root);
ORK_ORK_EXT(void)
export_file(const string& path_to_file, const exportable& object);
ORK_ORK_EXT(void) load_and_parse(bi_stream& fin, node& root);
ORK_ORK_EXT(node) load_and_parse(bi_stream& fin);

#endif // ORK_USE_YAML

} // namespace yaml
} // namespace ork
<|endoftext|>