// обновление шага double new_h(double EPS, double h, double k[K_NUM][VAL_NUM], double x, double y, double u, double v){ double var = Variation(h,k,x,y,u,v); double p = 1.0/(POW + 1.0); while (var > EPS){ h = h*min(max(FAC * pow(EPS/var,p))); new_k(h,k,x,y,u,v); var = Variation(h,k,x,y,u,v); if (h<H_DEFAULT) break; } h = h*min(max(FAC * pow(EPS/var,p))); return h; }
WrfGridValueMap* StoryLineWidget::GetOperationResult(OperationType op_type){ last_operation_elements_.clear(); std::vector< WrfGridValueMap* > elements; for ( int i = 0; i < stamp_items_.size(); ++i ) if ( stamp_items_[i]->is_selected() ){ elements.push_back(WrfDataManager::GetInstance()->GetStoryStamp(stamp_items_[i]->id())); last_operation_elements_.push_back(stamp_items_[i]->id()); } switch (op_type){ case SUM_OP: case MINUS_OP: if ( elements.size() != 2) return NULL; break; case VAR_OP: if ( elements.size() < 2 ) return NULL; break; default: return NULL; break; } if ( result_value_map_ == NULL ){ result_value_map_ = new WrfGridValueMap; result_value_map_->start_latitude = elements[0]->start_latitude; result_value_map_->end_latitude = elements[0]->end_latitude; result_value_map_->start_longitude = elements[0]->start_longitude; result_value_map_->end_longitude = elements[0]->end_longitude; result_value_map_->latitude_grid_number = elements[0]->latitude_grid_number; result_value_map_->longitude_grid_number = elements[0]->longitude_grid_number; result_value_map_->latitude_grid_space = elements[0]->latitude_grid_space; result_value_map_->longitude_grid_space = elements[0]->longitude_grid_space; result_value_map_->max_value = elements[0]->max_value; result_value_map_->min_value = elements[0]->min_value; result_value_map_->values.resize(elements[0]->longitude_grid_number * elements[0]->latitude_grid_number); } switch (op_type){ case SUM_OP: SumMap(elements); break; case MINUS_OP: Minius(elements); break; case VAR_OP: Variation(elements); break; default: return NULL; break; } int temp_level = -1; for ( int i = 0; i < elements.size(); ++i ) if ( elements[i]->level > temp_level ) temp_level = elements[i]->level; result_value_map_->level = temp_level + 1; return result_value_map_; }
// Основная функция. На вход: EPS --- порядок погрешности // filename --- файл для вывода, local --- значения локальной погрешности в точках int runge(double *global_error, double EPS, const char*filename, double local[CHECK_POSITIONS * VAL_NUM ]) { double x,y,u,v; // x y a b double h=0; double k[K_NUM][VAL_NUM]; // числа рунге int errflag = 0; int check_time = CHECK_POSITIONS; // количество оставшихся точек на временной шкале для проверки лок погрешности int flag = 0; double h_next = 0; // механическая переменная для хранения следующего шага *global_error = 0; FILE *file = fopen(filename, "w"); if (file == NULL) errflag = -1; else{ fprintf(file, "t, x, y\n"); //вводим начальные условия x = x0; y = y0; u = u0; v = v0; h = EPS/h0; new_k(h,k,x,y,u,v); // начальные числа Рунге h = new_h(EPS,h,k,x,y,u,v); // обновляем шаг new_k(h,k,x,y,u,v); // ежели он изменился -- обновим числа Рунге for (double t = 0;t<=WORK_TIME+h;t+=h){ // если мы в нужной точке T, 3T/4, T/2, T/4, то flag == 1 if (flag == 0) if (check_time > 0) // если меньше, то точек не осталось, увы if ((nearest(t) - t <= h)&&(nearest(t) - t >= 0)){ // если мы сюда попали, то расстояние до нужной точки меньше h // объявим следующий шаг этим расстоянием h_next = nearest(t) - t; } //подсчет глобальной погрешности (*global_error) = Variation(h,k,x,y,u,v) + (*global_error) * exp_int(h,x,y); // обновляем координаты x = new_parametr(h,x,k,x,y,u,v,0); y = new_parametr(h,y,k,x,y,u,v,1); u = new_parametr(h,u,k,x,y,u,v,2); v = new_parametr(h,v,k,x,y,u,v,3); fprintf(file, "%e, %e, %e\n", t,x,y); // если мы в нужной точке T, 3T/4, T/2, T/4, то flag == 1 if (flag == 1) { local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time)] = x; local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time) + 1] = y; local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time) + 2] = u; local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time) + 3] = v; h = h_next; // возвращаем исходное значение шага h_next = 0; flag = 0; check_time--; // мы же уже дошли до этой точке, осталось на одну меньше } h = new_h(EPS,h,k,x,y,u,v); //обновляем шаг if (h_next != 0){ double p; p = h; h = h_next; h_next = p;//сохраняем предыдуший шаг на случай, если новый слишком маленький flag = 1; // для того, чтобы мы видели вывод } new_k(h,k,x,y,u,v); //обновляем числа Рунге if (h<H_DEFAULT) {errflag = -2; break;} // на случай особых точек } } printf("final step = %e;\n", h); fclose(file); return errflag; }