AIさんに作ってもらった

はじめに

世の中AI流行りですが、当サイトも遅ればせながらAI関連の初記事です。

内容は業務上必要になったOpenFOAMのコードを作成するに際しての裏話ですが、これを第85回オープンCAE勉強会岐阜(2026/2/28)での発表ネタとして作成したものです。

 

function / wallHeatFlux on energyTransport

発表資料(近日中公開予定)

 

AIとのやりとり記録1

AIとのやりとり記録2

作成されたコード

				
					    wallHeatFlux_energy
    {
        type            coded;
        libs            (utilityFunctionObjects);
        name            energyWallHeatFlux;
        executeControl  timeStep;
        executeInterval 1;
        
        writeControl    timeStep;
        writeInterval   1;

        codeInclude
        #{
            #include "volFields.H"
            #include "fvPatchFields.H"
        #};

        codeWrite
        #{
            // 1. 辞書とパラメータの取得 (前回と同様)
            IOdictionary energyDict(IOobject("energy", mesh().time().system(), mesh(), IOobject::MUST_READ, IOobject::NO_WRITE));
            //const dictionary& dict = energyDict.subDictOrAdd("sTransport");
            // 2. 辞書構造への対応(サブディクショナリを考慮)
            const dictionary* subDictPtr = &energyDict;
            if (!energyDict.found("kappa"))
            {
                forAllConstIters(energyDict, iter)
                {
                    if (iter().isDict())
                    {
                        subDictPtr = &iter().dict();
                        break; 
                    }
                }
            }
            const dictionary& dict = *subDictPtr;

            const scalar kappa  = dict.get<dimensionedScalar>("kappa").value();
            const scalar rhoInf = dict.get<dimensionedScalar>("rhoInf").value();
            const scalar Cp     = dict.get<dimensionedScalar>("Cp").value();
            const scalar Prt    = dict.getOrDefault<scalar>("Prt", 0.85);
            const word TName    = dict.getOrDefault<word>("field", "T");
            const scalar rhoCp  = rhoInf * Cp;

            const auto& T = mesh().lookupObject<volScalarField>(TName);
            const auto& nut = mesh().lookupObject<volScalarField>("nut");

            // 2. 出力用フィールドの作成 (存在しない場合のみ新規作成)
            if (!mesh().foundObject<volScalarField>("wallHeatFlux_energy"))
            {
                volScalarField* qField = new volScalarField
                (
                    IOobject("wallHeatFlux_energy", mesh().time().timeName(), mesh(), IOobject::NO_READ, IOobject::AUTO_WRITE),
                    mesh(),
                    dimensionedScalar("zero", dimensionSet(1, 0, -3, 0, 0, 0, 0), 0.0) // [W/m2]
                );
                qField->store();
            }
            auto& qField = mesh().lookupObjectRef<volScalarField>("wallHeatFlux_energy");

            // 2. パッチループ
            forAll(T.boundaryField(), patchi)
            {
                const fvPatch& patch = mesh().boundary()[patchi];
                
                // 【重要】全てのプロセスが全パッチに対してこのループを通る必要があります
                if (patch.type() == "wall")
                {
                    const fvPatchScalarField& pT = T.boundaryField()[patchi];
                    const fvPatchScalarField& pNut = nut.boundaryField()[patchi];
                    const scalarField& magSf = mesh().magSf().boundaryField()[patchi];

                    scalarField q = -(kappa + (rhoCp * pNut / Prt)) * pT.snGrad();
                    qField.boundaryFieldRef()[patchi] = q;

                    // 【最重要】gSumは全プロセスで必ず実行される場所に配置
                    scalar totalQ = gSum(q * magSf);
                    scalar totalArea = gSum(magSf);

                    // 3. 出力判定 (マスタープロセスのみ実行)
                    if (Pstream::master() && mag(totalQ) > SMALL)
                    {
                        fileName outputDir = mesh().time().globalPath()/"postProcessing"/"wallHeatFlux";
                        if (!isDir(outputDir)) mkDir(outputDir);
                        
                        fileName filePath = outputDir/("heatFlux_" + patch.name() + ".dat");
                        OFstream os(filePath, IOstream::ASCII, IOstream::APPEND);
                        
                        if (mesh().time().timeIndex() <= 1)
                        {
                            os << "# Time\tTotal_W\tAvg_W_m2" << endl;
                        }

                        os << mesh().time().value() << "\t" << totalQ << "\t" << (totalQ / (totalArea + SMALL)) << endl;
                    }
                }
               }

            // 5. 書き出し制御
            // データの保存タイミング(writeTime)の時だけ、フィールドファイルをディスクに書き出す
            if (mesh().time().writeTime())
            {
                qField.write();
                if (Pstream::master())
                {
                    Info<< "Time = " << mesh().time().value() << ": wallHeatFlux fields written." << endl;
                }
            }
        #};
    }

				
			

あとがき

昨年までは、あと1年もすると後期高齢者となる自分がAI関連記事を発信することになるとはまずもって無いだろうと思っていたが、必要にせまられてAIさんに助けられることとなった。助けられたからには恩返しの情報発信である。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

上部へスクロール