/// <summary> /// This method creates the input to be used in finite element analysis. /// </summary> /// <param name="request"></param> /// <returns>A new instance of class <see cref="FiniteElementMethodInput"/>.</returns> public override async Task <FiniteElementMethodInput> CreateInput(TRequest request) { uint degreesOfFreedom = await this.CalculateDegreesOfFreedom(request.NumberOfElements).ConfigureAwait(false); TBeam beam = await this.BuildBeam(request, degreesOfFreedom); (bool[] boundaryConditions, uint numberOfTrueBoundaryConditions) = await this._mainMatrix.CalculateBoundaryConditions(beam, degreesOfFreedom).ConfigureAwait(false); double[,] mass = await this._mainMatrix.CalculateMass(beam, degreesOfFreedom).ConfigureAwait(false); double[,] stiffness = await this._mainMatrix.CalculateStiffness(beam, degreesOfFreedom).ConfigureAwait(false); double[,] damping = await this._mainMatrix.CalculateDamping(mass, stiffness).ConfigureAwait(false); double[] forces = await this._mainMatrix.CalculateForce(beam).ConfigureAwait(false); FiniteElementMethodInput input = await base.CreateInput(request).ConfigureAwait(false); input.NumericalMethod = (NumericalMethod)Enum.Parse(typeof(NumericalMethod), request.NumericalMethod, ignoreCase: true); input.Mass = await mass.ApplyBoundaryConditionsAsync(boundaryConditions, numberOfTrueBoundaryConditions).ConfigureAwait(false); input.Stiffness = await stiffness.ApplyBoundaryConditionsAsync(boundaryConditions, numberOfTrueBoundaryConditions).ConfigureAwait(false); input.Damping = await damping.ApplyBoundaryConditionsAsync(boundaryConditions, numberOfTrueBoundaryConditions).ConfigureAwait(false); input.OriginalForce = await forces.ApplyBoundaryConditionsAsync(boundaryConditions, numberOfTrueBoundaryConditions).ConfigureAwait(false); input.NumberOfTrueBoundaryConditions = numberOfTrueBoundaryConditions; return(input); }
/// <summary> /// Calculates and write in a file the results for two degrees of freedom analysis. /// </summary> /// <param name="input"></param> /// <param name="time"></param> /// <param name="previousResult"></param> /// <returns></returns> public virtual async Task <double[]> CalculateTwoDegreesOfFreedomResult(TwoDegreesOfFreedomInput input, double time, double[] previousResult) { FiniteElementMethodInput finiteElementMethodInput = await this._mappingResolver.BuildFiniteElementMethodInput(input).ConfigureAwait(false); FiniteElementResult previousFiniteElementResult = await this._mappingResolver.BuildFiniteElementResult(previousResult, input.Force).ConfigureAwait(false); FiniteElementResult finiteElementResult = await this.CalculateFiniteElementResult(finiteElementMethodInput, previousFiniteElementResult, time).ConfigureAwait(false); double[] result = await this._mappingResolver.BuildVariableVector(finiteElementResult).ConfigureAwait(false); return(result); }
/// <summary> /// Calculates the equivalent stiffness to calculate the displacement in Newmark-Beta method. /// </summary> /// <param name="input"></param> /// <returns></returns> public Task <double[, ]> CalculateEquivalentStiffness(FiniteElementMethodInput input) { double[,] equivalentStiffness = new double[input.NumberOfTrueBoundaryConditions, input.NumberOfTrueBoundaryConditions]; double const1 = 1 / (input.Beta * Math.Pow(input.TimeStep, 2)); double const2 = input.Gama / (input.Beta * input.TimeStep); for (int i = 0; i < input.NumberOfTrueBoundaryConditions; i++) { for (int j = 0; j < input.NumberOfTrueBoundaryConditions; j++) { equivalentStiffness[i, j] = const1 * input.Mass[i, j] + const2 * input.Damping[i, j] + input.Stiffness[i, j]; } } return(Task.FromResult(equivalentStiffness)); }
/// <summary> /// Calculates the equivalent force to calculate the displacement to Newmark method. /// </summary> /// <param name="input"></param> /// <param name="previousDisplacement"></param> /// <param name="previousVelocity"></param> /// <param name="previousAcceleration"></param> /// <returns></returns> public async Task <double[]> CalculateEquivalentForce(FiniteElementMethodInput input, double[] previousDisplacement, double[] previousVelocity, double[] previousAcceleration, double time) { double[] equivalentVelocity = await this.CalculateEquivalentVelocity(previousDisplacement, previousVelocity, previousAcceleration, input.NumberOfTrueBoundaryConditions).ConfigureAwait(false); double[] equivalentAcceleration = await this.CalculateEquivalentAcceleration(previousDisplacement, previousVelocity, previousAcceleration, input.NumberOfTrueBoundaryConditions).ConfigureAwait(false); double[] mass_accel = await input.Mass.MultiplyAsync(equivalentAcceleration).ConfigureAwait(false); double[] damping_vel = await input.Damping.MultiplyAsync(equivalentVelocity).ConfigureAwait(false); double[] equivalentForce = new double[input.NumberOfTrueBoundaryConditions]; for (int i = 0; i < input.NumberOfTrueBoundaryConditions; i++) { equivalentForce[i] = input.OriginalForce[i] * Math.Sin(input.AngularFrequency * time) + mass_accel[i] + damping_vel[i]; } return(equivalentForce); }
/// <summary> /// Calculates the equivalent force to calculate the displacement in Newmark-Beta method. /// </summary> /// <param name="input"></param> /// <param name="previousResult"></param> /// <param name="time"></param> /// <returns></returns> public async Task <double[]> CalculateEquivalentForce(FiniteElementMethodInput input, FiniteElementResult previousResult, double time) { double[,] equivalentDamping = await this.CalculateEquivalentDamping(input).ConfigureAwait(false); double[,] equivalentMass = await this.CalculateEquivalentMass(input).ConfigureAwait(false); double[] damping_vel = await equivalentDamping.MultiplyAsync(previousResult.Velocity).ConfigureAwait(false); double[] mass_accel = await equivalentMass.MultiplyAsync(previousResult.Acceleration).ConfigureAwait(false); double[] previousForce = await this._force.CalculateForceByType(input.OriginalForce, input.AngularFrequency, time, input.ForceType).ConfigureAwait(false); double[] force = await this._force.CalculateForceByType(input.OriginalForce, input.AngularFrequency, time + input.TimeStep, input.ForceType).ConfigureAwait(false); double[] deltaForce = await force.SubtractAsync(previousForce).ConfigureAwait(false); double[] equivalentForce = await deltaForce.SumAsync(damping_vel, mass_accel).ConfigureAwait(false); return(equivalentForce); }
/// <summary> /// This method creates the path to save the solution files. /// </summary> /// <param name="request"></param> /// <param name="input"></param> /// <returns>The path to save the solution files.</returns> public override Task <string> CreateSolutionPath(BeamRequest <TProfile> request, FiniteElementMethodInput input) { string previousPath = Path.GetDirectoryName(Directory.GetCurrentDirectory()); string fileUri = Path.Combine( previousPath, $"Solutions/FiniteElement/Beam/{request.Profile.GetType().Name}/nEl={request.NumberOfElements}/{request.NumericalMethod}"); string fileName = $"{request.AnalysisType}_{request.Profile.GetType().Name}_w={Math.Round(input.AngularFrequency, 2)}_nEl={request.NumberOfElements}.csv"; string path = Path.Combine(fileUri, fileName); Directory.CreateDirectory(fileUri); return(Task.FromResult(path)); }
/// <summary> /// This method creates the path to save the file with the maximum values for each angular frequency. /// </summary> /// <param name="request"></param> /// <param name="input"></param> /// <returns>The path to save the file with the maximum values for each angular frequency.</returns> public override Task <string> CreateMaxValuesPath(BeamWithDvaRequest <TProfile> request, FiniteElementMethodInput input) { string previousPath = Path.GetDirectoryName(Directory.GetCurrentDirectory()); string fileUri = Path.Combine( previousPath, $"Solutions/FiniteElement/BeamWithDva/MaxValues/{request.NumericalMethod}"); string fileName = $"MaxValues_{request.AnalysisType}_{request.Profile.GetType().Name}_NumberOfDvas={request.Dvas.Count}_w0={Math.Round(request.InitialAngularFrequency, 2)}_wf={Math.Round(request.FinalAngularFrequency, 2)}_nEl={request.NumberOfElements}.csv"; string path = Path.Combine(fileUri, fileName); Directory.CreateDirectory(fileUri); return(Task.FromResult(path)); }
/// <summary> /// This method calculates the vibration using finite element concepts and writes the results in a file. /// Each line in the file contains the result in an instant of time at an angular frequency. /// </summary> /// <param name="request"></param> /// <returns></returns> protected override async Task <FiniteElementResponse> ProcessOperation(TRequest request) { var response = new FiniteElementResponse { Data = new FiniteElementResponseData() }; response.SetSuccessCreated(); // Step 1 - Sets the numerical method to be used in analysis. base._numericalMethod = NumericalMethodFactory.CreateMethod(request.NumericalMethod); // Step 2 - Creates the input to numerical method. FiniteElementMethodInput input = await this.CreateInput(request).ConfigureAwait(false); // Step 3 - Generates the path to save the maximum values of analysis results and save the file URI. string maxValuesPath = await this.CreateMaxValuesPath(request, input).ConfigureAwait(false); ICollection <string> fileUris = new Collection <string>(); fileUris.Add(Path.GetDirectoryName(maxValuesPath)); while (input.AngularFrequency <= input.FinalAngularFrequency) { // Step 4 - Sets the value for time step and final time based on angular frequency and element mechanical properties. input.TimeStep = await this._time.CalculateTimeStep(input.AngularFrequency, request.PeriodDivision).ConfigureAwait(false); input.FinalTime = await this._time.CalculateFinalTime(input.AngularFrequency, request.PeriodCount).ConfigureAwait(false); // Step 5 - Generates the path to save the analysis results. // Each combination of damping ratio and angular frequency will have a specific path. string solutionPath = await this.CreateSolutionPath(request, input).ConfigureAwait(false); string solutionFolder = Path.GetDirectoryName(solutionPath); if (fileUris.Contains(solutionFolder) == false) { fileUris.Add(Path.GetDirectoryName(solutionPath)); } var previousResult = new FiniteElementResult { Displacement = new double[input.NumberOfTrueBoundaryConditions], Velocity = new double[input.NumberOfTrueBoundaryConditions], Acceleration = new double[input.NumberOfTrueBoundaryConditions], Force = input.OriginalForce }; var maxValuesResult = new FiniteElementResult { Displacement = new double[input.NumberOfTrueBoundaryConditions], Velocity = new double[input.NumberOfTrueBoundaryConditions], Acceleration = new double[input.NumberOfTrueBoundaryConditions], Force = new double[input.NumberOfTrueBoundaryConditions] }; try { using (StreamWriter streamWriter = new StreamWriter(solutionPath)) { // Step 6 - Calculates the initial results and writes it into a file. FiniteElementResult result = await this._numericalMethod.CalculateFiniteElementResultForInitialTime(input).ConfigureAwait(false); streamWriter.WriteResult(input.InitialTime, result.Displacement); // Step 7 - Sets the next time. double time = input.InitialTime + input.TimeStep; while (time <= input.FinalTime) { // Step 8 - Calculates the results and writes it into a file. result = await this._numericalMethod.CalculateFiniteElementResult(input, previousResult, time).ConfigureAwait(false); streamWriter.WriteResult(time, result.Displacement); previousResult = result; // Step 9 - Compares the previous results with the new calculated to catch the maximum values. await this.CompareValuesAndUpdateMaxValuesResult(result, maxValuesResult).ConfigureAwait(false); time += input.TimeStep; } } } catch (Exception ex) { response.AddError(OperationErrorCode.InternalServerError, $"Occurred error while calculating the analysis results and writing them in the file. {ex.Message}", HttpStatusCode.InternalServerError); response.SetInternalServerError(); return(response); } try { // Step 10 - Writes the maximum values of analysis result into a file. using (StreamWriter streamWriter = new StreamWriter(maxValuesPath, true)) { streamWriter.WriteResult(input.AngularFrequency, maxValuesResult.Displacement); } } catch (Exception ex) { response.AddError(OperationErrorCode.InternalServerError, $"Occurred error while writing the maximum values in the file. {ex.Message}", HttpStatusCode.InternalServerError); response.SetInternalServerError(); return(response); } input.AngularFrequency += input.AngularFrequencyStep; } // Step 11 - Calculates the structure natural frequencies and writes them into a file. //double[] naturalFrequencies = await this._naturalFrequency.CalculateByQRDecomposition(input.Mass, input.Stiffness, tolerance: 1e-3).ConfigureAwait(false); //this._file.Write("Natural Frequencies", naturalFrequencies, maxValuesPath); // Step 12 - Maps the response. response.Data.Author = request.Author; response.Data.AnalysisExplanation = "Not implemented."; response.Data.FileUris = fileUris; return(response); }
/// <summary> /// Calculates the result for the initial time for a finite element analysis using Runge Kutta Forth Order numerical method. /// </summary> /// <param name="input"></param> /// <returns></returns> public override Task <FiniteElementResult> CalculateFiniteElementResultForInitialTime(FiniteElementMethodInput input) { throw new NotImplementedException(); }
/// <summary> /// Calculates and write in a file the results for a finite element analysis using Runge Kutta Forth Order numerical method. /// </summary> /// <param name="input"></param> /// <param name="previousResult"></param> /// <param name="time"></param> /// <returns></returns> public override Task <FiniteElementResult> CalculateFiniteElementResult(FiniteElementMethodInput input, FiniteElementResult previousResult, double time) { throw new NotImplementedException(); }
/// <summary> /// Calculates and write in a file the results for a finite element analysis using Newmark integration method. /// </summary> /// <param name="input"></param> /// <param name="previousResult"></param> /// <param name="time"></param> /// <returns></returns> public override async Task <FiniteElementResult> CalculateFiniteElementResult(FiniteElementMethodInput input, FiniteElementResult previousResult, double time) { FiniteElementResult result = new FiniteElementResult { Displacement = new double[input.NumberOfTrueBoundaryConditions], Velocity = new double[input.NumberOfTrueBoundaryConditions], Acceleration = new double[input.NumberOfTrueBoundaryConditions], Force = previousResult.Force }; this.CalculateIngrationContants(input); double[,] equivalentStiffness = await this.CalculateEquivalentStiffness(input.Mass, input.Stiffness, input.Damping, input.NumberOfTrueBoundaryConditions).ConfigureAwait(false); double[,] inversedEquivalentStiffness = await equivalentStiffness.InverseMatrixAsync().ConfigureAwait(false); double[] equivalentForce = await this.CalculateEquivalentForce(input, previousResult.Displacement, previousResult.Velocity, previousResult.Acceleration, time).ConfigureAwait(false); result.Displacement = await inversedEquivalentStiffness.MultiplyAsync(equivalentForce).ConfigureAwait(false); string path = @"C:\Users\bruno\OneDrive\Área de Trabalho\Testes - IC Vibrações\Matrizes resultantes\master.csv"; using (StreamWriter streamWriter = new StreamWriter(path)) { this.WriteMatrix(streamWriter, equivalentStiffness, "Keq"); this.WriteMatrix(streamWriter, inversedEquivalentStiffness, "IKeq"); this.WriteVector(streamWriter, equivalentForce, "Feq"); this.WriteVector(streamWriter, result.Displacement, "Y"); } for (int i = 0; i < input.NumberOfTrueBoundaryConditions; i++) { result.Acceleration[i] = a0 * (result.Displacement[i] - previousResult.Displacement[i]) - a2 * previousResult.Velocity[i] - a3 * previousResult.Acceleration[i]; result.Velocity[i] = previousResult.Velocity[i] + a6 * previousResult.Acceleration[i] + a7 * result.Acceleration[i]; } return(result); }
/// <summary> /// Calculates the result for the initial time for a finite element analysis using Newmark integration method. /// </summary> /// <param name="input"></param> /// <returns></returns> public override Task <FiniteElementResult> CalculateFiniteElementResultForInitialTime(FiniteElementMethodInput input) { return(Task.FromResult(new FiniteElementResult { Displacement = new double[input.NumberOfTrueBoundaryConditions], Velocity = new double[input.NumberOfTrueBoundaryConditions], Acceleration = new double[input.NumberOfTrueBoundaryConditions], Force = input.OriginalForce })); }
/// <summary> /// Calculates and write in a file the results for a one degree of freedom analysis using Newmark-Beta integration method. /// </summary> /// <param name="input"></param> /// <param name="previousResult"></param> /// <param name="time"></param> /// <returns></returns> public override async Task <FiniteElementResult> CalculateFiniteElementResult(FiniteElementMethodInput input, FiniteElementResult previousResult, double time) { double[,] equivalentStiffness = await this.CalculateEquivalentStiffness(input).ConfigureAwait(false); double[,] inversedEquivalentStiffness = await equivalentStiffness.InverseMatrixAsync().ConfigureAwait(false); double[] equivalentForce = await this.CalculateEquivalentForce(input, previousResult, time).ConfigureAwait(false); double[] deltaDisplacement = await inversedEquivalentStiffness.MultiplyAsync(equivalentForce).ConfigureAwait(false); double[] deltaVelocity = new double[input.NumberOfTrueBoundaryConditions]; double[] deltaAcceleration = new double[input.NumberOfTrueBoundaryConditions]; for (int i = 0; i < input.NumberOfTrueBoundaryConditions; i++) { deltaVelocity[i] = input.Gama / (input.Beta * input.TimeStep) * deltaDisplacement[i] - input.Gama / input.Beta * previousResult.Velocity[i] + input.TimeStep * (1 - input.Gama / (2 * input.Beta)) * previousResult.Acceleration[i]; deltaAcceleration[i] = (1 / (input.Beta * Math.Pow(input.TimeStep, 2))) * deltaDisplacement[i] - (1 / (input.Beta * input.TimeStep)) * previousResult.Velocity[i] - (1 / (2 * input.Beta)) * previousResult.Acceleration[i]; } return(new FiniteElementResult { Displacement = await previousResult.Displacement.SumAsync(deltaDisplacement).ConfigureAwait(false), Velocity = await previousResult.Velocity.SumAsync(deltaVelocity).ConfigureAwait(false), Acceleration = await previousResult.Acceleration.SumAsync(deltaAcceleration).ConfigureAwait(false), Force = await this._force.CalculateForceByType(input.OriginalForce, input.AngularFrequency, time, input.ForceType).ConfigureAwait(false) }); }
/// <summary> /// Calculates and write in a file the results for a finite element analysis. /// </summary> /// <param name="input"></param> /// <param name="previousResult"></param> /// <param name="time"></param> /// <returns></returns> public abstract Task <FiniteElementResult> CalculateFiniteElementResult(FiniteElementMethodInput input, FiniteElementResult previousResult, double time);
/// <summary> /// Calculates the result for the initial time for a finite element analysis. /// </summary> /// <param name="input"></param> /// <returns></returns> public abstract Task <FiniteElementResult> CalculateFiniteElementResultForInitialTime(FiniteElementMethodInput input);