দ্বিতীয় অর্ডার ওডিইজে রঞ্জ-কত্তা পদ্ধতি প্রয়োগ করা হচ্ছে


11

ধ্রুবক মহাকর্ষীয় মাত্রায় নয় (যেমন, ভূগর্ভস্থ 10 000 কিলোমিটার থেকে নিখরচায় পড়ে যাওয়া) পতনের গতি নির্ধারণ করার জন্য আমি কীভাবে রুলে-কত্তা ৪ র্থ ক্রম দিয়ে এলারের পদ্ধতিটি প্রতিস্থাপন করতে পারি?

এখনও অবধি আমি ইউলার পদ্ধতিতে সাধারণ সংহতকরণ লিখেছি:

while()
{
    v += getMagnitude(x) * dt;
    x += v * dt;
    time += dt;
}

এক্স ভেরিয়েবল মানে বর্তমান অবস্থান, v এর অর্থ বেগ, গেটম্যাগনিটিউড (এক্স) এক্স পজিশনে ত্বরণ প্রদান করে।

আমি আর কে 4 বাস্তবায়নের চেষ্টা করেছি:

while()
{
    v += rk4(x, dt) * dt; // rk4() instead of getMagintude()
    x += v * dt;
    time += dt;
}

যেখানে rk4 () ফাংশন বডি:

inline double rk4(double tx, double tdt)
{
   double k1 = getMagnitude(tx);
   double k2 = getMagnitude(tx + 0.5 * tdt * k1);
   double k3 = getMagnitude(tx + 0.5 * tdt * k2);
   double k4 = getMagnitude(tx + tdt * k3);

   return (k1 + 2*k2 + 2*k3 + k4)/6.0;
}

তবে কিছু ভুল, কারণ আমি কেবল একবার আরকে 4 (ত্বরণ) ব্যবহার করে সংহত করছি। আরকে 4 ব্যবহার করে বেগ একীভূত করা অর্থহীন নয় কারণ এটি ভি * ডিটি-র মতো।

আপনি কি আমাকে বলতে পারবেন রানেজ-কত্তা সংহতকরণ ব্যবহার করে দ্বিতীয় অর্ডার ডিফারেন্সিয়াল সমীকরণগুলি কীভাবে সমাধান করবেন? আমি কে 1, এল 1, কে 2, এল 2 ... এল 4 সহগগুলি গণনা করে আর কে 4 বাস্তবায়ন করব? আমি এটা কিভাবে করবো?


হাই @ মার্সিন, আপনার সমস্যাটি আসলে কী তা আমার মনে হয় আরও ভাল প্রতিফলিত করার জন্য আমি আপনার শিরোনাম সম্পাদনা করেছি। আমি মনে করি আমরা আরও কার্যকর উত্তর পেতে পারি এবং এটি অন্যদের জন্য আরও অনুসন্ধানযোগ্য হবে যারা ভবিষ্যতে এই প্রশ্নটি নতুন শিরোনাম সহ দেখেন। আপনি যদি একমত না হন তবে নির্দ্বিধায় এটিকে পরিবর্তন করুন।
ডগ লিপিনস্কি

উত্তর:


17

মাল্টি-স্টেপ (উদাহরণস্বরূপ রঞ্জ-কোট্টা) পদ্ধতিগুলি কীভাবে দ্বিতীয় বা উচ্চতর অর্ডার ওডিইডি বা ওডিইডি সিস্টেমগুলিতে প্রয়োগ করতে হবে তা নিয়ে বেশ বিভ্রান্তি রয়েছে বলে মনে হয়। প্রক্রিয়াটি খুব সহজ হয়ে গেলে আপনি এটি বুঝতে পারবেন, তবে কোনও ভাল ব্যাখ্যা ছাড়াই সম্ভবত সুস্পষ্ট নয়। নিম্নলিখিত পদ্ধতিটি হ'ল আমি সবচেয়ে সহজ।

F=mx¨

[x˙v˙]=[vF/m]

vxk1k4(x,v)

while (t<TMAX)
    k1 = RHS( t, X );
    k2 = RHS( t + dt / 2, X + dt / 2 * k1 );
    k3 = RHS( t + dt / 2, X + dt / 2 * k2 );
    k4 = RHS( t + dt, X + dt * k3 );
    X = X + dt / 6 * ( k1 + 2 * k2 + 2 * k3 + k4 );
    t = t + dt;
end

X=(x,v)RHS( t, X )(x˙(t),v˙(t))

দুর্ভাগ্যক্রমে সি ++ দেশীয়ভাবে ভেক্টর অপারেশনগুলিকে সমর্থন করে না তাই আপনাকে হয় ভেক্টর লাইব্রেরি ব্যবহার করতে হবে, লুপগুলি ব্যবহার করতে হবে বা ম্যানুয়ালি আলাদা অংশগুলি লিখতে হবে। সি ++ এ আপনি std::valarrayএকই প্রভাব অর্জন করতে ব্যবহার করতে পারেন । ধ্রুব ত্বরণ সহ একটি সাধারণ কাজের উদাহরণ এখানে working

