bool ParametricCurveTests::testTransfiniteInterpolant() { bool success = true; // to begin, just let's do a simple quad mesh double width=4, height=3; double x0 = 0, y0 = 0; double x1 = width, y1 = 0; double x2 = width, y2 = height; double x3 = 0, y3 = height; vector< ParametricCurvePtr > edges(4); edges[0] = ParametricCurve::line(x0, y0, x1, y1); edges[1] = ParametricCurve::line(x1, y1, x2, y2); edges[2] = ParametricCurve::line(x2, y2, x3, y3); edges[3] = ParametricCurve::line(x3, y3, x0, y0); ParametricSurfacePtr transfiniteInterpolant = ParametricSurface::transfiniteInterpolant(edges); double x0_actual, y0_actual, x2_actual, y2_actual; transfiniteInterpolant->value(0, 0, x0_actual, y0_actual); transfiniteInterpolant->value(1, 1, x2_actual, y2_actual); double tol=1e-14; if ((abs(x0_actual-x0) > tol) || (abs(y0_actual-y0) > tol)) { success = false; cout << "transfinite interpolant doesn't interpolate (x0,y0).\n"; } if ((abs(x2_actual-x2) > tol) || (abs(y2_actual-y2) > tol)) { success = false; cout << "transfinite interpolant doesn't interpolate (x2,y2).\n"; } // the transfinite interpolant should be just (4t1, 3t2) FunctionPtr t1 = Function::xn(1); FunctionPtr t2 = Function::yn(1); FunctionPtr xPart = 4 * t1; FunctionPtr yPart = 3 * t2; FunctionPtr expected_tfi = Function::vectorize(xPart, yPart); int cubatureDegree = 4; BasisCachePtr parametricCache = BasisCache::parametricQuadCache(cubatureDegree); // a couple quick sanity checks: if (! expected_tfi->equals(expected_tfi, parametricCache)) { success = false; cout << "ERROR in Function::equals(): vector Function does not equal itself.\n"; } if (! transfiniteInterpolant->equals(transfiniteInterpolant, parametricCache)) { success = false; cout << "Weird error: transfiniteInterpolant does not equal itself.\n"; } // check that the transfiniteInterpolant's value() method matches values() { int numCells = 1; int numPoints = parametricCache->getRefCellPoints().dimension(0); int spaceDim = 2; FieldContainer<double> values(numCells,numPoints,spaceDim); transfiniteInterpolant->values(values, parametricCache); int cellIndex = 0; for (int ptIndex=0; ptIndex<numPoints; ptIndex++) { double t1 = parametricCache->getPhysicalCubaturePoints()(cellIndex,ptIndex,0); double t2 = parametricCache->getPhysicalCubaturePoints()(cellIndex,ptIndex,1); double x, y; transfiniteInterpolant->value(t1, t2, x, y); double x_expected = values(cellIndex,ptIndex,0); double y_expected = values(cellIndex,ptIndex,1); if (abs(x-x_expected) > tol) { cout << "transfinite interpolant value() does not match values()\n"; success = false; } if (abs(y-y_expected) > tol) { cout << "transfinite interpolant value() does not match values()\n"; success = false; } } } if (! expected_tfi->equals(transfiniteInterpolant, parametricCache, tol)) { cout << "transfinite interpolant doesn't match expected.\n"; success = false; int numCells = 1; int numPoints = parametricCache->getRefCellPoints().dimension(0); int spaceDim = 2; FieldContainer<double> values(numCells,numPoints,spaceDim); FieldContainer<double> expected_values(numCells,numPoints,spaceDim); expected_tfi->values(expected_values, parametricCache); transfiniteInterpolant->values(values, parametricCache); reportFunctionValueDifferences(parametricCache->getPhysicalCubaturePoints(), expected_values, values, tol); } // derivatives FunctionPtr xPart_dt1 = Function::constant(4); FunctionPtr yPart_dt1 = Function::constant(0); FunctionPtr expected_tfi_dt1 = Function::vectorize(xPart_dt1, yPart_dt1); if (! expected_tfi_dt1->equals(transfiniteInterpolant->dt1(), parametricCache, tol)) { cout << "d/dt1 of transfinite interpolant doesn't match expected.\n"; success = false; int numCells = 1; int numPoints = parametricCache->getRefCellPoints().dimension(0); int spaceDim = 2; FieldContainer<double> values(numCells,numPoints,spaceDim); FieldContainer<double> expected_values(numCells,numPoints,spaceDim); expected_tfi_dt1->values(expected_values, parametricCache); transfiniteInterpolant->dt1()->values(values, parametricCache); reportFunctionValueDifferences(parametricCache->getPhysicalCubaturePoints(), expected_values, values, tol); } FunctionPtr xPart_dt2 = Function::constant(0); FunctionPtr yPart_dt2 = Function::constant(3); FunctionPtr expected_tfi_dt2 = Function::vectorize(xPart_dt2, yPart_dt2); if (! expected_tfi_dt2->equals(transfiniteInterpolant->dt2(), parametricCache, tol)) { cout << "d/dt2 of transfinite interpolant doesn't match expected.\n"; success = false; int numCells = 1; int numPoints = parametricCache->getRefCellPoints().dimension(0); int spaceDim = 2; FieldContainer<double> values(numCells,numPoints,spaceDim); FieldContainer<double> expected_values(numCells,numPoints,spaceDim); expected_tfi_dt2->values(expected_values, parametricCache); transfiniteInterpolant->dt2()->values(values, parametricCache); reportFunctionValueDifferences(parametricCache->getPhysicalCubaturePoints(), expected_values, values, tol); } BasisCachePtr physicalBasisCache = BasisCache::quadBasisCache(width, height, cubatureDegree); FunctionPtr one = Function::constant(1); FunctionPtr expected_tfi_dx = Function::vectorize(one, Function::zero()); FunctionPtr expected_tfi_dy = Function::vectorize(Function::zero(), one); FunctionPtr expected_tfi_grad = Function::vectorize(expected_tfi_dx, expected_tfi_dy); if (! expected_tfi_grad->equals(transfiniteInterpolant->grad(), physicalBasisCache, tol)) { cout << "grad of transfinite interpolant doesn't match expected.\n"; success = false; int numCells = 1; int numPoints = physicalBasisCache->getRefCellPoints().dimension(0); int spaceDim = 2; FieldContainer<double> values(numCells,numPoints,spaceDim,spaceDim); FieldContainer<double> expected_values(numCells,numPoints,spaceDim,spaceDim); expected_tfi_grad->values(expected_values, physicalBasisCache); transfiniteInterpolant->grad()->values(values, physicalBasisCache); reportFunctionValueDifferences(physicalBasisCache->getPhysicalCubaturePoints(), expected_values, values, tol); } return success; }
void ProcessRemovalsByLength::Execute() { LOG_TRACE(); /** * Verify our cached partition and partition sizes are correct */ // auto categories = model_->categories(); unsigned year = model_->current_year(); unsigned year_index = year - model_->start_year(); unsigned time_step = model_->managers().time_step()->current_time_step(); auto cached_partition_iter = cached_partition_->Begin(); auto partition_iter = partition_->Begin(); // vector<vector<partition::Category> > map<unsigned, map<string, map<string, vector<Double>>>> &Removals_at_age = mortality_instantaneous_->catch_at(); /** * Loop through the provided categories. Each provided category (combination) will have a list of observations * with it. We need to build a vector of proportions for each length using that combination and then * compare it to the observations. */ for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { LOG_FINEST() << "category: " << category_labels_[category_offset]; Double start_value = 0.0; Double end_value = 0.0; Double number_at_age = 0.0; // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; vector<Double> expected_values(number_bins_, 0.0); vector<Double> numbers_at_length; vector<vector<Double>> age_length_matrix; /** * Loop through the 2 combined categories building up the * expected proportions values. */ auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { // AgeLength* age_length = categories->age_length((*category_iter)->name_); // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; age_length_matrix.resize((*category_iter)->data_.size()); vector<Double> age_frequencies(length_bins_.size(), 0.0); const auto& age_length_proportions = model_->partition().age_length_proportions((*category_iter)->name_)[year_index][time_step]; for (unsigned data_offset = 0; data_offset < (*category_iter)->data_.size(); ++data_offset) { unsigned age = ((*category_iter)->min_age_ + data_offset); // Calculate the age structure removed from the fishing process number_at_age = Removals_at_age[year][method_][(*category_iter)->name_][data_offset]; LOG_FINEST() << "Numbers at age = " << age << " = " << number_at_age << " start value : " << start_value << " end value : " << end_value; // Implement an algorithm similar to DoAgeLengthConversion() to convert numbers at age to numbers at length // This is different to DoAgeLengthConversion as this number is now not related to the partition // Double mu= (*category_iter)->mean_length_by_time_step_age_[time_step][age]; // LOG_FINEST() << "mean = " << mu << " cv = " << age_length->cv(year, time_step, age) << " distribution = " << age_length->distribution_label() << " and length plus group = " << length_plus_; // age_length->CummulativeNormal(mu, age_length->cv(year, time_step, age), age_frequencies, length_bins_, length_plus_); // LOG_WARNING() << "This is bad code because it allocates memory in the middle of an execute"; age_length_matrix[data_offset].resize(number_bins_); // Loop through the length bins and multiple the partition of the current age to go from // length frequencies to age length numbers for (unsigned j = 0; j < number_bins_; ++j) { age_length_matrix[data_offset][j] = number_at_age * age_length_proportions[data_offset][j]; LOG_FINEST() << "The proportion of fish in length bin : " << length_bins_[j] << " = " << age_frequencies[j]; } } if (age_length_matrix.size() == 0) LOG_CODE_ERROR()<< "if (age_length_matrix_.size() == 0)"; numbers_at_length.assign(age_length_matrix[0].size(), 0.0); for (unsigned i = 0; i < age_length_matrix.size(); ++i) { for (unsigned j = 0; j < age_length_matrix[i].size(); ++j) { numbers_at_length[j] += age_length_matrix[i][j]; } } for (unsigned length_offset = 0; length_offset < number_bins_; ++length_offset) { LOG_FINEST() << " numbers for length bin : " << length_bins_[length_offset] << " = " << numbers_at_length[length_offset]; expected_values[length_offset] += numbers_at_length[length_offset]; LOG_FINE() << "----------"; LOG_FINE() << "Category: " << (*category_iter)->name_ << " at length " << length_bins_[length_offset]; LOG_FINE() << "start_value: " << start_value << "; end_value: " << end_value << "; final_value: " << numbers_at_length[length_offset]; LOG_FINE() << "expected_value becomes: " << expected_values[length_offset]; } } if (expected_values.size() != proportions_[model_->current_year()][category_labels_[category_offset]].size()) LOG_CODE_ERROR()<< "expected_values.size(" << expected_values.size() << ") != proportions_[category_offset].size(" << proportions_[model_->current_year()][category_labels_[category_offset]].size() << ")"; /** * save our comparisons so we can use them to generate the score from the likelihoods later */ for (unsigned i = 0; i < expected_values.size(); ++i) { SaveComparison(category_labels_[category_offset], 0, length_bins_[i], expected_values[i], proportions_[model_->current_year()][category_labels_[category_offset]][i], process_errors_by_year_[model_->current_year()], error_values_[model_->current_year()][category_labels_[category_offset]][i], 0.0, delta_, 0.0); } } }
void ProportionsMigrating::Execute() { LOG_TRACE(); /** * Verify our cached partition and partition sizes are correct */ auto cached_partition_iter = cached_partition_->Begin(); auto partition_iter = partition_->Begin(); // vector<vector<partition::Category> > /** * Loop through the provided categories. Each provided category (combination) will have a list of observations * with it. We need to build a vector of proportions for each age using that combination and then * compare it to the observations. */ LOG_FINEST() << "Number of categories " << category_labels_.size(); for (unsigned category_offset = 0; category_offset < category_labels_.size(); ++category_offset, ++partition_iter, ++cached_partition_iter) { Double start_value = 0.0; Double end_value = 0.0; vector<Double> expected_values(age_spread_, 0.0); vector<Double> numbers_age_before((model_->age_spread() + 1), 0.0); vector<Double> numbers_age_after((model_->age_spread() + 1), 0.0); /** * Loop through the 2 combined categories building up the * expected proportions values. */ auto category_iter = partition_iter->begin(); auto cached_category_iter = cached_partition_iter->begin(); for (; category_iter != partition_iter->end(); ++cached_category_iter, ++category_iter) { for (unsigned data_offset = 0; data_offset < (*category_iter)->data_.size(); ++data_offset) { // We now need to loop through all ages to apply ageing misclassification matrix to account // for ages older than max_age_ that could be classified as an individual within the observation range unsigned age = ( (*category_iter)->min_age_ + data_offset); start_value = (*cached_category_iter).data_[data_offset]; end_value = (*category_iter)->data_[data_offset]; numbers_age_before[data_offset] += start_value; numbers_age_after[data_offset] += end_value; LOG_FINE() << "----------"; LOG_FINE() << "Category: " << (*category_iter)->name_ << " at age " << age; LOG_FINE() << "start_value: " << start_value << "; end_value: " << end_value; } } /* * Apply Ageing error on numbers at age before and after */ if (ageing_error_label_ != "") { vector<vector<Double>>& mis_matrix = ageing_error_->mis_matrix(); vector<Double> temp_before(numbers_age_before.size(), 0.0); vector<Double> temp_after(numbers_age_after.size(), 0.0); for (unsigned i = 0; i < mis_matrix.size(); ++i) { for (unsigned j = 0; j < mis_matrix[i].size(); ++j) { temp_before[j] += numbers_age_before[i] * mis_matrix[i][j]; temp_after[j] += numbers_age_after[i] * mis_matrix[i][j]; } } numbers_age_before = temp_before; numbers_age_after = temp_after; } /* * Now collapse the number_age into out expected values */ Double plus_before = 0, plus_after = 0; for (unsigned k = 0; k < numbers_age_before.size(); ++k) { // this is the difference between the unsigned age_offset = min_age_ - model_->min_age(); if (numbers_age_before[k] > 0) { if (k >= age_offset && (k - age_offset + min_age_) <= max_age_) { expected_values[k - age_offset] = (numbers_age_before[k] - numbers_age_after[k]) / numbers_age_before[k]; LOG_FINEST() << "Numbers before migration = " << numbers_age_before[k] << " numbers after migration = " << numbers_age_after[k] << " proportion migrated = " << expected_values[k - age_offset]; } if (((k - age_offset + min_age_) > max_age_) && age_plus_) { plus_before += numbers_age_before[k]; plus_after += numbers_age_after[k]; } } else { if (k >= age_offset && (k - age_offset + min_age_) <= max_age_) expected_values[k] = 0; if (((k - age_offset + min_age_) > max_age_) && age_plus_) { plus_before += 0; plus_after += 0; } } } LOG_FINEST() << "Plus group before migration = " << plus_before << " Plus group after migration = " << plus_after; if (age_plus_) expected_values[age_spread_ - 1] = (plus_before - plus_after) / plus_before; if (expected_values.size() != proportions_[model_->current_year()][category_labels_[category_offset]].size()) LOG_CODE_ERROR() << "expected_values.size(" << expected_values.size() << ") != proportions_[category_offset].size(" << proportions_[model_->current_year()][category_labels_[category_offset]].size() << ")"; /** * save our comparisons so we can use them to generate the score from the likelihoods later */ for (unsigned i = 0; i < expected_values.size(); ++i) { LOG_FINEST() << " Numbers at age " << min_age_ + i << " = " << expected_values[i]; SaveComparison(category_labels_[category_offset], min_age_ + i ,0.0 ,expected_values[i], proportions_[model_->current_year()][category_labels_[category_offset]][i], process_errors_by_year_[model_->current_year()], error_values_[model_->current_year()][category_labels_[category_offset]][i], delta_, 0.0); } } }