本篇教程由作者设定使用 CC BY-NC-SA 协议。

  1. (散热片)[https://www.mcmod.cn/item/290.html]系列(水字数):

    散热片 (Heat Vent)

    散热风口是一种拥有散热能力的核反应炉配件。

    它自身可以储存1,000点热量并散发自身6点热量。
            正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。

    反应堆散热片 (Reactor Heat Vent)

    反应堆散热片是一种拥有散热能力的核反应炉配件。它自身可以储存1,000点热量,吸收核反应炉自身5点热量,并散发自身5点热量。
           正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。

    虽然性能较低但是它是唯一一个散热量为奇数的散热片,MOX控温使用

    元件散热片 (Component Heat Vent)

    元件散热片是一种拥有散热能力的核反应炉配件。

    它自身不储存热量,也不吸收任何热量,只会散发周围元件4点的热量。

    高级散热片 (Advanced Heat Vent)

    高级散热片是一种拥有散热能力的核反应炉配件。它自身可以储存1,000点热量,吸收、散发自身各12点热量。
            正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。

    超频散热片 (Overclocked Heat Vent)

    超频散热片是一种拥有散热能力的核反应炉配件。

    流体热核为单个40HU/t

    自身耐久为1,000,吸收核反应炉自身36点热量/秒,并散发自身20点热量/秒,同时消耗耐久为36/秒,恢复耐久为20/秒。

    实际运行中无额外散热原件则消耗16耐久/秒。

    因为没有其他热交换元件的帮助,超频散热片吸热效率将会大于散热效率。这意味着超频热排放出口会很快超过热量上限。

    所以超频散热片需要被元件散热片等辅助散热片紧贴包围才可以长时间工作。正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。

    但也是基于这个原理,我们才可以制作出超高效率的mk5流体核电!

  2. (热交换器)[https://www.mcmod.cn/item/290.html]系列(水字数):

    热交换器 (Heat Exchanger)

              热交换模块是一种能够交换热量的核反应炉配件。它自身可以储存2500点热量,向相邻其他元件传递12点热量,并向核反应炉自身传递4点热量。
              正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)

    反应堆热交换器 (Reactor Heat Exchanger)

              反应堆热交换器是一种能够与核反应炉自身交换热量的核反应炉配件。它自身可以储存5000点热量,不会与相邻其他元件交换热量,只会向核反应炉自身传递72点热量。
              正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。

    元件热交换器 (Component Heat Exchanger)

               元件热交换模块是一种能够与周围元件交换热量的核反应炉配件。它自身可以储存5000点热量,不会与核反应炉自身交换热量,只会向相邻其他元件传递36点热量。
              正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。

    高级热交换器 (Advanced Heat Exchanger)

              高级热交换模块是一种能够交换热量的核反应炉配件。它自身可以储存10,000点热量,向相邻其他元件交换24点热量,并与核反应堆交换8点热量。
             正常工作时会显示耐久度,如果超过自身热量上限耐久度将会变为0(消失)。


    3.分析

打开ic2的源码, 找反应堆核心逻辑:ic2.core.block.reactor.tileentity.TileEntityNuclearReactorElectric, 查看函数updateEntityServer

protected void updateEntityServer() {
   super.updateEntityServer();
   if (this.updateTicker++ % this.getTickRate() == 0) {
       if (!this.worldObj.doChunksNearChunkExist(this.xCoord, this.yCoord, this.zCoord, 2)) {
           this.output = 0.0F;
       } else {
         /**
         无关
         */
           this.dropAllUnfittingStuff();
           this.output = 0.0F;
           this.maxHeat = 10000; //最大热量
           this.hem = 1.0F;            //
           this.processChambers();    //处理原件散热逻辑

           if (this.fluidcoolreactor) {  //热力核电HU输出逻辑

            /**

            */

            }

           this.EmitHeatbuffer = 0;
           if (this.calculateHeatEffects()) { //calculateHeatEffects 计算热量效果,是蒸发,着火,岩浆还是jjboom
               return;
           }

           this.setActive(this.heat >= 1000 || this.output > 0.0F);
           this.markDirty();
       }
       ((NetworkManager)IC2.network.get()).updateTileEntityField(this, "output");
   }
}

转到processChambers

int size = this.getReactorSize();
for(int pass = 0; pass < 2; ++pass) { //这个pass是个废操作
   for(int y = 0; y < 6; ++y) { 

       for(int x = 0; x < size; ++x) {

           //遍历所有有效的舱室

           ItemStack stack = this.reactorSlot.get(x, y);

           if (stack != null && stack.getItem() instanceof IReactorComponent) {

               IReactorComponent comp = (IReactorComponent)stack.getItem();
               comp.processChamber(this, stack, x, y, pass == 0); //执行舱室逻辑(燃料棒,散热片,热交换器,冷却单元,中子反射器等)
           }
       }
   }
}

再找反应堆和散热器的核心逻辑:

IC2核电站散热片分析-第1张图片

HeatSwitch就是热交换器,Vent是散热器.


散热器构造函数为: public ItemReactorVent(InternalName internalName, int 热量储存, int 元件自身散热, int 为反应堆散热); 显然注册数据和百科上一致.

ItemReactorVent的processChamber:

public void processChamber(IReactor reactor, ItemStack yourStack, int x, int y, boolean heatrun) {
   if (heatrun) {
       int rheat;
       if (this.reactorVent > 0) { //反应堆散热,直接将reactor的heat减去
           rheat = reactor.getHeat();
           int reactorDrain = rheat;
           if (rheat > this.reactorVent) {
               reactorDrain = this.reactorVent;
           }
           rheat -= reactorDrain;
           if (this.alterHeat(reactor, yourStack, x, y, reactorDrain) > 0) {
               return;
           }
           reactor.setHeat(rheat);
       }
       rheat = this.alterHeat(reactor, yourStack, x, y, -this.selfVent); //alterHeat是计算散热片耐久的逻辑, 这个逻辑会把自身热量存储减去selfHeat(自身散热速度),自身热量决定了散热片的耐久
       if (rheat <= 0) {
           reactor.addEmitHeat(rheat + this.selfVent); //元件自身散热多少, 就会输出多少HU给流体反应堆
       }
   }
}

源码上可以看出, 散热片会先从反应堆上面吸取热量, 再将热量释放(是不是和cpu很像? 从cpu上面吸收热量, 再释放到空气中), 吸收的大小就是反应堆散热速率, 释放的大小就是元件散热速率

这里我们可以得到两个定义:

反应堆热量

    就是反应堆UI的热量%多少,默认0-10000, 超过上限就会jjboom

元件热量

    体现在散热元件的耐久, 元件内堆积热量越多, 元件耐久越低, 直到元件被烧毁, 元件烧毁会使得元件原本提供的反应堆散热也失去, 使散热恶化

散热片, 反应堆散热片,高级散热片,超频散热片都是ItemReactorVent的实例对象,因此它们的逻辑是一致的,只是数值不同

对于散热片热量的流向,我们可以理解为:

燃料棒发热 --> 传到反应堆 --> 散热片吸收反应堆上面的热量 --> 存在自己的热量槽 --> 散发出去

                      |->直接传递给吸热元件(周围可接受热量的元件平分热量, 如周围元件不能吸热则丢回给反应堆) --> 存在自己的热量槽 --> 散发出去(该途径散热不经过反应堆, 不会增加反应堆温度)

注:元件散热片不提供热量存储

散热片, 高级散热片都只提供自身散热, 因此对降低反应堆温度没有直接帮助

反应堆散热片和超频散热片都提供反应堆散热, 但超频散热片的自身散热性能低于吸收的反应堆热量,因此如百科描述的那样,会堆积热量最终熔毁, 因此需要辅助散热, 一种方式是使用元件散热片, 这种Heat方式要元件散热片挨着超频散热片, 四面都要,这样4个元件散热片提供16点散热,正好抹平超频散热片的散热坑.还有一种方式是先导出到热交换器,再交给散热片/高级散热片去散热.

元件散热片: 和周围元件交换4点热量并释放出去

我们可以得到这样的结论, 一方面要有足够的能力将热量从堆导出来(反应堆散热), 另一方面,要有足够的能力把热量从元件中散发掉,缺一不可.

按照这个原理可以找到一个比较好的设计方案,至少很快就能摸索出一个在炸的边缘疯狂摇摆,而且正好又不炸的.其中的巅峰大概就是如图的420了

IC2核电站散热片分析-第2张图片

        7个4X, 每个发热96, 发电60, 7个发电420, 发热672. 其中使用了27个超频散热片,理论上来说有972的堆壳散热, 但是实际上的27个超频的元件散热只有540,不足以抗住堆心672的发热,因此由元件散热片补齐.

观察可知元件散热片发散了28 * 4共112点热量,不算那个交换器总元件散热在652, 最后那个热交换器是关键所在. 没有这个元件,由于元件散热和堆心发热的20点差异, 反应堆一定会爆炸. 

由此我们也可以看出, 依靠散热片的EU核电其实是很快就能摸到天花板的,最极限的反应堆散热也就1000不到,最难的是元件散热,这16的差异找补回来是一件难事.

4.热交换器分析
        热交换器是一种从元件和或者反应堆吸取或将热量释放到其他元件/反应堆的元件

源码位于: ItemReactorHeatSwitch.class


public void processChamber(IReactor reactor, ItemStack yourStack, int x, int y, boolean heatrun) {
   if (heatrun) {
       int myHeat = 0;
       ArrayList<ItemReactorHeatSwitch.ItemStackCoord> heatAcceptors = new ArrayList();

       if (this.switchSide > 0) {

           //如果可以和周围元件交换热量

           //switchSide是和周围元件交换热量的最大速度

           this.checkHeatAcceptor(reactor, x - 1, y, heatAcceptors);
           this.checkHeatAcceptor(reactor, x + 1, y, heatAcceptors);
           this.checkHeatAcceptor(reactor, x, y - 1, heatAcceptors);
           this.checkHeatAcceptor(reactor, x, y + 1, heatAcceptors);
       }

       int add;
       if (this.switchSide > 0) {

           for(Iterator i$ = heatAcceptors.iterator(); i$.hasNext(); myHeat += add) {

               //这里可以看出,热交换速率是每个元件最大switchSide每秒,而不是周围元件加起来能交换这么多的热, 比如说一个元件热交换器, 可以向周围元件传递最大36点热量每秒,那么它能向每个元件传递最大36

               ItemReactorHeatSwitch.ItemStackCoord stackcoord = (ItemReactorHeatSwitch.ItemStackCoord)i$.next(); //热交换器自己
               IReactorComponent heatable = (IReactorComponent)stackcoord.stack.getItem();  //周围元件
               double mymed = (double)this.getCurrentHeat(reactor, yourStack, x, y) * 100.0D / (double)this.getMaxHeat(reactor, yourStack, x, y);  //热交换器自身存热量比例
               double heatablemed = (double)heatable.getCurrentHeat(reactor, stackcoord.stack, stackcoord.x, stackcoord.y) * 100.0D / (double)heatable.getMaxHeat(reactor, stackcoord.stack, stackcoord.x, stackcoord.y);     //周围元件存热量比例
               add = (int)((double)heatable.getMaxHeat(reactor, stackcoord.stack, stackcoord.x, stackcoord.y) / 100.0D * (heatablemed + mymed / 2.0D)); // (不大于1.5的值乘以周围元件最大存热量除100, 这说明换热速率是变化的, 随着周围元件和自身热量储存而变化)
               if (add > this.switchSide) {
                   add = this.switchSide; //不超过
               }

               if (heatablemed + mymed / 2.0D < 1.0D) { //周围元件或者热交换器热量很多了, 散热速率较大,达到最大速率的一半

                   add = this.switchSide / 2;

               }

               if (heatablemed + mymed / 2.0D < 0.75D) {
                   add = this.switchSide / 4;
               }

               if (heatablemed + mymed / 2.0D < 0.5D) {  
                   add = this.switchSide / 8;
               }

               if (heatablemed + mymed / 2.0D < 0.25D) { //都没什么热量, 换热速率只有1
                   add = 1;
               }

               if ((double)Math.round(heatablemed * 10.0D) / 10.0D > (double)Math.round(mymed * 10.0D) / 10.0D) { //周围元件存热比高于自身, 热交换器从周围吸热
                   add -= 2 * add;
               } else if ((double)Math.round(heatablemed * 10.0D) / 10.0D == (double)Math.round(mymed * 10.0D) / 10.0D) {  //温度相等, 不动
                   add = 0;
               }

               myHeat -= add; //缺省情况下是热交换器往周围元件放热
               add = heatable.alterHeat(reactor, stackcoord.stack, stackcoord.x, stackcoord.y, add);  //周围元件吸热add, add如果是负数则是往热交换器放热
           }
       }

       if (this.switchReactor > 0) {

            /**

            ** 这块的逻辑差不多,只是交换热量的对象是反应堆自身

            **/

       }

       this.alterHeat(reactor, yourStack, x, y, myHeat); //最终自身吸热/放热
   }
}


分析可知, 热交换器本身是作为热量缓存来使用的, 它可以在自身温度较高时将热量扔出去,也可以在周围元件/反应堆温度高时将热量吸进来

可以用于将热量传递给能散热自身的元件,比如反应堆散热器和高级散热器,作为补充超频散热器的桥梁, 或是在一些游走在危险边缘的反应堆上面充当缓冲器, 使反应堆可以全周期运行, 比如420, 该热交换器甚至换个位置都不行, 极为玄学, 应该是试验出来的.

5. 热输出核电到底怎么摆输出最高?    

HU发电逻辑如下(原本在上文反应堆核心逻辑中)

this.processfluidsSlots();
int huOtput = (int)(huOutputModifier * (float)this.EmitHeatbuffer); //本身的热输出量再乘以一个系数
int outputroom = this.outputTank.getCapacity() - this.outputTank.getFluidAmount(); //冷却液消耗量也必须跟上,否则也会堆积热量
if (outputroom > 0) {
   FluidStack draincoolant;
   if (huOtput < outputroom) {
       draincoolant = this.inputTank.drain(huOtput, false); //1mb的冷却液对应1HU, 这么看最大也就输出8kHU了, 又不能给反应堆流体输入接口换个大的
   } else {
       draincoolant = this.inputTank.drain(outputroom, false);
   }

   if (draincoolant != null) {
       this.EmitHeat = draincoolant.amount;
       huOtput -= this.inputTank.drain(draincoolant.amount, true).amount; //冷却液必须足够且输出热量不能大于冷却液槽大小
       this.outputTank.fill(new FluidStack(BlocksItems.getFluid(InternalName.fluidHotCoolant), draincoolant.amount), true);
   } else {
       this.EmitHeat = 0;
   }
} else {
   this.EmitHeat = 0;
}

this.addHeat(huOtput / 2);  //余热的一半加给反应堆, 如果反应堆散热没有足够裕度, 又不处理, 就等着boom吧, 严禁干烧!

前文散热片逻辑已经提到, HU输出仅仅取决于所有散热片的元件散热量, 以及这边代码提到的一个系数

热交换装置不提供任何HU输出, 尤其不要用反应堆热交换器!

也不要用任何什么30k,60k,180k,360k冷却单元.


6. 我LuV/ZPM了, 想继续使用核电发电, 怎么做?

(GT发电量X2, GTNH整合包再X5, 整体X10, 所以输出达到LuV/ZPM)

前面提到常规的散热片方式是撑不起太高的发电的,这个时候就要请出终极武器了!

强冷! 利用各种冷却单元强大的反应堆散热能力和超大耐久, 配合各种自动化mod + 真空冷冻机/反应堆红石自动注入器, 可以实现比原来高得多的输出!

IC2核电站散热片分析-第3张图片        通过让单个冷却单元工作一段时间,可以获得耐久较低的冷却单元, 通过抽取较低耐久的冷却单元并填入新的来确保冷却单元不会耗尽,  抽取的冷却单元会补充耐久.

前面提到了, 燃料棒可以直接向相邻的可存热元件释放热量, 那么只要把冷却单元贴着燃料棒摆就行了, 只要你能确保每个燃料棒边上必然有一个冷却单元就好了, 当然, 为了保险, 最好在反应堆放一个反应堆散热片以应对换冷却单元瞬间的升温, 并且放入冷却单元前处理一下各单元的耐久, 保证冷却时间点错开.

随便摆一个看看:

IC2核电站散热片分析-第4张图片

5400EU/t, 在GTNH整合再乘以5, 27000, LuV妥妥的.