সূর্য সিদ্ধান্ত পঞ্জিকা সকল প্রবন্ধ

সূর্যোদয় ও সূর্যাস্ত: horizon, refraction ও upper-limb definition কেন ফল বদলায়?

Upper limb বনাম Sun center, atmospheric refraction, horizon ও elevation-এর কারণে sunrise/sunset কেন বদলায়; Swiss Ephemeris flags ও C# implementation।

কেউ বলেন সূর্যের প্রথম কিনারা দেখা গেলেই sunrise; কেউ বলেন সূর্যের কেন্দ্র mathematical horizon অতিক্রম করলে sunrise। পৃথিবীর atmosphere আলো বাঁকিয়ে সূর্যকে তার geometric অবস্থানের চেয়ে ওপরে দেখায়। আবার পাহাড়, ভবন বা সমুদ্রের horizon-ও একই নয়। তাই sunrise/sunset comparison করার প্রথম প্রশ্ন হওয়া উচিত: দুই গণনায় event definition কি একই?

“সূর্য উঠেছে”—কিন্তু কোন instant?

সূর্য একটি দৃশ্যমান disk; point source নয়। ভোরে disk-এর অংশগুলো ধারাবাহিকভাবে horizon অতিক্রম করে:

  1. প্রথমে upper limb বা উপরের কিনারা দেখা যায়;
  2. তারপর center horizon-এ আসে;
  3. সবশেষে lower limb উঠলে পুরো disk দৃশ্যমান হয়।

সূর্যাস্তে sequence উল্টো: lower limb আগে horizon ছোঁয়, center পরে, upper limb অদৃশ্য হলে পুরো disk অস্ত যায়। কোনো software যদি “rise/set” বলে কিন্তু limb/refraction profile না জানায়, output পুরোপুরি reproducible নয়।

Upper limb, center ও lower limb

Disc definitionSunriseSunsetব্যবহার
Upper limbপ্রথম কিনারা দৃশ্যমানশেষ কিনারা অদৃশ্যসাধারণ astronomical almanac ও public rise/set
CenterCenter horizon অতিক্রমCenter horizon অতিক্রমকিছু Hindu/Vedic calculation profile
Lower limbপুরো disk horizon-এর ওপরেDisk-এর প্রথম অংশ horizon-এর নিচেবিশেষ observational definition

সূর্যের apparent semidiameter গড়ে প্রায় ১৬ arcminute। তাই refraction বাদ দিলেও upper-limb sunrise center-at-horizon sunrise-এর আগে এবং upper-limb sunset পরে হবে। Earth–Sun distance বদলায় বলে solar semidiameter সারা বছর সামান্য পরিবর্তিত হয়; high-precision ephemeris library সেই পরিবর্তন নিজে সামলাতে পারে।

Atmospheric refraction কী করে?

বায়ুমণ্ডলের ঘনত্ব উচ্চতার সঙ্গে বদলায়। Horizon-এর কাছে সূর্যালোক দীর্ঘ পথ atmosphere-এর মধ্যে দিয়ে আসে এবং বাঁকে; ফলে apparent Sun geometric Sun-এর চেয়ে ওপরে দেখা যায়। তাই geometric center horizon-এর নিচে থাকলেও upper limb দৃশ্যমান হতে পারে।

Refraction স্থির physical constant নয়। Pressure, temperature, humidity এবং near-horizon atmospheric layering-এর কারণে প্রকৃত sunrise একেক দিনে conventional computed time থেকে কিছুটা সরে যেতে পারে। U.S. Naval Observatory তাই rise/set time-কে precise observation prediction নয়, standard-condition calculation হিসেবে বোঝায়।

৪৭′, ৫০′ এবং center-at-horizon—তিনটি আলাদা profile

ProfileCenter altitude at eventউপাদান
Rashtriya Panchang−৪৭′ ≈ −০.৭৮৩৩°৩১′ horizontal refraction + ১৬′ solar semidiameter
USNO conventional sunrise/setপ্রায় −৫০′ = −০.৮৩৩৩°Standard upper-limb/average atmosphere convention
Swiss Hindu rising preset০° centerDisc center + no refraction + geocentric/no solar ecliptic latitude

Rashtriya Panchang-এর official explanation upper limb, ৩১′ refraction ও ১৬′ semidiameter ব্যবহার করে এবং ৪৭′-কে প্রায় ৩.৫ মিনিটের সমতুল্য বলে। USNO standard sea-level definition center zenith distance 90.8333°-এর কাছাকাছি convention ব্যবহার করে। দুই standard-এর ৩′ angular difference ছোট হলেও identical time আশা করা উচিত নয়।

Swiss Ephemeris documentation-এ default rise/set upper limb ও refraction-ভিত্তিক। একই documentation Hindu sunrise-এর জন্য SE_BIT_DISC_CENTER এবং SE_BIT_NO_REFRACTION নির্দেশ করে; version 2.06 থেকে SE_BIT_HINDU_RISING preset এই সঙ্গে geocentric/no-ecliptic-latitude flag-ও অন্তর্ভুক্ত করে।

Geometric horizon, astronomical horizon ও visible horizon

Horizonঅর্থসীমাবদ্ধতা
Geometric horizonObserver-এর gravity direction-এর perpendicular ideal planeTerrain ও atmosphere নেই
Astronomical/apparent horizonStandard refraction ও conventional limb সহ calculated crossingAverage atmosphere
Visible/local horizonপাহাড়, গাছ, ভবন বা সমুদ্ররেখায় বাস্তব skylineAzimuth অনুযায়ী horizon altitude বদলায়

পূর্বদিকে ৩° উঁচু পাহাড় থাকলে theoretical sunrise-এর সময় Sun ideal horizon-এ উঠলেও চোখে দেখা যাবে না। আবার পশ্চিমে খোলা সমুদ্র থাকলে sunset বাধাহীন দেখা যেতে পারে। তাই local visible horizon ব্যবহার করতে হলে একটি single elevation নয়, azimuth-dependent horizon profile দরকার।

Observer elevation কেন sunrise এগিয়ে দেয়?

Observer sea level-এর ওপরে উঠলে geometric horizon নিচের দিকে dip করে; দূরের horizon দেখা যায়। সাধারণভাবে elevation বাড়লে:

  • sunrise আগে দেখা যায়;
  • sunset পরে দেখা যায়;
  • daylight interval দীর্ঘ হয়।

তবে একটি পাহাড়ের summit elevation আর surrounding terrain একই নয়। GPS elevation দিয়ে open-sea dip correction করা local ridge বা city skyline-এর বাধা দূর করে না। Swiss Ephemeris-এর swe_rise_trans_true_hor() local horizon altitude নেওয়ার ব্যবস্থা দেয়; advanced refraction function observer height, pressure ও temperature-ও গ্রহণ করতে পারে।

Topocentric ও geocentric অবস্থান

Topocentric calculation পৃথিবীর কেন্দ্র নয়, observer-এর actual location থেকে object-এর direction ব্যবহার করে। Sun-এর ক্ষেত্রে parallax ছোট; Moon-এর ক্ষেত্রে অনেক বেশি। তবুও profile reproducibility-এর জন্য এটি স্পষ্ট করা দরকার।

ReferenceViewpointRise/set-এ ভূমিকা
GeocentricEarth centerকিছু Hindu calendar convention
TopocentricLatitude, longitude, elevation-এ observerPhysical local observation-এর natural model

“Geocentric tithi” এবং “topocentric sunrise” একই daily report-এ থাকা contradiction নয়। Tithi Moon–Sun longitude difference-এর geocentric event; sunrise স্থানীয় horizon event। কেবল প্রতিটির profile আলাদা field-এ প্রকাশ করুন।

একই ৪৭′ correction সর্বত্র একই মিনিট নয়

Sun horizon-কে কত steep angle-এ অতিক্রম করছে তা latitude ও season-এর উপর নির্ভর করে। Equator-এর কাছে crossing তুলনামূলক steep; উচ্চ latitude-এ shallow। ফলে:

  • একই angular threshold equator-এর কাছে কয়েক মিনিট;
  • উচ্চ latitude-এ আরও বেশি clock-time difference;
  • polar circle-এর কাছে ছোট refraction change-ও event আছে/নেই বদলাতে পারে।

তাই “upper limb সবসময় center-এর ঠিক ৩ মিনিট আগে”—এমন hard-coded rule সঠিক নয়। Exact local geometry solve করতে হবে।