#include <valarray>
#include <iostream>

const size_t NDIM = 2;

typedef std::valarray<double> Vector;

Vector RHS( const double t, const Vector X )
{
  // Right hand side of the ODE to solve, in this case:
  // d/dt(x) = v;
  // d/dt(v) = 1;
  Vector output(NDIM);
  output[0] = X[1];
  output[1] = 1;
  return output;
}

int main()
{

  //initialize values

  // State variable X is [position, velocity]
  double init[] = { 0., 0. };
  Vector X( init, NDIM );

  double t = 0.;
  double tMax=5.;
  double dt = 0.1;

  //time loop
  int nSteps = round( ( tMax - t ) / dt );
  for (int stepNumber = 1; stepNumber<=nSteps; ++stepNumber)
  {

    Vector k1 = RHS( t, X );
    Vector k2 = RHS( t + dt / 2.0,  X + dt / 2.0 * k1 );
    Vector k3 = RHS( t + dt / 2.0, X + dt / 2.0 * k2 );
    Vector k4 = RHS( t + dt, X + dt * k3 );

    X += dt / 6.0 * ( k1 + 2.0 * k2 + 2.0 * k3 + k4 );
    t += dt;
  }
  std::cout<<"Final time: "<<t<<std::endl;
  std::cout<<"Final position: "<<X[0]<<std::endl;
  std::cout<<"Final velocity: "<<X[1]<<std::endl;

}

6
" দুর্ভাগ্যক্রমে সি ++ দেশীয়ভাবে ভেক্টর অপারেশনগুলিকে সমর্থন করে না " আমি মনে করি এটি স্ট্যান্ডার্ড লাইব্রেরিতে এমনকি এটি করে, তবে অন্যান্য লিনিয়ার বীজগণিত গ্রন্থাগারগুলির সাথে সহজে ব্যবহার করা সহজ হয় না: en.cppreferences.com/w/cpp/numeric/valarray আমার মনে হয় আইজেনের মতো সাধারণ লিনিয়ার বীজগণিত গ্রন্থাগারগুলিকেও "সমর্থন" হিসাবে গণ্য করা উচিত।
কিরিল

1
@ কিরিল, টিপটির জন্য ধন্যবাদ। আমি এখনও সি ++ তে তুলনামূলকভাবে নতুন এবং আমি আগে ভ্যালারাই ব্যবহার করি নি, আমি খুব দরকারী কিছু শিখেছি! যোগ করার জন্য সম্পাদনা।
ডগ লিপিনস্কি

1
সম্ভবত এই পরামর্শটি তখন সহায়ক হবে: 1) আপনার কোডটি স্বয়ংক্রিয়ভাবে ফর্ম্যাট করার জন্য ঝনঝন-ফর্ম্যাট ব্যবহার করুন, এটি সত্যই আদর্শ এবং অভিন্ন। 2) typedef std::valarray<double> Vectorসাধারণত ব্যবহৃত ধরণের জন্য ব্যবহার করুন । 3) প্রকারের সুরক্ষা এবং নির্ভুলতার const int NDIM = 2পরিবর্তে ব্যবহার করুন #define। 4) সি ++ 11 যেহেতু আপনি কেবল এইচএইচএসের শরীর প্রতিস্থাপন করতে পারেন return {X[1], 1}। ৫) প্রথমে ভেরিয়েবলগুলি ডিক্লেয়ার করার জন্য সি ++ (সি এর বিপরীতে) আসলেই অস্বাভাবিক, পরে সেগুলি আরম্ভ করুন, আপনি যে স্থানে ( double t = 0.ইত্যাদি) সূচনা করেন সেখানে একই স্থানে ভেরিয়েবলগুলি ঘোষণা করতে পছন্দ করুন
ক্যারিল

1
@MarcinW। RHS()ডিফারেনশিয়াল সমীকরণের ডান হাতের পার্ট গণনা করে। রাষ্ট্র ভেক্টর এক্স (x, v) তাই dX / dt = (dx / dt, dv / dt) = (v, a)। আপনার সমস্যার জন্য (যদি a = G * M / x ^ 2) আরএইচএস ফিরে আসা উচিত { X[1], G*M/(X[0]*X[0]) }
ডগ লিপিনস্কি

1
@ কিরিল আমি জানি, তবে এটি কেবল সি ++ 11 সাল থেকে কাজ করে যার অর্থ এটি সর্বাধিক জনপ্রিয় সংকলকগুলির ডিফল্ট সংকলক বিকল্পগুলির সাথে কাজ করে না। আমি এটিকে পুরানো স্ট্যান্ডার্ডগুলির সাথে কাজ করে এমন কোনও কিছুর পক্ষে ছেড়ে যেতে পছন্দ করেছি এবং আশা করি কোডটি সংকলন করতে অক্ষমতার কারণে বিভ্রান্তি হ্রাস করব।
ডগ লিপিনস্কি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.