回到宿舍。
林晚秋先去洗了中午那隻碗,又從灶台下面摸出兩個窩頭和半碟醃蘿蔔條。
她在鐵鍋里倒了半碗水,把窩頭放在蒸屜上熱著,然後從床底下拖出一顆大白菜,剝了幾片葉子,拿刀切成細絲。
「今天食堂的王師傅給了半勺麻醬。」
林晚秋一邊切菜一邊說。
「我拿來拌白菜絲,再滴兩滴醋,夏天吃著解膩。」
陳序年蹲在灶台邊幫她拉風箱,火苗燒著鐵鍋底,屋裡的溫度一點一點漲上來。
【寫到這裡我希望讀者記一下我們域名 找書就去天天看小說,𝓽𝓽𝓴𝓪𝓱.𝓽𝔀超全 】
「晚秋。」
「幹嘛?」
「那塊自留地,菜苗出來了沒有?」
「出了一半。」
林晚秋把切好的白菜絲倒進大碗裡,從罐子裡挖了一小勺麻醬拌勻。
「小白菜出的整齊,水蘿蔔還沒冒頭,我下午經過後頭看了一眼,土有點干,明天得澆點水。」
「明天我早起澆。」
「你別早起了,你每天晚上都要熬到後半夜,早上能多睡一會兒是一會兒,我順路就澆了,不耽誤事。」
兩人坐在小方桌前吃晚飯,窩頭蘸著麻醬白菜絲,嚼在嘴裡又咸又香,陳序年把碗裡的飯扒的乾乾淨淨,林晚秋從他碗裡撈走了最後一根蘿蔔條。
飯後,林晚秋去外面的水池子洗碗。
陳序年坐在書桌前,拉開抽屜拿出一本空白的硬皮筆記本。
梁啟明程式設計需要三周,這三周他自己也不能閒著。
降維的數學框架已經給了梁啟明,隱式格式也講清楚了,但具體到程式設計細節,有幾個關鍵的數值處理技巧,梁啟明未必能自己摸到。
首先是定點數的標度因子,這台機器做十六位定點運算,沒有浮點硬體支援,輻射流體力學裡涉及的物理量跨度極大,溫度從幾千度到幾千萬度,壓力從一個大氣壓到幾十億個大氣壓。
所有的實數運算都要靠手工轉換成定點數完成,每一步運算都必須追蹤小數點在哪個位置上,一旦溢位,後面所有的計算結果全是廢資料,整段紙帶等於白跑。
梁啟明學數學出身,推公式、列方程的功底紮實,但他之前沒有碰過計算機程式設計。
定點數運算里這些溢位的陷阱,他不栽一跤記不住,陳序年清楚這一點,所以提前把陷阱標出來。
另一個難點是矩陣方程的疊代求解子程式,六百個網格點耦合在一起,每走一步時間推進,就要解一組六百階的稀疏線性方程組。
如果用直接法,儲存量遠遠超過4096字的記憶體容量,根本裝不下,只能走疊代法,而疊代法能不能收斂、收斂的快慢,取決於初始猜測值和鬆弛因子怎麼選。
這兩個引數的取值跟物理問題本身的性質綁在一起,沒有通用的萬能公式,得根據具體算例去調。
陳序年在筆記本上一條一條列清單,把梁啟明可能踩的坑寫下來,每個坑旁邊標註了提示方向。
他不打算直接把答案寫在紙上遞過去,但會在梁啟明卡住的時候給他指一條路。
林晚秋洗完碗走進來的時候,他已經寫了三頁。
「又在寫東西?」
林晚秋把碗筷碼進柜子,走到桌邊看了一眼,紙上全是她看不懂的數字和符號。
「給梁組長準備的參考資料。」
陳序年合上筆記本。
「你們那個梁組長是不是天天熬通宵?昨天他來醫務室拿止痛片,黑眼圈都掛下來了。」
「搞計算的都這樣。」
「你也這樣。」
林晚秋拉開衣櫃,取出一件洗好的白大褂掛在門後。
「我看你這個月瘦了不止五斤,鎖骨都凸出來了。」
「等這陣子忙完就好了。」
「你每回都說等忙完就好了。」
林晚秋在床沿上坐下,脫了鞋,把腳縮排被窩裡。
「從我認識你到現在,你什麼時候閒過?」
陳序年放下筆,轉過身看著她。
「等這台機器跑出結果來,就能鬆一口氣了。」
「多久?」
「快的話一個月,慢的話兩個月。」
林晚秋沒說話,她低頭把被角往裡掖了掖,好一會兒才開口。
「那我把後頭那塊地的水蘿蔔種子再補點,等蘿蔔出來了,正好趕上你忙完,到時候我給你做蘿蔔燉粉條。」
陳序年笑了一下。
「行,等著吃你的蘿蔔燉粉條。」
「快寫吧,別耽誤了,我先睡了。」
林晚秋往裡挪了挪,給他留出了半邊床的位置。
陳序年轉回身,繼續寫,屋裡安靜下來,只剩筆尖在紙上划過的聲音,和林晚秋慢慢變勻的呼吸。
寫到第五頁,他停筆,從頭把內容檢查了一遍。
頁面上沒有任何來源可疑的資料,寫的全是數學方法層面的技巧提示。
就算被錢忠國拿去翻看,也只會覺得這是一個在數值計算領域有積累的人整理出來的工作筆記,挑不出毛病。
他合上筆記本鎖進抽屜,關了燈上床。
林晚秋已經睡著了,他掀開被角躺進去,她哼了一聲,翻了個身,額頭抵在他肩膀上。
明天開始,梁啟明就要動手寫那一千二百條機器指令了。
……
梁啟明動手的比預想的還快。
第二天早上七點,陳序年經過主樓二樓計算室的時候,梁啟明已經趴在桌上了。
桌麵攤著三大張硫酸紙,畫滿了程式流程圖,每一條分支、每一個判斷框都標了編號和說明。
小周和老李一人守著一台手搖計算機,對照紙上的離散格式做手算驗證。
「昨晚幾點睡的?」
陳序年在門口站了一下。
梁啟明頭也不抬。
「沒睡,方程組的離散格式全推完了,一共十七個子程式,我在流程圖上標了編號,你看看有沒有邏輯漏洞。」
陳序年走到桌前,拿起最大的那張硫酸紙。
流程圖畫的很清楚,主程式擱在最上面,往下分出十七條分支,每條分支旁邊都標了子程式名稱和功能說明。
主迴圈的結構跟他預想的一致,外層迴圈走時間步,內層迴圈走空間網格。
每一步先查狀態方程表算溫度和壓力,再算輻射輸運係數,最後把隱式格式的線性方程組組裝好送進疊代求解子程式。
時間步長的自適應控制單獨拎出來做了一個子程式,根據物理量變化的梯度來自動調步長。
陳序年的目光在第十一個子程式上停住了,旁邊標註寫的是稀疏矩陣疊代求解。
「這個子程式你打算用什麼疊代方法?」
梁啟明停下筆,轉過身來。
「雅可比疊代,最簡單,程式設計容易。」
「雅可比收斂慢。」
陳序年把硫酸紙放回桌上。
「六百階的稀疏矩陣,雅可比疊代一步要掃全部網格點一遍,收斂到要求精度至少得疊代幾百次,每一步時間推進都要疊代幾百次,八百步下來,光疊代就得跑幾十萬次。」
梁啟明皺起眉頭。
「那換高斯-賽德爾?收斂快一倍。」
「高斯-賽德爾好一些,但還不夠。」
陳序年從口袋裡摸出那本硬皮筆記本,翻到昨晚寫的第三頁。
「你看看這個,逐次超鬆弛法,在高斯-賽德爾的基礎上加一個鬆弛因子,理論上能把收斂速度再提高三到五倍。」
梁啟明接過筆記本,看了半分鐘,眼神一下亮了。
「鬆弛因子……這個值怎麼取?」
「跟矩陣的譜半徑有關,我在第四頁寫了一個估算公式,你可以先用理論值,跑起來之後根據實際收斂速度微調。」
梁啟明翻到第四頁,盯著公式看了一陣子,然後抬起頭。
「陳工,你這些東西是從哪本書上看來的?」
「翻過一些外文資料。」
陳序年把筆記本收回來。
「方法不重要,重要的是你把它編程序序里跑通,跑不通的話,再好的方法也是廢紙。」
梁啟明點了一下頭,轉過身繼續畫流程圖。
陳序年沒有再多待,退出計算室,回了自己的辦公室。
筆記本鎖進抽屜之前,他又翻了翻後面幾頁,定點數溢位的處理技巧寫在第五頁,狀態方程查表的插值子程式最佳化寫在第六頁。
這些東西他不打算一次全拋給梁啟明,等他撞上了再給,記得才牢。
接下來三天,陳序年辦公室的門幾乎沒關過。
梁啟明每隔幾個小時就派小周或者老李過來問一個問題。
問題雜七雜八,從指令編碼格式到地址計算規則,從紙帶輸入輸出的控制字元到子程式呼叫時堆疊指標怎麼儲存。
陳序年一個一個答,該講透的講透,該讓他們回去自己試的就丟一句你試試看。
有些問題陳序年當場就能回答,有些他會讓小周等一下,自己先在草稿紙上畫一遍邏輯,確認沒有歧義之後再把結論寫給他帶回去。
他不能出錯,梁啟明的程式設計能力在快速增長,如果他給的提示本身有誤,梁啟明排查的時候反而會浪費更多時間。
第四天,梁啟明的第一批程式上了紙帶。
何建軍操作打孔機,梁啟明念二進位制碼,何建軍按鍵打孔。
一條指令十六位,念一遍打一遍,念錯了就廢一段紙帶重來。
整個過程需要兩個人配合的嚴絲合縫,念的人不能含糊,打的人不能走神,一千多條指令念下來,嗓子都是啞的。
第一盤紙帶打了四個小時。
下午兩點,梁啟明把紙帶裝進讀入裝置,按下執行鍵。
紙帶噠噠噠的被吞進去,控制面板上的指示燈開始閃爍。
閃了四十下,全暗了。
「停了。」
王德明湊過來看面板上的程式計數器。
「跑到第四十一條指令的時候停的。」
梁啟明扒開紙帶輸出端,撕下一小段結果帶,對著燈光辨認孔位。
「第四十一條是個跳轉指令,跳轉地址算錯了。」
梁啟明臉色發青。
「我把子程式的起始地址寫成了十進位制,忘了轉成十六進位制。」
他回到桌前,在草稿紙上重新算了一遍地址,改了三條指令,讓何建軍重新打孔。
第二次執行,跑到了第一百二十條停住,儲存器訪問越界。
一個變數的地址偏移量多算了兩個字,程式直接讀進了未初始化的空間,取出來的資料完全沒有意義。
梁啟明查了偏移量計算表,找到了那個多餘的加法,改掉,重新打孔。
第三次,跑到了第二百八十條,停在疊代子程式的入口,原因是暫存器分配衝突。
主程式和子程式用了同一個暫存器暫存中間結果,子程式一進去就把主程式存在那個暫存器里的值給覆蓋了,等子程式跑完返回主程式,主程式拿到的已經是一個被篡改過的數。
梁啟明趴在桌上查了整整一個下午,他把十七個子程式的暫存器使用情況全部列出來,畫了一張匯總表,逐個子程式重新分配暫存器,確保沒有衝突。
這張表畫了三遍才定稿,前兩遍都發現有交叉的地方。
第四次,程式跑通了整個主迴圈的第一步。
「第一步出來了!」
小周從紙帶輸出端撕下結果,用鉛筆飛快的把二進位制轉成十進位制,又翻出手算的驗證資料對照。
「溫度、密度、壓力都對上了!輻射通量偏了百分之二!」
「百分之二在容許範圍內。」
梁啟明長出一口氣,靠在椅背上揉了揉太陽穴。
「繼續跑,看後面會不會發散。」
程式往下跑了二十步,在第二十一步崩了。
梁啟明盯著紙帶輸出的資料看了半天。
「溫度值溢位了。」
他回頭看陳序年,陳序年站在門口,手裡端著一隻搪瓷杯。
「定點數溢位。」
陳序年走進來,把搪瓷杯放在桌上。
「溫度從幾千度跳到幾萬度,數值量級變了四個數量級,你的標度因子沒跟著調。」
「標度因子?」
陳序年從口袋裡掏出筆記本,翻到第五頁,放在梁啟明面前。
「十六位定點數,有效數字只有四到五位,你要表示的物理量跨了十幾個數量級,一個固定的標度因子根本兜不住,每一步運算結束後,要檢查結果的量級,如果超出了當前標度因子的表示範圍,就要做一次重新定標。」
梁啟明看著筆記本上的內容,額頭上青筋跳了一下。
「這就是說,每一條乘法和除法指令後面,都要跟一段定標檢查的程式碼?」
「對。」
「那程式長度至少要翻一倍。」
「所以我一開始估計一千二百條。」