Sunrise definition পঞ্জিকার কোন ফল বদলায়?

Sunrise কয়েক মিনিট বদলালে শুধু header-এর সূর্যোদয় নয়, sunrise-state নির্ভর rule-ও বদলাতে পারে:

  • তিথি, নক্ষত্র, যোগ ও করণ কোনটি sunrise-এ present;
  • তিথি sunrise-এর আগে না পরে শেষ হয়েছে;
  • Ekādaśī viddha/śuddha classification;
  • Aruṇodaya—sunrise-এর ৯৬ মিনিট আগে—এর anchor;
  • sunrise-to-next-sunrise event list;
  • বাংলা মাসের প্রথম দিনের sunrise assignment;
  • festival ও fast day selection।

কিন্তু geocentric Saṅkrānti instant, তিথি boundary বা planetary longitude sunrise definition-এর কারণে নিজে বদলায় না। বদলাতে পারে কোন local day-এ eventটি assign হবে। Astronomy event time ও calendar assignment আলাদা layer রাখুন।

এই project-এ কোন profile ব্যবহার করা উচিত?

আপনার Surya Siddhanta app-এর বর্তমান research convention হলো Sun center/no-refraction। Historical continuity ও existing festival regression বজায় রাখতে এটিকে silently upper-limb profile-এ বদলানো উচিত নয়। বরং profile presets দিন:

Preset keyDefinitionপ্রস্তাবিত ব্যবহার
hindu-center-geometricCenter, no refraction, Hindu/geocentric flagsমূল Panchanga rule ও existing regression
rashtriya-upper-limb-47Upper limb; ৩১′ + ১৬′Rashtriya Panchang comparison
standard-upper-limbLibrary default upper limb + standard refractionPublic astronomical sunrise/sunset
observed-local-horizonTerrain horizon + met data + elevationObservational research

Daily Details-এ primary profile-এর পাশে একটি short label দিন। Settings-এ অন্য profile তুলনার জন্য নির্বাচন করা যেতে পারে, কিন্তু profile পরিবর্তনে calendar results পুনর্গণনা এবং cache invalidation বাধ্যতামূলক।

C# 5-compatible profile model

public enum SolarDiscDefinition
{
    UpperLimb,
    Center,
    LowerLimb
}

public enum SolarRefractionMode
{
    Standard,
    None,
    MeasuredAtmosphere
}

public sealed class SolarRiseSetProfile
{
    public string Key { get; set; }
    public string Version { get; set; }
    public SolarDiscDefinition Disc { get; set; }
    public SolarRefractionMode Refraction { get; set; }
    public bool UseGeocentricHinduMode { get; set; }
    public double PressureHpa { get; set; }
    public double TemperatureC { get; set; }
    public double ObserverElevationMeters { get; set; }
    public double HorizonAltitudeDegrees { get; set; }
}

public sealed class SolarDayEvents
{
    public DateTime LocalDate { get; set; }
    public DateTimeOffset SunriseUtc { get; set; }
    public DateTimeOffset SunsetUtc { get; set; }
    public string ProfileKey { get; set; }
    public string ProfileVersion { get; set; }
    public string TimeZoneId { get; set; }
    public double Latitude { get; set; }
    public double Longitude { get; set; }
}

Profile Key human-readable identity; Version algorithm/configuration change track করে। Pressure/temperature ব্যবহার না হলে misleading zero না রেখে profile অনুযায়ী default semantics document করুন।

Recommended project preset

static SolarRiseSetProfile HinduCenterGeometric()
{
    return new SolarRiseSetProfile
    {
        Key = "hindu-center-geometric",
        Version = "1.0",
        Disc = SolarDiscDefinition.Center,
        Refraction = SolarRefractionMode.None,
        UseGeocentricHinduMode = true,
        PressureHpa = 0.0,
        TemperatureC = 15.0,
        ObserverElevationMeters = 0.0,
        HorizonAltitudeDegrees = 0.0
    };
}

Swiss Ephemeris rise/set flags

নিচের code flag-selection logic দেখায়। আপনার C# wrapper-এ constant class বা method signature আলাদা হলে নাম adapt করুন:

static int BuildRiseSetMode(
    bool isRise,
    SolarRiseSetProfile profile)
{
    int mode = isRise
        ? SweConst.SE_CALC_RISE
        : SweConst.SE_CALC_SET;

    if (profile.UseGeocentricHinduMode)
    {
        mode |= SweConst.SE_BIT_HINDU_RISING;
        return mode;
    }

    if (profile.Disc == SolarDiscDefinition.Center)
        mode |= SweConst.SE_BIT_DISC_CENTER;
    else if (profile.Disc == SolarDiscDefinition.LowerLimb)
        mode |= SweConst.SE_BIT_DISC_BOTTOM;

    if (profile.Refraction == SolarRefractionMode.None)
        mode |= SweConst.SE_BIT_NO_REFRACTION;

    return mode;
}

Older Swiss Ephemeris wrapper-এ SE_BIT_HINDU_RISING না থাকলে equivalent flags:

mode |= SweConst.SE_BIT_DISC_CENTER;
mode |= SweConst.SE_BIT_NO_REFRACTION;
mode |= SweConst.SE_BIT_GEOCTR_NO_ECL_LAT;

Result validation

public sealed class SolarEventResult
{
    public bool Found { get; set; }
    public DateTimeOffset InstantUtc { get; set; }
    public string Status { get; set; }
    public int NativeReturnCode { get; set; }
    public string NativeMessage { get; set; }
}

// Native return code indicates no event/error হলে
// DateTime.MinValue বানিয়ে success দেখাবেন না।

Custom altitude solver-এর মূল geometry

Library function ব্যবহার করাই নিরাপদ। Research/debugging-এর জন্য center altitude relation:

যেখানে:

  • φ = observer latitude;
  • δ = Sun declination;
  • H = local hour angle;
  • h₀ = chosen event altitude—০°, −৪৭′, −৫০′ ইত্যাদি।

একবার formula বসিয়ে approximate hour angle পাওয়া যায়, কিন্তু high-accuracy result-এর জন্য Sun position, nutation/apparent coordinates, semidiameter ও refraction trial instant-এ পুনর্গণনা করে root solve করুন।

static double BisectAltitudeCrossing(
    double leftJd,
    double rightJd,
    double targetAltitude,
    Func<double, double> apparentAltitudeAt,
    double toleranceDays)
{
    double leftValue = apparentAltitudeAt(leftJd) - targetAltitude;
    double rightValue = apparentAltitudeAt(rightJd) - targetAltitude;

    if (leftValue == 0.0) return leftJd;
    if (rightValue == 0.0) return rightJd;
    if (leftValue * rightValue > 0.0)
        throw new ArgumentException("Solar altitude root is not bracketed.");

    while (rightJd - leftJd > toleranceDays)
    {
        double middleJd = (leftJd + rightJd) / 2.0;
        double middleValue =
            apparentAltitudeAt(middleJd) - targetAltitude;

        if (leftValue * middleValue <= 0.0)
        {
            rightJd = middleJd;
            rightValue = middleValue;
        }
        else
        {
            leftJd = middleJd;
            leftValue = middleValue;
        }
    }

    return (leftJd + rightJd) / 2.0;
}

Rise root-এ altitude increasing, set root-এ decreasing। Search bracket local noon-এর দুই পাশে আলাদা রাখলে wrong crossing এড়ানো যায়। One-day window-এ event না থাকলে polar status দিন; bracket জোর করে বড় করে unrelated date-এর root ধরবেন না।

Time zone ও DST sunrise geometry বদলায় না

Sunrise প্রথমে absolute UT/JD instant হিসেবে solve করুন, তারপর location-এর time-zone rule দিয়ে local time render করুন। DST:

  • astronomical crossing বদলায় না;
  • wall-clock label এক ঘণ্টা বদলাতে পারে;
  • পরের sunrise sunrise + 24 hours নয়;
  • প্রতিটি local civil date-এর event independently solve করতে হবে।
DateTimeOffset localSunrise =
    TimeZoneInfo.ConvertTime(sunriseUtc, zone);

DateTimeOffset localSunset =
    TimeZoneInfo.ConvertTime(sunsetUtc, zone);

Historic local mean time, wartime DST বা zone-boundary change-এর জন্য modern Windows zone rules যথেষ্ট নাও হতে পারে। Historical profile আলাদা version করুন।

Historical sunrise কতটা নিশ্চিত?

Sun-এর astronomical position বহু পুরোনো date-এ যথেষ্ট নির্ভুলভাবে model করা গেলেও historical “দৃশ্যমান sunrise” পুনর্গঠন কঠিন:

  • তৎকালীন pressure/temperature জানা নেই;
  • local horizon ও শহরের terrain পরিবর্তিত হতে পারে;
  • observer elevation/datum অনিশ্চিত;
  • historical civil time/LMT convention আলাদা;
  • Julian/Gregorian label আলাদা হলেও instant একই।

সুতরাং historical files-এ “computed conventional sunrise” বলুন; “বাস্তবে চোখে দেখা sunrise exact second” দাবি করবেন না। Profile key, coordinates, JD এবং Julian/Gregorian display policy সঙ্গে export করুন।

Polar day, polar night এবং shallow crossing

Hour-angle equation-এর right side [-1, +1]-এর বাইরে গেলে chosen altitude threshold-এ crossing নেই। এটি calculation failure নয়; ঐ date/location/profile-এ Sun rise বা set করে না।

High latitude-এ refraction variability event status-ও বদলাতে পারে। USNO উল্লেখ করে যে Sun horizon বরাবর shallow চললে refraction expected sunrise delay করতে বা কখনো apparent event তৈরি/বিলুপ্ত করতে পারে। UI-তে:

status = "NoSunrise";
status = "NoSunset";
status = "SunAboveThresholdAllDay";
status = "SunBelowThresholdAllDay";

Midnight fallback বা আগের দিনের time repeat করা উচিত নয়। Panchanga day-এর জন্য high-latitude policy প্রয়োজন হলে সেটি আলাদা ধর্মীয়/calendar policy—astronomy result নয়।

API ও XML-এ profile প্রকাশ

{
  "date": "2026-10-09",
  "location": {
    "name": "Dhaka",
    "latitude": 23.8103,
    "longitude": 90.4125,
    "elevationMeters": 4.0,
    "timeZoneId": "Bangladesh Standard Time"
  },
  "sunrise": "2026-10-09T05:54:43+06:00",
  "sunset": "2026-10-09T17:39:18+06:00",
  "profile": {
    "key": "hindu-center-geometric",
    "version": "1.0",
    "disc": "center",
    "refraction": "none",
    "horizonAltitudeDegrees": 0.0,
    "engine": "Swiss Ephemeris"
  }
}

উপরের সময়গুলো format example, certified test vector নয়। XML:

<solar-events date="2026-10-09"
              timezone="Bangladesh Standard Time"
              latitude="23.8103"
              longitude="90.4125">
  <profile key="hindu-center-geometric" version="1.0"
           disc="center" refraction="none"
           horizon-degrees="0" />
  <sunrise local="2026-10-09T05:54:43+06:00" />
  <sunset local="2026-10-09T17:39:18+06:00" />
</solar-events>

Print report-এ full metadata না চাইলে footnote যথেষ্ট: “সূর্যোদয়–সূর্যাস্ত: Sun center, geometric horizon, refraction excluded।” Machine-readable output-এ full profile রাখুন।

সাধারণ implementation error

ভুলফলসংশোধন
সব sunrise definition identical ধরাকয়েক মিনিট mismatchDisc/refraction profile compare
Upper limb কিন্তু semidiameter বাদCenter time পাওয়াLibrary default বা explicit threshold
No-refraction flag ভুলে যাওয়াHindu center result আগে/পরে সরেFinal flags diagnostic-এ রাখুন
Hindu preset + default limb mixঅসংজ্ঞায়িত hybridAtomic preset
Elevation মানেই terrain correctionMountain/city skyline ভুলAzimuth horizon profile
৪৭′ = সর্বত্র ৩.৫ মিনিট hard-codeLatitude/season errorExact crossing solve
Historical atmosphere exact দাবিFalse precisionConventional profile label
UTC offset sunrise solver-এ যোগAstronomy/time-zone mixingUT solve, পরে local render
Next sunrise +24hDST ও seasonal errorNext date independently solve
No event-এ DateTime.MinValueYear 1/out-of-range exceptionExplicit status result

Validation checklist

  1. Same date/location-এ upper-limb sunrise center-এর আগে;
  2. Same date/location-এ upper-limb sunset center-এর পরে;
  3. Refraction-on sunrise no-refraction-এর আগে;
  4. Refraction-on sunset no-refraction-এর পরে;
  5. Rashtriya threshold −৪৭′;
  6. USNO conventional threshold প্রায় −৫০′;
  7. Hindu center threshold ০°;
  8. SE_BIT_HINDU_RISING preset test;
  9. Equivalent three-flag fallback test;
  10. Default Swiss upper-limb/refraction test;
  11. Disc-bottom flag separate test;
  12. Sea-level open horizon;
  13. Positive observer elevation;
  14. Positive eastern terrain horizon delays sunrise;
  15. Positive western terrain horizon advances sunset disappearance;
  16. Pressure change refraction path;
  17. Temperature change refraction path;
  18. Pressure zero/default semantics documented;
  19. Dhaka regression date;
  20. Kolkata regression date;
  21. New York summer date;
  22. New York winter date;
  23. Equator equinox test;
  24. Mid-latitude solstice test;
  25. High-latitude shallow crossing;
  26. Polar no-sunrise status;
  27. Polar no-sunset status;
  28. Rise root increasing;
  29. Set root decreasing;
  30. Morning/evening bracket isolation;
  31. Root tolerance one second বা configured precision;
  32. Native negative return code handled;
  33. No DateTime.MinValue fallback;
  34. UT result before zone conversion;
  35. DST spring transition;
  36. DST fall transition;
  37. Next sunrise independently solved;
  38. Sunrise profile cache key-তে;
  39. Profile version cache invalidation;
  40. Daily HTML/API/XML same instant;
  41. Printed report footnote matches profile;
  42. Near-sunrise tithi boundary regression;
  43. Ekādaśī decision profile regression;
  44. Arunodaya derived from chosen sunrise;
  45. Historical JD retained;
  46. Julian/Gregorian display same instant;
  47. Observed printed Panchanga uses matching definition;
  48. Seconds displayed with uncertainty note;
  49. Coordinate/elevation/zone mismatch rejected;
  50. Swiss Ephemeris version recorded।

উপসংহার

সূর্যোদয় ও সূর্যাস্তের সময় শুধু Sun-এর longitude থেকে আসে না; local horizon crossing-এর definition দরকার। Upper limb না center, refraction আছে কি না, observer height, terrain horizon, topocentric/geocentric choice এবং atmospheric assumptions—সবই ফল বদলাতে পারে।

Rashtriya Panchang upper limb-এর জন্য ৩১′ refraction ও ১৬′ semidiameter—মোট ৪৭′—ব্যবহার করে। Swiss Ephemeris Hindu preset center-at-horizon, no-refraction এবং geocentric convention ব্যবহার করে। তাই একই location-এ কয়েক মিনিটের difference expected; profile একই না হলে একটিকে অন্যটির error বলা যায় না।

এই project-এর existing hindu-center-geometric rule বজায় রেখে optional comparison profiles দিন। প্রতিটি report ও export-এ profile key/version প্রকাশ, event time UT-তে solve, local time পরে render, এবং near-boundary festival regression test করলে পঞ্জিকার ফল ব্যাখ্যাযোগ্য ও পুনরুৎপাদনযোগ্য থাকবে।

তথ্যসূত্র ও আরও পাঠ

  1. Positional Astronomy Centre—Rashtriya Panchang Explanation; upper limb, ৩১′ refraction, ১৬′ semidiameter ও sunrise-to-next-sunrise convention.
  2. Swiss Ephemeris Programmer’s Documentation; swe_rise_trans, disc-center/no-refraction এবং Hindu rising flags.
  3. Swiss Ephemeris Programming Interface; true-horizon এবং pressure/temperature-dependent refraction functions.
  4. U.S. Naval Observatory—Rise, Set and Twilight Definitions; upper-limb convention, standard atmosphere ও observational uncertainty.
  5. U.S. Naval Observatory—Computing Times of Rise, Set, and Twilight; rise/set algorithm background.
  6. U.S. Naval Observatory—First Sunrise of the New Year; high-latitude refraction ও elevation effects.
  7. সূর্য সিদ্ধান্ত পঞ্জিকা project specification; Sun center/no-refraction primary profile, location-specific sunrise এবং daily Panchanga assignment.

মন্তব্য, আলোচনা ও প্রশ্ন