গণনাপদ্ধতি · বার্ষিক গ্রহগণিত · প্রবন্ধ ৪০
মেষ সংক্রান্তিতে বার্ষিক গ্রহগণনা: অব্দপিণ্ড, দিনবৃন্দ ও মধ্যগ্রহ report কীভাবে তৈরি হয়?
একটি বাংলা সৌরবছর শুরু হয় সূর্যের মেষ রাশিতে প্রবেশকে কেন্দ্র করে। সেই exact instant-কে anchor করে অব্দপিণ্ড, দিনবৃন্দ বা অহর্গণ, বীজ, দেশান্তর এবং প্রতিটি গ্রহের মধ্যস্থান প্রকাশ করলে বার্ষিক report শুধু ফল দেখায় না—পুরো গণনাটিই যাচাইযোগ্য করে তোলে।
মূলনীতি: year-start anchor নির্ধারণ, classical mean-planet calculation এবং publication formatting—এই তিনটি পৃথক stage। Modern Saṅkrānti fit anchor-এ ব্যবহার হলেও planetary constants নিজে থেকে বদলাবে না।
কেন মেষ সংক্রান্তি বার্ষিক report-এর anchor?
বাংলা সৌরবছরের প্রথম মাস বৈশাখ এবং তার solar boundary হলো Meṣa Saṅkrānti—নিরয়ণ সূর্যের মেষ রাশিতে প্রবেশ। তাই “বাংলা বছর ১৪৩৩-এর আরম্ভে গ্রহগুলোর মধ্যস্থান কত ছিল?” প্রশ্নের স্বাভাবিক reference instant হলো ঐ বছরের মেষ-প্রবেশ।
এটি civil day-এর শুরু নয়। Saṅkrānti দুপুর, সন্ধ্যা বা রাত্রিতেও ঘটতে পারে। ফলে report-এ শুধু “১ বৈশাখ” লিখলে যথেষ্ট নয়; অন্তত UTC instant, selected local time, Julian Day এবং calendar label দিতে হবে।
| Reference | কী বোঝায় | Report-এ ভূমিকা |
|---|---|---|
| Saṅkrānti instant | সূর্যের sign boundary crossing | Primary computational anchor |
| বাংলা ১ বৈশাখ | Project-এর sunrise/civil-day rule-এ নির্ধারিত তারিখ | Calendar label |
| Gregorian/Julian date | একই instant-এর civil calendar representation | User-facing historical label |
| Julian Day | Continuous astronomical day count | Reproducible machine anchor |
Exact instant নির্বাচন: আনুমানিক বছর নয়, solar root
বাংলা বছর থেকে Gregorian search seed অনুমান করা যায়—যেমন প্রথম বাংলা বছর ঐতিহাসিকভাবে ৫৯৪ খ্রিস্টাব্দের অঞ্চলে পড়ে। কিন্তু final instant কখনও শুধু bengaliYear + 593 করে বানানো উচিত নয়। Calendar conversion, historical dual-date display এবং month-start rule আলাদা বিষয়; solar boundary engine-কেই মেষ-প্রবেশ solve করতে হবে।
নিরাপদ search procedure
- বাংলা বছর ও location validate করুন;
- একটি generous Gregorian search window তৈরি করুন;
- নিরয়ণ solar longitude-এর ০° crossing bracket করুন;
- Bisection/approved root solver দিয়ে exact instant বের করুন;
- সেই instant থেকে local date ও Bengali month-start rule চালান;
- Result যে Meṣa এবং সংশ্লিষ্ট Bengali year—assert করুন;
- JD, UTC, local time, profile ও rule trace সংরক্ষণ করুন।
গুরুত্বপূর্ণ: report anchor-এর local date এবং বাংলা ১ বৈশাখের civil date এক নাও হতে পারে। Crossing instant আগে/পরে হওয়ার ওপর calendar policy নতুন মাসের প্রথম দিন নির্ধারণ করে। দুটো field আলাদা রাখুন।
Anchor profile এবং planet profile আলাদা রাখুন
এই project-এ ১৯৪৭ এবং পরবর্তী Gregorian বছরে printed Panjika alignment-এর জন্য month-specific Modern Sankranti Star Fit ব্যবহৃত হয়। Meṣa-র delta +31। কিন্তু এই adjustment-এর scope Saṅkrānti ও Bengali date boundary; Moon, tithi, nakshatra, yoga, karana বা displayed planet positions নয়।
| Metadata | Historical report | ১৯৪৭+ publication report |
|---|---|---|
anchor_profile | classical-base | modern-star-fit-1947-v1 |
anchor_star_delta | ০ | Meṣa: +31 internal units |
planet_profile | classical-bija বা selected classical profile | একই classical profile |
| Tithi/Nakshatra profile | Unmodified Panchanga engine | Unmodified Panchanga engine |
এভাবে report স্পষ্টভাবে বলতে পারে: “Year anchor printed modern Saṅkrānti fit দিয়ে নির্ধারিত; ঐ exact instant-এ planets classical constants দিয়ে গণিত।” Anchor সময় সামান্য বদলালে planets-এর longitude সময়ের কারণে সামান্য বদলবে—কিন্তু planet constants বদলায়নি। এই distinction-টিই audit-এর জন্য জরুরি।
অব্দপিণ্ড, দিনবৃন্দ, অহর্গণ, বীজ ও দেশান্তর
একই শব্দ বিভিন্ন handbook বা code-port-এ সামান্য ভিন্ন intermediate বোঝাতে পারে। তাই report-এর label engine-এর actual variable ও formula-র সঙ্গে মিলিয়ে লিখতে হবে। নিচের সংজ্ঞাগুলো architectural guide—আপনার source algorithm-এর exact divisor, epoch ও unit-ই authoritative।
অব্দপিণ্ড (Abda-piṇḍa)
Year-related accumulated বা reduced quantity, যা epoch থেকে নির্বাচিত বছরের অবস্থান নির্ণয়ে ব্যবহৃত হয়। এটি সব implementation-এ সরাসরি “বছরের সংখ্যা” নয়। Raw integer, divisor, quotient ও remainder থাকলে সবগুলো trace-এ রাখা উচিত।
দিনবৃন্দ / অহর্গণ (Dinabrinda / Ahargaṇa)
নির্ধারিত epoch থেকে elapsed civil/astronomical days অথবা algorithm-specific reduced day count। Exact instant report-এ integral day এবং fractional day আলাদা রাখলে rounding error ধরা সহজ হয়।
A = JDanchor − JDepoch
Awhole = floor(A)
Afraction = A − Awhole
যদি classical algorithm civil sunrise থেকে day count করে, modern midnight-based JD fraction সরাসরি তার জায়গায় বসাবেন না। প্রথমে engine-এর epoch convention অনুযায়ী instant transform করুন।
বীজ (Bīja)
Mean-motion বা epoch parameter-এর documented correction। এটি final longitude-এ ইচ্ছামতো degree যোগ নয়। Report-এ base value, correction, corrected value এবং unit দিতে হবে।
দেশান্তর (Deśāntara)
Reference meridian এবং observer-এর longitude-এর পার্থক্যজনিত local-time/longitude correction। এটি civil time-zone offset নয়। Modern time zone রাজনৈতিক clock convention; deśāntara একটি astronomical locality correction।
Approximate local-time difference = longitude difference × 4 minutes per degree
Sign = declared reference meridian ও east/west convention অনুযায়ী
একটি ষোড়শ-শতকের karaṇa-text বিশ্লেষণে deśāntara observer-এর স্থান ও prime meridian-এর পার্থক্য হিসেবে বর্ণিত এবং দ্রুতগতির কারণে Moon-এর mean longitude-এ প্রয়োগ দেখানো হয়েছে। আপনার Surya Siddhanta port অন্য scope ব্যবহার করলে report-এ সেই exact convention লিখুন—generic rule অনুমান করবেন না।
মধ্যগ্রহ (Mean planets)
Epoch থেকে uniform mean motion accumulate করে পাওয়া longitude। একটি conceptual form:
λ̄ = normalize(λ̄epoch + A · n + B)
n = mean daily motion; B = documented bīja/epoch term
Traditional engine-এ A · n প্রায়ই huge integer revolution counts ও cycle-day divisor থেকে আসে। Display-এর আগে modulo করুন; intermediate-এর আগে নয়। যতদিন সম্ভব integer/rational numerator ও denominator রাখুন।
একটি reproducible calculation pipeline
| Stage | Input | Output | Must record |
|---|---|---|---|
| ১. Request | বাংলা বছর, location | Validated request | Lat, lon, time-zone ID |
| ২. Anchor | Year, solar engine, profile | Meṣa crossing | UTC, local, JD, root tolerance |
| ৩. Calendar label | Anchor + month rule | ১ বৈশাখ date | Applied rule |
| ৪. Epoch reduction | Anchor JD | Abda-piṇḍa, Dinabrinda/Ahargaṇa | Epoch, quotient, remainder |
| ৫. Locality | Reference & local longitude | Deśāntara | Reference meridian, sign, unit |
| ৬. Mean motion | Day count + planet constants | Mean longitudes | Revolutions, divisor, bīja |
| ৭. Optional true | Mean places | Manda/śīghra corrected places | Every correction stage |
| ৮. Render | Typed report model | HTML/XML | Version, generated time |
C# 5-compatible data model
public sealed class YearStartAnchor
{
public int BengaliYear { get; set; }
public DateTime InstantUtc { get; set; }
public DateTime InstantLocal { get; set; }
public double JulianDayUt { get; set; }
public string TimeZoneId { get; set; }
public string GregorianLabel { get; set; }
public string JulianLabel { get; set; }
public string BengaliFirstDayLabel { get; set; }
public string AppliedRule { get; set; }
public string AnchorProfile { get; set; }
public int AnchorStarDelta { get; set; }
}
public sealed class ClassicalYearTrace
{
public string EpochName { get; set; }
public string AbdaPindaRaw { get; set; }
public string DinabrindaRaw { get; set; }
public long AharganaWhole { get; set; }
public double AharganaFraction { get; set; }
public string DeshantaraRaw { get; set; }
public string DeshantaraSignRule { get; set; }
public string BijaProfile { get; set; }
}
public sealed class MeanPlanetRow
{
public string Key { get; set; }
public string NameBn { get; set; }
public string RevolutionNumerator { get; set; }
public string CycleDayDenominator { get; set; }
public string EpochTerm { get; set; }
public string BijaTerm { get; set; }
public double MeanLongitude { get; set; }
public string MeanLongitudeFormatted { get; set; }
}
public sealed class YearlyPlanetReport
{
public YearStartAnchor Anchor { get; set; }
public ClassicalYearTrace Trace { get; set; }
public IList<MeanPlanetRow> MeanPlanets { get; set; }
public string PlanetProfile { get; set; }
public string EngineVersion { get; set; }
}
Raw fields string রাখা ইচ্ছাকৃত: classical calculation-এর বড় integer বা exact fraction double-এ হারিয়ে না ফেলে serialise করা যায়। Numerical field chart/sorting-এর সুবিধার জন্য আলাদা থাকে।
C# service workflow
১. Year-start resolve করুন
public YearStartAnchor ResolveYearStart(
int bengaliYear,
DesktopLocation location)
{
if (bengaliYear < 1)
throw new ArgumentOutOfRangeException("bengaliYear");
SankrantiResult crossing = sankrantiService.FindMeshaForBengaliYear(
bengaliYear,
location);
if (crossing == null || crossing.SolarMonth != SolarMonth.Mesha)
throw new InvalidOperationException(
"মেষ সংক্রান্তির exact instant পাওয়া যায়নি।");
YearStartAnchor anchor = new YearStartAnchor();
anchor.BengaliYear = bengaliYear;
anchor.InstantUtc = crossing.InstantUtc;
anchor.InstantLocal = crossing.InstantLocal;
anchor.JulianDayUt = crossing.JulianDayUt;
anchor.TimeZoneId = location.TimeZoneId;
anchor.BengaliFirstDayLabel = crossing.BengaliFirstDayLabel;
anchor.AppliedRule = crossing.AppliedRule;
anchor.AnchorProfile = crossing.ProfileName;
anchor.AnchorStarDelta = crossing.StarDelta;
return anchor;
}
FindMeshaForBengaliYear হবে existing tested solar-boundary service-এর single entry point। Daily details, Bengali calendar grid, historical Saṅkrānti test এবং yearly report—সবখানে একই service ব্যবহার করুন। এতে একই year-এর চারটি আলাদা সময় হওয়ার ঝুঁকি থাকে না।
২. Anchor-এর exact instant-এ classical trace তৈরি করুন
public YearlyPlanetReport Build(
int bengaliYear,
DesktopLocation location)
{
YearStartAnchor anchor = ResolveYearStart(bengaliYear, location);
// Deliberately use the classical planetary profile here.
ClassicalCalculation calculation = classicalEngine.CalculateAtJulianDay(
anchor.JulianDayUt,
location.Longitude,
ClassicalProfile.Bija);
YearlyPlanetReport report = new YearlyPlanetReport();
report.Anchor = anchor;
report.Trace = MapTrace(calculation.Trace);
report.MeanPlanets = MapMeanPlanets(calculation);
report.PlanetProfile = "classical-bija";
report.EngineVersion = BuildInfo.Version;
return report;
}
এখানে anchor.AnchorProfile এবং report.PlanetProfile ইচ্ছাকৃতভাবে আলাদা। classicalEngine-এর shared yr dictionary-তে Modern Star Fit ঢোকাবেন না।
৩. Rāśi-degree format
static string FormatLongitude(double longitude)
{
double value = longitude % 360.0;
if (value < 0.0) value += 360.0;
int sign = (int)Math.Floor(value / 30.0);
double inside = value - sign * 30.0;
int degree = (int)Math.Floor(inside);
double minuteValue = (inside - degree) * 60.0;
int minute = (int)Math.Floor(minuteValue);
double second = (minuteValue - minute) * 60.0;
return String.Format(
CultureInfo.InvariantCulture,
"{0}° {1:00}′ {2:00.00}″ ({3})",
degree, minute, second, RashiNamesBn[sign]);
}
Rounding-এর ফলে 59.999... second কখনও 60.00 হতে পারে। Production formatter-এ carry normalisation করে second→minute এবং minute→degree propagate করুন।
HTML report-এ কী দেখাবেন?
Header block
- বাংলা বছর ও location;
- Meṣa Saṅkrānti local time ও UTC;
- Julian Day UT;
- Historical হলে Julian এবং proleptic Gregorian—দুই label;
- বাংলা ১ বৈশাখের civil date;
- Anchor profile, star delta, planet profile ও engine version।
Intermediate trace table
| পরিমাণ | Raw value | ব্যাখ্যা/Unit |
|---|---|---|
| অব্দপিণ্ড | Exact engine output | Formula/version উল্লেখ |
| দিনবৃন্দ | Exact engine output | Reduced day quantity হলে লিখুন |
| অহর্গণ | Whole + fraction | Epoch convention |
| দেশান্তর | Signed raw correction | Reference meridian ও unit |
| বীজ | Profile + body values | Internal unit ও sign |
Mean planet table
static string RenderMeanPlanetRows(
IList<MeanPlanetRow> planets)
{
StringBuilder rows = new StringBuilder();
foreach (MeanPlanetRow planet in planets)
{
rows.Append("<tr><td>").Append(H(planet.NameBn))
.Append("</td><td><code>").Append(H(planet.RevolutionNumerator))
.Append(" / ").Append(H(planet.CycleDayDenominator))
.Append("</code></td><td>").Append(H(planet.EpochTerm))
.Append("</td><td>").Append(H(planet.BijaTerm))
.Append("</td><td>").Append(H(planet.MeanLongitudeFormatted))
.Append("</td></tr>");
}
return rows.ToString();
}
এখানে দুটি পৃথক declaration ব্যবহার করা হয়েছে—var rows = ..., trace = ...; নয়—কারণ C#-এ implicitly typed local variable declaration-এ multiple declarator অনুমোদিত নয়।
Optional comparison table
Swiss Ephemeris comparison দিলে “error” না লিখে “difference from selected modern reference” লিখুন। একই JD, ayanāṃśa, coordinate type, geocentric/topocentric mode ও time scale নিশ্চিত করুন। Mean traditional longitude-কে modern true longitude-এর সঙ্গে সরাসরি বিচার করা বৈজ্ঞানিকভাবে অসম stage comparison।
Machine-readable XML export
<yearly_planet_report bengali_year="1433"
location="Dhaka, Bangladesh"
engine_version="...">
<anchor
julian_day_ut="..."
utc="..."
local="..."
timezone="Bangladesh Standard Time"
profile="modern-star-fit-1947-v1"
star_delta="31"
bengali_first_day="..." />
<classical_trace
epoch="..."
abda_pinda="..."
dinabrinda="..."
ahargana_whole="..."
ahargana_fraction="..."
deshantara="..."
bija_profile="classical-bija" />
<mean_planets profile="classical-bija">
<planet key="sun"
name_bn="রবি"
revolution_numerator="..."
cycle_day_denominator="..."
epoch_term="..."
bija_term="..."
longitude_degrees="..."
longitude_text="..." />
</mean_planets>
</yearly_planet_report>
XML attribute-এ raw numerical value invariant culture-এ রাখুন; Bengali display text আলাদা attribute/element-এ। এতে comma decimal separator বা Bengali digit parsing-এর কারণে downstream error হবে না।
C# XML builder
static XElement PlanetElement(MeanPlanetRow row)
{
return new XElement("planet",
new XAttribute("key", row.Key),
new XAttribute("name_bn", row.NameBn),
new XAttribute("revolution_numerator", row.RevolutionNumerator),
new XAttribute("cycle_day_denominator", row.CycleDayDenominator),
new XAttribute("epoch_term", row.EpochTerm),
new XAttribute("bija_term", row.BijaTerm),
new XAttribute("longitude_degrees",
row.MeanLongitude.ToString("R", CultureInfo.InvariantCulture)),
new XAttribute("longitude_text", row.MeanLongitudeFormatted));
}
ঐতিহাসিক বছর, Julian/Gregorian এবং .NET DateTime
বাংলা বছর ১-এর মতো early historical report-এ astronomical instant একটি, কিন্তু civil label দুটি হতে পারে: Julian calendar date এবং proleptic Gregorian date। Julian Day-কে canonical রেখে দুই calendar conversion আলাদা formatter দিয়ে করুন।
- ১৮ মার্চ ৫৯৪ খ্রিস্টাব্দের নিচে project minimum boundary enforce করুন;
- Julian label বানাতে Gregorian
DateTimeconstructor-কে ভুল calendar date দেবেন না; - ১৫৮২ transition-এ missing civil dates দিয়ে astronomical day count ভাঙবেন না;
- বাংলা ৯৮৯-এর ১৫৮২–১৫৮৩ interval regression test রাখুন;
- Display calendar switch এবং astronomical JD calculation আলাদা রাখুন।
Recommended historical header: “Julian: … · Proleptic Gregorian: … · JD(UT): …”। ব্যবহারকারী কোন convention দেখছেন তা কখনও অনুমানের ওপর ছেড়ে দেবেন না।
Validation checklist
- বাংলা বছর ১ accepted;
- বাংলা বছর ০ rejected;
- Minimum date ১৮ মার্চ ৫৯৪ enforced;
- Search result অবশ্যই Meṣa crossing;
- Root bracket-এর দুই পাশে solar longitude sign change;
- Root tolerance metadata-তে;
- UTC ও local instant একই moment;
- Time-zone ID retained;
- JD invariant culture-এ;
- Anchor local date এবং Bengali first day আলাদা field;
- Historical anchor profile classical;
- ১৯৪৬-এ modern fit disabled;
- ১৯৪৭-এ modern fit enabled;
- Modern Meṣa star delta +31;
- Anchor profile version retained;
- Planet profile separately retained;
- Modern anchor fit planet constants mutate করে না;
- Tithi unchanged;
- Nakshatra unchanged;
- Yoga unchanged;
- Karana unchanged;
- Moon model unchanged;
- Eclipse engine unchanged;
- Base dictionaries immutable;
- Parallel report requests isolated;
- Abda-piṇḍa raw value preserved;
- Dinabrinda raw value preserved;
- Ahargaṇa whole/fraction preserved;
- Epoch name and JD published;
- Sunrise/midnight epoch convention published;
- Deśāntara reference meridian published;
- Deśāntara sign rule published;
- Deśāntara unit published;
- Time-zone offset not mislabeled deśāntara;
- Bīja profile named;
- Every bīja value has unit;
- Mean revolution numerator preserved;
- Cycle-day denominator preserved;
- Modulo applied only at display/output stage;
- Longitude always [0°, 360°);
- Rāśi index ০–১১;
- DMS carry normalization tested;
- বাংলা ৯৮৯ / ১৫৮২ transition tested;
- Julian and Gregorian labels map to same JD;
- Dhaka report tested;
- Kolkata report tested;
- New York report tested;
- HTML and XML numerical results identical;
- XML decimals use dot;
- Engine/version included in cache key;
- Regression snapshot retained.
সাধারণ ভুল এবং সমাধান
| ভুল | ফল | সমাধান |
|---|---|---|
year + 593 দিয়ে fixed date | Exact Saṅkrānti হারায় | Solar boundary root solve |
| Saṅkrānti date = ১ বৈশাখ ধরে নেওয়া | Late crossing-এ wrong civil day | Month-start rule আলাদা চালান |
| Modern star fit global constants-এ | Planets ও tithi বদলে যায় | Anchor-only isolated profile |
| Time-zone = deśāntara | দুই ভিন্ন correction মিশে যায় | Clock এবং meridian metadata আলাদা |
| Raw intermediate বাদ | Result reproduce করা যায় না | Numerator, divisor, quotient, remainder রাখুন |
| আগে decimal rounding | Long-range drift | Integer/rational যতদূর সম্ভব |
| Historical date এক calendar-এ | User ambiguity | Dual Julian/Gregorian label |
| Mean বনাম modern true compare | ভুল “error” conclusion | Same-stage, same-settings comparison |
একটি report কখন গবেষণাযোগ্য?
শুধু “রবি—০° মেষ” দেখানো একটি display। গবেষণাযোগ্য report বলতে এমন output বোঝায় যেখানে অন্য কেউ year, location, JD, epoch, constants, bīja profile, deśāntara convention এবং raw intermediate নিয়ে একই result পুনরায় তৈরি করতে পারেন।
এই কারণে printable table-এর পাশে collapsible “Applied calculation trace” রাখা ভালো। সাধারণ পাঠক পরিষ্কার summary দেখবেন; গবেষক raw values, formula version ও correction profile খুলে দেখতে পারবেন। HTML, XML এবং API—তিন output-ই একই typed YearlyPlanetReport model থেকে render করা উচিত।
উপসংহার
মেষ সংক্রান্তি বাংলা সৌরবছরের natural astronomical anchor। কিন্তু year anchor, civil ১ বৈশাখ এবং planetary model একই জিনিস নয়। Exact Meṣa crossing resolve করুন; calendar rule দিয়ে প্রথম দিন label করুন; তারপর সেই JD-তে unmodified selected classical profile দিয়ে অব্দপিণ্ড, দিনবৃন্দ/অহর্গণ, দেশান্তর, বীজ এবং মধ্যগ্রহ নির্ণয় করুন।
১৯৪৭-পরবর্তী Modern Sankranti Star Fit ব্যবহার করলে report-এ anchor_profile ও planet_profile আলাদা প্রকাশ করুন। Historical year-এ dual Julian/Gregorian label এবং সর্বত্র Julian Day রাখুন। তাহলেই একই report printed Panjika production, historical research এবং software regression test—তিন ক্ষেত্রেই কার্যকর হবে।
তথ্যসূত্র ও আরও পাঠ
- Sūrya-Siddhānta English translation; mean motion, ahargaṇa এবং planetary procedures.
- Ebenezer Burgess—Translation of the Sūrya-Siddhānta; public-domain full translation.
- Kyoto Sangyo University Pancanga 3.14; modern Sūryasiddhānta ও older Pañcasiddhāntikā constants selectable.
- Pancanga 3.14 Readme; Ujjain default meridian, locality input এবং traditional solar-month rule notes.
- Cidambi, Montelle & Plofker—Astronomical handbooks in 16th-century South Asia; ahargaṇa, mean longitude, kṣepaka/dhruva এবং deśāntara analysis.
- সূর্য সিদ্ধান্ত পঞ্জিকা project specification; minimum historical boundary, ১৯৪৭ cutoff, Modern Sankranti Star Fit এবং calculation-scope policy.
মন্তব্য, আলোচনা ও প্রশ্ন