public MembraneActionData(MembraneType oldMembrane, MembraneType newMembrane) { OldMembrane = oldMembrane; NewMembrane = newMembrane; }
/// <summary> /// Computes the energy balance for the given organelles in biome /// </summary> public static EnergyBalanceInfo ComputeEnergyBalance(IEnumerable <OrganelleDefinition> organelles, Biome biome, MembraneType membrane) { var result = new EnergyBalanceInfo(); float processATPProduction = 0.0f; float processATPConsumption = 0.0f; float movementATPConsumption = 0.0f; int hexCount = 0; var atp = SimulationParameters.Instance.GetCompound("atp"); var enumerated = organelles.ToList(); // Compute all process efficiencies once var efficiencies = ComputeOrganelleProcessEfficiencies(enumerated, biome); foreach (var organelle in enumerated) { foreach (var efficiencyInfo in efficiencies) { foreach (var processData in efficiencyInfo.Value.Processes) { // Find process inputs and outputs that use/produce ATP // and that are performed by this organelle // and add to totals if (!organelle.Processes.ContainsKey(processData.Process.InternalName)) { continue; } if (processData.OtherInputs.ContainsKey(atp.InternalName)) { var amount = processData.OtherInputs[atp.InternalName].Amount; processATPConsumption += amount; result.AddConsumption(organelle.Name, amount); } if (processData.Outputs.ContainsKey(atp.InternalName)) { var amount = processData.Outputs[atp.InternalName].Amount; processATPProduction += amount; result.AddProduction(organelle.Name, amount); } } } // Take special cell components that take energy into account if (organelle.HasComponentFactory <MovementComponentFactory>()) { var amount = Constants.FLAGELLA_ENERGY_COST; movementATPConsumption += amount; result.Flagella += amount; result.AddConsumption(organelle.Name, amount); } // Store hex count hexCount += organelle.HexCount; } // Add movement consumption together result.BaseMovement = Constants.BASE_MOVEMENT_ATP_COST * hexCount; var totalMovementConsumption = movementATPConsumption + result.BaseMovement; // Add osmoregulation result.Osmoregulation = Constants.ATP_COST_FOR_OSMOREGULATION * hexCount * membrane.OsmoregulationFactor; result.AddConsumption("osmoregulation", result.Osmoregulation); // Compute totals result.TotalProduction = processATPProduction; result.TotalConsumptionStationary = processATPConsumption + result.Osmoregulation; result.TotalConsumption = result.TotalConsumptionStationary + totalMovementConsumption; result.FinalBalance = result.TotalProduction - result.TotalConsumption; result.FinalBalanceStationary = result.TotalProduction - result.TotalConsumptionStationary; return(result); }
/// <summary> /// Computes the energy balance for the given organelles in biome /// </summary> /// <param name="organelles">The organelles to compute the balance with</param> /// <param name="biome">The conditions the organelles are simulated in</param> /// <param name="membrane">The membrane type to adjust the energy balance with</param> /// <param name="onlyMovementInDirection"> /// Only movement organelles that can move in this (cell origin relative) direction are calculated. Other /// movement organelles are assumed to be inactive in the balance calculation. /// </param> public static EnergyBalanceInfo ComputeEnergyBalance(IEnumerable <OrganelleTemplate> organelles, BiomeConditions biome, MembraneType membrane, Vector3 onlyMovementInDirection) { var result = new EnergyBalanceInfo(); float processATPProduction = 0.0f; float processATPConsumption = 0.0f; float movementATPConsumption = 0.0f; int hexCount = 0; foreach (var organelle in organelles) { foreach (var process in organelle.Definition.RunnableProcesses) { var processData = CalculateProcessMaximumSpeed(process, biome); if (processData.WritableInputs.ContainsKey(ATP)) { var amount = processData.WritableInputs[ATP]; processATPConsumption += amount; result.AddConsumption(organelle.Definition.InternalName, amount); } if (processData.WritableOutputs.ContainsKey(ATP)) { var amount = processData.WritableOutputs[ATP]; processATPProduction += amount; result.AddProduction(organelle.Definition.InternalName, amount); } } // Take special cell components that take energy into account if (organelle.Definition.HasComponentFactory <MovementComponentFactory>()) { var amount = Constants.FLAGELLA_ENERGY_COST; var organelleDirection = MicrobeInternalCalculations.GetOrganelleDirection(organelle); if (organelleDirection.Dot(onlyMovementInDirection) > 0) { movementATPConsumption += amount; result.Flagella += amount; result.AddConsumption(organelle.Definition.InternalName, amount); } } // Store hex count hexCount += organelle.Definition.HexCount; } // Add movement consumption together result.BaseMovement = Constants.BASE_MOVEMENT_ATP_COST * hexCount; result.AddConsumption("baseMovement", result.BaseMovement); var totalMovementConsumption = movementATPConsumption + result.BaseMovement; // Add osmoregulation result.Osmoregulation = Constants.ATP_COST_FOR_OSMOREGULATION * hexCount * membrane.OsmoregulationFactor; result.AddConsumption("osmoregulation", result.Osmoregulation); // Compute totals result.TotalProduction = processATPProduction; result.TotalConsumptionStationary = processATPConsumption + result.Osmoregulation; result.TotalConsumption = result.TotalConsumptionStationary + totalMovementConsumption; result.FinalBalance = result.TotalProduction - result.TotalConsumption; result.FinalBalanceStationary = result.TotalProduction - result.TotalConsumptionStationary; return(result); }
public static float CalculateSpeed(IEnumerable <OrganelleTemplate> organelles, MembraneType membraneType, float membraneRigidity) { float microbeMass = Constants.MICROBE_BASE_MASS; float organelleMovementForce = 0; // For each direction we calculate the organelles contribution to the movement force float forwardsDirectionMovementForce = 0; float backwardsDirectionMovementForce = 0; float leftwardDirectionMovementForce = 0; float rightwardDirectionMovementForce = 0; // Force factor for each direction float forwardDirectionFactor; float backwardDirectionFactor; float rightDirectionFactor; float leftDirectionFactor; var organellesList = organelles.ToList(); foreach (var organelle in organellesList) { microbeMass += organelle.Definition.Mass; if (organelle.Definition.HasComponentFactory <MovementComponentFactory>()) { Vector3 organelleDirection = GetOrganelleDirection(organelle); // We decompose the vector of the organelle orientation in 2 vectors, forward and right // To get the backward and left is easy because they are the opposite of those former 2 forwardDirectionFactor = organelleDirection.Dot(Vector3.Forward); backwardDirectionFactor = -forwardDirectionFactor; rightDirectionFactor = organelleDirection.Dot(Vector3.Right); leftDirectionFactor = -rightDirectionFactor; float movementConstant = Constants.FLAGELLA_BASE_FORCE * organelle.Definition.Components.Movement !.Momentum / 100.0f; // We get the movement force for every direction as well forwardsDirectionMovementForce += MovementForce(movementConstant, forwardDirectionFactor); backwardsDirectionMovementForce += MovementForce(movementConstant, backwardDirectionFactor); rightwardDirectionMovementForce += MovementForce(movementConstant, rightDirectionFactor); leftwardDirectionMovementForce += MovementForce(movementConstant, leftDirectionFactor); } } var maximumMovementDirection = MaximumSpeedDirection(organellesList); // Maximum-force direction is not normalized so we need to normalize it here maximumMovementDirection = maximumMovementDirection.Normalized(); // Calculate the maximum total force-factors in the maximum-force direction forwardDirectionFactor = maximumMovementDirection.Dot(Vector3.Forward); backwardDirectionFactor = -forwardDirectionFactor; rightDirectionFactor = maximumMovementDirection.Dot(Vector3.Right); leftDirectionFactor = -rightDirectionFactor; // Add each movement force to the total movement force in the maximum-force direction. organelleMovementForce += MovementForce(forwardsDirectionMovementForce, forwardDirectionFactor); organelleMovementForce += MovementForce(backwardsDirectionMovementForce, backwardDirectionFactor); organelleMovementForce += MovementForce(rightwardDirectionMovementForce, rightDirectionFactor); organelleMovementForce += MovementForce(leftwardDirectionMovementForce, leftDirectionFactor); float baseMovementForce = Constants.CELL_BASE_THRUST * (membraneType.MovementFactor - membraneRigidity * Constants.MEMBRANE_RIGIDITY_MOBILITY_MODIFIER); float finalSpeed = (baseMovementForce + organelleMovementForce) / microbeMass; return(finalSpeed); }