/// <summary> /// This method validates the profile used in the analysis. /// </summary> /// <param name="profile"></param> /// <param name="response"></param> /// <returns>True, if the values in the profile can be used in the analysis. False, otherwise.</returns> public virtual Task <bool> Execute(TProfile profile, FiniteElementResponse response) { if (profile == null) { response.AddError(OperationErrorCode.RequestValidationError, $"Profile cannot be null."); return(Task.FromResult(false)); } return(Task.FromResult(true)); }
/// <summary> /// This method validates the finite element request. /// </summary> /// <param name="request"></param> /// <returns></returns> protected override async Task <FiniteElementResponse> ValidateOperation(TRequest request) { FiniteElementResponse response = await base.ValidateOperation(request).ConfigureAwait(false); if (response.Success == false) { return(response); } if (request.NumberOfElements <= 0) { response.AddError(OperationErrorCode.RequestValidationError, "Number of elements must be greather than zero."); } if (Enum.TryParse(typeof(Materials), request.Material, out _) == false) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid material: '{request.Material}'."); } if (request.Length <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Length: '{request.Length}' must be greather than zero."); } foreach (var fastening in request.Fastenings) { if (fastening.NodePosition < 0 || fastening.NodePosition > request.NumberOfElements) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid value for fastening node position: '{fastening.NodePosition}'. It must be greather than zero and less than '{request.NumberOfElements}'."); } if (Enum.TryParse(typeof(Fastenings), fastening.Type, out _) == false) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid fastening type: '{fastening.Type}'."); } } foreach (var forces in request.Forces) { if (forces.NodePosition < 0 || forces.NodePosition > request.NumberOfElements) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid value for fastening node position: {forces.NodePosition}. It must be greather than zero and less than {request.NumberOfElements}."); } } if (await this._profileValidator.Execute(request.Profile, response).ConfigureAwait(false) == false) { response.AddError(OperationErrorCode.RequestValidationError, "Invalid beam profile."); } return(response); }
/// <summary> /// This method validates the <see cref="BeamWithDvaRequest{TProfile}"/>. /// </summary> /// <param name="request"></param> /// <returns></returns> protected override async Task <FiniteElementResponse> ValidateOperation(BeamWithDvaRequest <TProfile> request) { FiniteElementResponse response = await base.ValidateOperation(request).ConfigureAwait(false); foreach (var dva in request.Dvas) { if (dva.Mass < 0) { response.AddError(OperationErrorCode.RequestValidationError, $"DVA Mass: {dva.Mass} cannot be less than zero. DVA index: {request.Dvas.IndexOf(dva)}."); } if (dva.Stiffness < 0) { response.AddError(OperationErrorCode.RequestValidationError, $"DVA Stiffness: {dva.Stiffness} cannot be less than zero. DVA index: {request.Dvas.IndexOf(dva)}."); } if (dva.NodePosition < 0 || dva.NodePosition > request.NumberOfElements) { response.AddError(OperationErrorCode.RequestValidationError, $"DVA NodePosition: {dva.NodePosition} must be greather than zero and less than number of elements: {request.NumberOfElements}. DVA index: {request.Dvas.IndexOf(dva)}."); } } return(response); }
/// <summary> /// This method validates the rectangular profile used in the analysis. /// </summary> /// <param name="profile"></param> /// <param name="response"></param> /// <returns>True, if the values in the rectangular profile can be used in the analysis. False, otherwise.</returns> public override async Task <bool> Execute(RectangularProfile profile, FiniteElementResponse response) { if (await base.Execute(profile, response).ConfigureAwait(false) == false) { return(false); } if (profile.Area == 0 && profile.MomentOfInertia == 0 && profile.Height == 0 && profile.Width == 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Some parameter must be informed. If height and width are informed, Area and Moment of Inertia cannot be informed. If Area and Moment of Inertia are informed, height and width cannot be informed."); return(false); } if (profile.Height > 0 && profile.Width > 0) { if (profile.Area != null || profile.MomentOfInertia != null) { response.AddError(OperationErrorCode.RequestValidationError, $"When heigth and width are informed, Area: {profile.Area} and Moment of Inertia: {profile.MomentOfInertia} cannot be informed."); return(false); } if (profile.Thickness < 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Thickness cannot be less than zero."); return(false); } return(true); } else if (profile.Height < 0 || profile.Width < 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid value to heigth: {profile.Height} and widht: {profile.Width}. Height and width must be greather than zero"); return(false); } if (profile.Area > 0 && profile.MomentOfInertia > 0) { if (profile.Height != 0 && profile.Width != 0) { response.AddError(OperationErrorCode.RequestValidationError, $"When Area and Moment of Inertia are informed, heigth: {profile.Height} and width: {profile.Width} must be zero."); return(false); } if (profile.Thickness != 0) { response.AddError(OperationErrorCode.RequestValidationError, $"When Area and Moment of Inertia are informed, thickness: {profile.Thickness} must be zero."); } return(true); } else { response.AddError(OperationErrorCode.RequestValidationError, $"Area: {profile.Area} and Moment of Inertia: {profile.MomentOfInertia} must be greather than zero."); return(false); } }
/// <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> /// This method validates the <see cref="BeamWithPiezoelectricRequest{TProfile}"/>. /// </summary> /// <param name="request"></param> /// <returns></returns> protected override async Task <FiniteElementResponse> ValidateOperation(BeamWithPiezoelectricRequest <TProfile> request) { FiniteElementResponse response = await base.ValidateOperation(request).ConfigureAwait(false); if (response.Success == false) { return(response); } if (request.PiezoelectricYoungModulus <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Piezoelectric Young Modulus: {request.PiezoelectricYoungModulus} must be greather than zero."); } if (request.PiezoelectricConstant <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Piezoelectric Constant: {request.PiezoelectricConstant} must be greather than zero."); } if (request.DielectricConstant <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Dielectric Constant: {request.DielectricConstant} must be greather than zero."); } if (request.ElasticityConstant <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Elasticity Constant: {request.ElasticityConstant} must be greather than zero."); } if (request.DielectricPermissiveness <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Dielectric Permissiveness: {request.DielectricPermissiveness} must be greather than zero."); } if (request.PiezoelectricSpecificMass <= 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Piezoelectric SpecificMass: {request.PiezoelectricSpecificMass} must be greather than zero."); } foreach (var electricalCharge in request.ElectricalCharges) { if (electricalCharge.NodePosition < 0 || electricalCharge.NodePosition > request.NumberOfElements) { response.AddError(OperationErrorCode.RequestValidationError, $"Electrical Charge NodePosition: {electricalCharge.NodePosition} must be greather than zero and less than number of elements: {request.NumberOfElements}. Electrical Charge index: {request.ElectricalCharges.IndexOf(electricalCharge)}."); } } if (Enum.TryParse(typeof(PiezoelectricPosition), Regex.Replace(request.PiezoelectricPosition, @"\s", ""), ignoreCase: true, out _) == false) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid piezoelectric position: '{request.PiezoelectricPosition}'."); } if (await this._profileValidator.Execute(request.PiezoelectricProfile, response).ConfigureAwait(false) == false) { response.AddError(OperationErrorCode.RequestValidationError, "Invalid piezoelectric profile."); } if (request.ElementsWithPiezoelectric == null) { return(response); } if (request.ElementsWithPiezoelectric.Max() > request.NumberOfElements || request.ElementsWithPiezoelectric.Min() < 1) { response.AddError(OperationErrorCode.RequestValidationError, $"Element with piezoelectric must be greather than one (1) and less than number of elements: {request.NumberOfElements}."); } return(response); }
/// <summary> /// This method validates the circular profile used in the analysis. /// </summary> /// <param name="profile"></param> /// <param name="response"></param> /// <returns>True, if the values in the circular profile can be used in the analysis. False, otherwise.</returns> public override async Task <bool> Execute(CircularProfile profile, FiniteElementResponse response) { if (await base.Execute(profile, response).ConfigureAwait(false) == false) { return(false); } if (profile.Area == 0 && profile.MomentOfInertia == 0 && profile.Diameter == 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Some parameter must be informed. If diameter is informed, Area and Moment of Inertia cannot be informed. If Area and Moment of Inertia are informed, diameter cannot be informed."); return(false); } if (profile.Diameter > 0) { if (profile.Area != 0 || profile.MomentOfInertia != 0) { response.AddError(OperationErrorCode.RequestValidationError, $"When diameter is informed, Area: {profile.Area} and Moment of Inertia: {profile.MomentOfInertia} cannot be informed."); return(false); } if (profile.Thickness < 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Thickness cannot be less than zero."); return(false); } return(true); } else if (profile.Diameter < 0) { response.AddError(OperationErrorCode.RequestValidationError, $"Invalid value to diameter: {profile.Diameter}. Diameter must be greather than zero"); } if (profile.Area > 0 && profile.MomentOfInertia > 0) { if (profile.Diameter != 0) { response.AddError(OperationErrorCode.RequestValidationError, $"When Area and Moment of Inertia are informed, diameter: {profile.Diameter} and thickness: {profile.Thickness} cannot be informed."); return(false); } if (profile.Thickness != 0) { response.AddError(OperationErrorCode.RequestValidationError, $"When Area and Moment of Inertia are informed, thickness: {profile.Thickness} must be zero."); } return(true); } else { response.AddError(OperationErrorCode.RequestValidationError, $"Area: {profile.Area} and Moment of Inertia: {profile.MomentOfInertia} must be greather than zero."); return(false); } }