All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.meliorbis.numerics.function.primitives.DoubleRectangularGridDomain Maven / Gradle / Ivy

Go to download

A library for working with large multi-dimensional arrays and the functions they represent

There is a newer version: 1.2
Show newest version
package com.meliorbis.numerics.function.primitives;

import java.util.Arrays;
import java.util.List;

import com.meliorbis.numerics.DoubleArrayFactories;
import com.meliorbis.numerics.function.grid.RectangularGridDomain;
import com.meliorbis.numerics.function.grid.RectangularGridFunction;
import com.meliorbis.numerics.generic.MultiDimensionalArray;
import com.meliorbis.numerics.generic.primitives.DoubleArray;
import com.meliorbis.numerics.generic.primitives.impl.Interpolation;

/**
 * The domain of a function defined over a rectangular grid, interpolating at intermediate points
 * 
 * @author Tobias Grasl
 */
public class DoubleRectangularGridDomain implements RectangularGridDomain>
{
	private final DoubleArray[] _gridPoints;
	private final int[] _valuesSize;
	private DoubleGridFunctionFactory _factory;
	
	DoubleRectangularGridDomain(DoubleArray[] gridPoints_, DoubleGridFunctionFactory factory_)
	{
		_gridPoints = gridPoints_;
		_factory = factory_;
		
		_valuesSize = initValuesSize();
	}
	
	private int[] initValuesSize()
	{
		// Create an array with enough elements for the input sizes plus the number of output variables
		int[] _size = new int[_gridPoints.length + 1];
		
		for (int i = 0; i < _gridPoints.length; i++)
		{
			_size[i] = _gridPoints[i].numberOfElements();
		}
		
		// Set the default output length to 1
		_size[_gridPoints.length] = 1;
		
		return _size;
	}

	public DoubleRectangularGridDomain(List> gridPoints_, DoubleGridFunctionFactory factory_)
	{
		this(gridPoints_.toArray(new DoubleArray[gridPoints_.size()]), factory_);
	}

	/**
	 * @return The axes of the rectangular grid over which this function is defined
	 */
	public DoubleArray[] getGridPoints()
	{
		return _gridPoints;
	}

	@Override
	public int getNumberOfDimensions()
	{
		return _gridPoints.length;
	}
	
	@Override
	public DoubleArray getAxis(int dimension_)
	{
		return _gridPoints[dimension_];
	}

	@Override
	public DoubleArray createValueGrid(int outputDims_)
	{
		int[] size;
		
		/* Thread safety demands that we do not modify the member array willy-nilly
		 * Hence use that directly if it fits, else clone it and set the output size
		 * appropriately if not
		 */
		if(outputDims_ == 1)
		{
			size = _valuesSize;
		}
		else
		{
			size = _valuesSize.clone();
			size[getNumberOfDimensions()] = outputDims_;
		}
		
		return DoubleArrayFactories.createArrayOfSize(size);
	}

	@Override
	public DoubleArray createValueGrid()
	{
		return createValueGrid(1);
	}

	/**
	 * @see com.meliorbis.numerics.function.grid.RectangularGridDomain#interpolateToGrid(int, com.meliorbis.numerics.generic.MultiDimensionalArray, com.meliorbis.numerics.generic.MultiDimensionalArray)
	 */
	@Override
	public > RectangularGridFunction interpolateToGrid(int axis_, DoubleArray nonRectangularDomainValues_, OA values_)
	{
		return interpolateToGrid(axis_, nonRectangularDomainValues_, values_, false);
	}
	
	/**
	 * Given a function with output values {@code values_} and input values on the grid points in this domain, except in dimension {@code axis_}, where
	 * the inputs are assumed non-rectangular and given by {@code nonRectangularDomainValues_}, this method will interpolate that exceptional dimension 
	 * onto the grid and return the resulting rectangular grid function.
	 * 
	 * The function can be constrained, meaning that the first y value (along each line) is considered the extreme value. Any target x values lying before the first source x will then be
	 * assigned that value, rather than using an extrapolated one.
	 * 
	 * @param axis_ The dimension along which to perform the mapping
	 * @param nonRectangularDomainValues_ The input values along dimension {@code axis_} for each point orthogonal to that axis.
	 * @param values_ The values at the points defined by this domain's grid except in dimension {@code axis_}, where the input values are in
	 * {@code nonRectangularDomainValues_}
	 * @param constrained_ If true, the constraint mechanism is applied.
	 * 
	 * @return A function on this domain that corresponds to the mapping defined by the two arrays passed
	 * 
	 * @param  The output value type
	 * @param  The array type to use to hold the outputs
	 */
	@SuppressWarnings("unchecked")
	@Override
	public > RectangularGridFunction interpolateToGrid(int axis_, DoubleArray nonRectangularDomainValues_, OA values_, boolean constrained_)
	{
		assert Arrays.equals(nonRectangularDomainValues_.size(), values_.size()) : "The arrays must be of equal size";
		assert axis_ < nonRectangularDomainValues_.numberOfDimensions() : "Axis must be in range";
		assert nonRectangularDomainValues_.numberOfDimensions() == getNumberOfDimensions() : "Number of dimensions of inputs and domain must equal";
		
		if(!(values_ instanceof DoubleArray))
		{
			throw new IllegalArgumentException("This implementation only works with IDoubleArray values arrays");
		}
		
		DoubleArray values = (DoubleArray) values_;
		
		// Interpolate the function to the 
		DoubleArray valuesOnGrid = Interpolation.interpolateFunction(nonRectangularDomainValues_, values, axis_, _gridPoints[axis_], new Interpolation.Params().constrained());
		
		return (RectangularGridFunction) _factory.createFunction(this, valuesOnGrid);
	}

	@Override
	public boolean equals(Object obj_)
	{
		if(!(obj_ instanceof DoubleRectangularGridDomain))
		{
			return false;
		}
		
		DoubleRectangularGridDomain other = (DoubleRectangularGridDomain) obj_;
		
		return Arrays.equals(_gridPoints, other._gridPoints);
	}
	
	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy