All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.jbgust.jsrm.infra.pressure.ChamberPressureCalculation Maven / Gradle / Ivy

package com.github.jbgust.jsrm.infra.pressure;

import com.github.jbgust.jsrm.application.JSRMConfig;
import com.github.jbgust.jsrm.application.motor.SolidRocketMotor;
import com.github.jbgust.jsrm.calculation.CalculatorBuilder;
import com.github.jbgust.jsrm.calculation.CalculatorResults;
import com.github.jbgust.jsrm.calculation.Formula;
import com.github.jbgust.jsrm.infra.ConstantsExtractor;
import com.github.jbgust.jsrm.infra.JSRMConstant;
import com.github.jbgust.jsrm.infra.pressure.resultprovider.BurningSurfaceResultProvider;
import com.github.jbgust.jsrm.infra.pressure.resultprovider.EndGrainSurfaceResultProvider;
import com.github.jbgust.jsrm.infra.pressure.resultprovider.GrainVolumeResultProvider;
import com.github.jbgust.jsrm.infra.pressure.resultprovider.ProgressionResultProvider;
import com.google.common.collect.ImmutableMap;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import static com.github.jbgust.jsrm.infra.pressure.ChamberPressureCalculation.Results.*;
import static com.github.jbgust.jsrm.infra.pressure.function.LowKnFunction.LOW_KN_MASS_STORAGE_RATE;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

public class ChamberPressureCalculation {

    private SolidRocketMotor motor;
    private JSRMConfig config;
    private final Map constants;
    private final Map initialValues;

    public ChamberPressureCalculation(SolidRocketMotor motor, JSRMConfig config, Map constants) {
        this.motor = motor;
        this.config = config;
        this.constants = constants;
        initialValues = getInitialValues(motor, config);
    }

    public Map> compute() {

        CalculatorResults pressureResults = computeChamberPressureDuringPropellantBurn();
        CalculatorResults knResults = computeKn(pressureResults);

        addNewConstantsFromPressureResults(pressureResults);

        CalculatorResults postBurnPressureResults = computePostBurnPressure();

        return buildResults(pressureResults, knResults, postBurnPressureResults);
    }

    private CalculatorResults computeKn(CalculatorResults pressureResults) {
        return new CalculatorBuilder(PressureFormulas.KN)
                .withResultsToSave(PressureFormulas.KN)
                .withConstants(ConstantsExtractor.toCalculationFormat(constants))
                .withResultLineProviders(
                        new BurningSurfaceResultProvider(motor.getPropellantGrain().getGrainConfigutation(), config.getNumberLineDuringBurnCalculation()),
                        new KnDependenciesResultsProvider(throatArea.name(), pressureResults.getResults(PressureFormulas.THROAT_AREA)))
                .createCalculator()
                .compute(0, config.getNumberLineDuringBurnCalculation());
    }

    private Map> buildResults(CalculatorResults pressureResults, CalculatorResults knResults, CalculatorResults postBurnPressureResults) {
        int lastPressureResultsLine = config.getNumberLineDuringBurnCalculation() - 1;
        List throatAreaResults = new ArrayList<>(pressureResults.getResults(PressureFormulas.THROAT_AREA));
        IntStream.range(0, config.getNumberLineDuringPostBurnCalculation() + 1)
                .forEach(value -> throatAreaResults.add(pressureResults.getResult(PressureFormulas.THROAT_AREA, lastPressureResultsLine)));

        // During post burn pressure KN = 0 because burning surface = 0
        List knResultValues = new ArrayList<>(knResults.getResults(PressureFormulas.KN));
        IntStream.range(0, config.getNumberLineDuringPostBurnCalculation() + 1)
                .forEach(value -> knResultValues.add(0d));

        List massFlowRateValues = new ArrayList<>(pressureResults.getResults(PressureFormulas.NOZZLE_MASS_FLOW_RATE));
        List grainMassValues = new ArrayList<>(pressureResults.getResults(PressureFormulas.GRAIN_MASS));

        // linear decrease of MassFlow rate during post burn phase to 0 kg/s
        double lastMassFlowRateComputed = massFlowRateValues.get(massFlowRateValues.size() - 1);
        double massflowIncrement = lastMassFlowRateComputed/(config.getNumberLineDuringPostBurnCalculation()+1);
        IntStream.range(0, config.getNumberLineDuringPostBurnCalculation() + 1)
                .forEach(value -> massFlowRateValues.add(lastMassFlowRateComputed - (massflowIncrement * (value+1))));

        // add  0g for grainMass during postBurn Result
        IntStream.range(0, config.getNumberLineDuringPostBurnCalculation() + 1)
                .forEach(value -> grainMassValues.add(0D));

        List nozzlePassageAreaResults = new ArrayList<>(pressureResults.getResults(PressureFormulas.NOZZLE_CRITICAL_PASSAGE_AREA));
        IntStream.range(0, config.getNumberLineDuringPostBurnCalculation() + 1)
                .forEach(value -> nozzlePassageAreaResults.add(pressureResults.getResult(PressureFormulas.NOZZLE_CRITICAL_PASSAGE_AREA, lastPressureResultsLine)));


        List timeSinceBurnStartResults = mergeResults(pressureResults, postBurnPressureResults, PressureFormulas.TIME_SINCE_BURN_STARTS, PostBurnPressureFormulas.POST_BURN_TIME_SINCE_BURN_STARTS);
        List chamberPressureMPAResults = mergeResults(pressureResults, postBurnPressureResults, PressureFormulas.CHAMBER_PRESSURE_MPA, PostBurnPressureFormulas.POST_BURN_CHAMBER_PRESSURE_MPA);
        List absoluteChamberPressureResults = mergeResults(pressureResults, postBurnPressureResults, PressureFormulas.ABSOLUTE_CHAMBER_PRESSURE, PostBurnPressureFormulas.POST_BURN_ABSOLUTE_CHAMBER_PRESSURE);
        List absoluteChamberPressurePSIGResults = mergeResults(pressureResults, postBurnPressureResults, PressureFormulas.ABSOLUTE_CHAMBER_PRESSURE_PSIG, PostBurnPressureFormulas.POST_BURN_ABSOLUTE_CHAMBER_PRESSURE_PSIG);

        //feed last line
        timeSinceBurnStartResults.add(constants.get(JSRMConstant.tbinc) + timeSinceBurnStartResults.get(timeSinceBurnStartResults.size() - 1));
        chamberPressureMPAResults.add(0d);
        absoluteChamberPressureResults.add(0d);
        absoluteChamberPressurePSIGResults.add(0d);

        return ImmutableMap.>builder()
                .put(throatArea, throatAreaResults)
                .put(nozzleCriticalPassageArea, nozzlePassageAreaResults)
                .put(timeSinceBurnStart, timeSinceBurnStartResults)
                .put(chamberPressureMPA, chamberPressureMPAResults)
                .put(absoluteChamberPressure, absoluteChamberPressureResults)
                .put(absoluteChamberPressurePSIG, absoluteChamberPressurePSIGResults)
                .put(kn, knResultValues)
                .put(massFlowRate, massFlowRateValues)
                .put(grainMass, grainMassValues)
                .put(lowKNCorrection, singletonList(countLowKNFunctionUsage(pressureResults)))
                .build();
    }

    private double countLowKNFunctionUsage(CalculatorResults pressureResults) {
        if(constants.get(JSRMConstant.safeKN) == 1) {
            return Long.valueOf(pressureResults.getResults(PressureFormulas.MASS_STORAGE_RATE).stream()
                    .filter(massStorageRate -> Double.compare(LOW_KN_MASS_STORAGE_RATE, massStorageRate) == 0)
                    .count()).doubleValue();
        }

        return 0d;
    }

    private List mergeResults(CalculatorResults pressureResults,
                                      CalculatorResults postBurnPressureResults,
                                      PressureFormulas pressureFormulas,
                                      PostBurnPressureFormulas postBurnPressureFormulas) {
        return Stream
                .concat(
                        pressureResults.getResults(pressureFormulas).stream(),
                        postBurnPressureResults.getResults(postBurnPressureFormulas).stream())
                .collect(toList());
    }

    private CalculatorResults computePostBurnPressure() {

        initialValues.put(PostBurnPressureFormulas.POST_BURN_TIME_SINCE_BURN_STARTS, constants.get(JSRMConstant.tbout) + constants.get(JSRMConstant.tbinc));
        return new CalculatorBuilder(PostBurnPressureFormulas.POST_BURN_ABSOLUTE_CHAMBER_PRESSURE_PSIG)
                .withConstants(ConstantsExtractor.toCalculationFormat(constants))
                .withInitialValues(initialValues)
                .withResultsToSave(PostBurnPressureFormulas.values())
                .createCalculator()
                .compute(0, config.getNumberLineDuringPostBurnCalculation());
    }

    private CalculatorResults computeChamberPressureDuringPropellantBurn() {
        return new CalculatorBuilder(PressureFormulas.ABSOLUTE_CHAMBER_PRESSURE_PSIG)
                .withConstants(ConstantsExtractor.toCalculationFormat(constants))
                .withInitialValues(initialValues)
                .withResultsToSave(
                        PressureFormulas.THROAT_AREA,
                        PressureFormulas.NOZZLE_CRITICAL_PASSAGE_AREA,
                        PressureFormulas.TIME_SINCE_BURN_STARTS,
                        PressureFormulas.CHAMBER_PRESSURE_MPA,
                        PressureFormulas.ABSOLUTE_CHAMBER_PRESSURE,
                        PressureFormulas.ABSOLUTE_CHAMBER_PRESSURE_PSIG,
                        PressureFormulas.NOZZLE_MASS_FLOW_RATE,
                        PressureFormulas.GRAIN_MASS,
                        PressureFormulas.MASS_STORAGE_RATE
                )
                .withResultLineProviders(
                        new ProgressionResultProvider(config.getNumberLineDuringBurnCalculation()),
                        new EndGrainSurfaceResultProvider(motor.getPropellantGrain().getGrainConfigutation(), config.getNumberLineDuringBurnCalculation()),
                        new GrainVolumeResultProvider(motor.getPropellantGrain().getGrainConfigutation(), config.getNumberLineDuringBurnCalculation()))
                .createCalculator()
                .compute(JSRMConstant.START_CALCULATION_LINE, config.getNumberLineDuringBurnCalculation());
    }

    private void addNewConstantsFromPressureResults(CalculatorResults pressureResults) {
        int lastPressureResultsLine = config.getNumberLineDuringBurnCalculation() - 1;

        constants.put(JSRMConstant.tbout, pressureResults.getResult(PressureFormulas.TIME_SINCE_BURN_STARTS, lastPressureResultsLine));
        constants.put(JSRMConstant.pbout, pressureResults.getResult(PressureFormulas.CHAMBER_PRESSURE_MPA, lastPressureResultsLine));
        constants.put(JSRMConstant.astarf, pressureResults.getResult(PressureFormulas.NOZZLE_CRITICAL_PASSAGE_AREA, lastPressureResultsLine));
        constants.put(JSRMConstant.expectedPfinal, 2 * constants.get(JSRMConstant.patm) + JSRMConstant.PMAXPERC / 100 * getPmax(pressureResults));
        constants.put(JSRMConstant.tbinc, getTbinc(constants));
    }

    private double getPmax(CalculatorResults pressureResults) {
        return pressureResults.getResults(PressureFormulas.ABSOLUTE_CHAMBER_PRESSURE).stream().max(Double::compareTo).get();
    }

    private Double getTbinc(Map constants) {
        Map tbincVariables = Stream.of(JSRMConstant.vc, JSRMConstant.expectedPfinal, JSRMConstant.pbout, JSRMConstant.rat, JSRMConstant.to, JSRMConstant.astarf, JSRMConstant.cstar)
                .collect(toMap(Enum::name, constants::get));

        tbincVariables.put(IncrementTimeBurstSolver.NB_LINE_VARIABLE, (double) config.getNumberLineDuringPostBurnCalculation());

        return new IncrementTimeBurstSolver().solve(tbincVariables);
    }

    private  Map getInitialValues(SolidRocketMotor motor, JSRMConfig config) {
        Map initialValues = new HashMap<>();
        initialValues.put(PressureFormulas.TEMPORARY_CHAMBER_PRESSURE, config.getAmbiantPressureInMPa());
        initialValues.put(PressureFormulas.TIME_SINCE_BURN_STARTS, 0d);
        initialValues.put(PressureFormulas.MASS_GENERATION_RATE, 0d);
        initialValues.put(PressureFormulas.NOZZLE_MASS_FLOW_RATE, 0d);
        initialValues.put(PressureFormulas.MASS_STORAGE_RATE, 0d);
        initialValues.put(PressureFormulas.MASS_COMBUSTION_PRODUCTS, 0d);
        initialValues.put(PressureFormulas.DENSITY_COMBUSTION_PRODUCTS, 0d);
        return initialValues;
    }

    public enum Results {
        throatArea,
        nozzleCriticalPassageArea,
        timeSinceBurnStart,
        chamberPressureMPA,
        absoluteChamberPressure,
        absoluteChamberPressurePSIG,
        kn,
        massFlowRate,
        lowKNCorrection, grainMass;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy