/// <summary> /// Finds the boundary evaluator (<see cref="AppControl.BoundaryValues"/>) /// associated with <paramref name="fieldName"/> for the condition /// <paramref name="boundaryValues"/>. /// </summary> /// <param name="boundaryValues">The boundary condition</param> /// <param name="fieldName">The id of the boundary in question</param> /// <returns> /// The evaluator stored in <see cref="AppControl.BoundaryValues"/> /// for a boundary with id <paramref name="fieldName"/>. /// </returns> private static Func <double[], double, double> GetBoundaryValueFunction(AppControl.BoundaryValueCollection boundaryValues, string fieldName) { Func <double[], double, double> boundaryValue = null; TryGetBoundaryValueFunction(boundaryValues, fieldName, out boundaryValue); if (boundaryValue == null) { throw new ArgumentException( "Missing boundary specification for field '" + fieldName + "'", "condition"); } return(boundaryValue); }
/// <summary> /// Retrieves the configured boundary condition for a given /// <paramref name="edgeTagName"/>. /// </summary> /// <param name="edgeTagName">The name of the edge</param> /// <returns> /// The boundary condition that has been assigned to edges with /// name <paramref name="edgeTagName"/> /// </returns> public virtual BoundaryCondition GetBoundaryCondition(string edgeTagName) { AppControl.BoundaryValueCollection boundaryValues = GetConfiguredBoundaryValues(edgeTagName); var key = boundaryValueMap.Keys.SingleOrDefault(tag => edgeTagName.StartsWith(tag, StringComparison.InvariantCultureIgnoreCase)); if (key == null) { throw new NotImplementedException("Unknown edge tag name \"" + edgeTagName + "\""); } else { return(boundaryValueMap[key](control, boundaryValues)); } }
/// <summary> /// Searches the boundary config (<see cref="AppControl.BoundaryValues"/>) /// for a definition of a set of boundary values for an edge with name /// <paramref name="edgeTagName"/>. /// </summary> /// <param name="edgeTagName"> /// The id of the boundary in question /// </param> /// <returns>The boundary values specified in the control file</returns> private AppControl.BoundaryValueCollection GetConfiguredBoundaryValues(string edgeTagName) { AppControl.BoundaryValueCollection boundaryValues = null; foreach (var tagConditionPair in control.BoundaryValues) { if (edgeTagName.StartsWith(tagConditionPair.Key, StringComparison.InvariantCultureIgnoreCase)) { boundaryValues = tagConditionPair.Value; } } if (boundaryValues == null) { throw new ArgumentException( "Unable to find a definition for boundary conditions for edges of type '" + edgeTagName + "'", "edgeTagName"); } return(boundaryValues); }
/// <summary> /// ctor /// </summary> /// <param name="grdDat"></param> /// <param name="_bndy"></param> /// <param name="bndFunctionNames"> /// all names of boundary functions that should be parsed for, see <see cref="bndFunction"/> /// </param> public BoundaryCondMap(IGridData grdDat, IDictionary <string, AppControl.BoundaryValueCollection> _bndy, params string[] bndFunctionNames) { var bndy = new Dictionary <string, AppControl.BoundaryValueCollection>(_bndy, new StringIgnoreCaseEq()); m_grdDat = grdDat; //m_grid = grdDat.Grid; //var grid = m_grid; // verify Boundary Condition Type Enum // ==================================== { Type tT = typeof(BCType); if (!tT.IsEnum) { throw new ApplicationException("generic type argument must be an enumeration."); } var consts = tT.GetMembers(); foreach (var c in consts) { try { BCType val; val = (BCType)Enum.Parse(tT, c.Name); // if we pass this line, we've found a constant of the enum BoundaryCondTypes.Add(c.Name, val); } catch (Exception) { // some other member, e.g. Equals(),... } } } // verify boundary function names // ============================== foreach (string s in bndFunctionNames) { Func <double[], double, double>[] vals = new Func <double[], double, double> [GridCommons.FIRST_PERIODIC_BC_TAG]; //ArrayTools.Set(vals, Zero); for (int ii = 0; ii < vals.Length; ii++) { vals[ii] = Zero; } bndFunction.Add(s, vals); } // verification: test if EdgeTagsNames and EdgeTags in control file and in grid match // ================================================================================== //int D = grid.SpatialDimension; { List <string> Problems = new List <string>(); // 1st: look if all EdgeTagsNames in the Grid have a corresponding entry in the control file foreach (byte EdgeTag in grdDat.EdgeTagNames.Keys) // loop over all edge tag names in grid ... { string EdgeTagName = grdDat.EdgeTagNames[EdgeTag]; if (EdgeTagName.Length <= 0) { Problems.Add("Found an empty EdgeTagName in the grid. (EdgeTag = " + EdgeTag + ")."); } if (EdgeTag == 0) { // must not be in the control file foreach (string edgetagname in bndy.Keys) { if (edgetagname.Equals(EdgeTagName, StringComparison.InvariantCultureIgnoreCase)) { Problems.Add("Illegal specification for boundary condition on internal edge: (EdgeTagName = '" + EdgeTagName + "', Edgetag = " + EdgeTag + "."); } } } else if (EdgeTag >= GridCommons.FIRST_PERIODIC_BC_TAG) { // must not be in the control file foreach (string edgetagname in bndy.Keys) { if (edgetagname.Equals(EdgeTagName, StringComparison.InvariantCultureIgnoreCase)) { Problems.Add("Illegal specification for boundary condition on periodic edge: (EdgeTagName = '" + EdgeTagName + "', Edgetag = " + EdgeTag + "."); } } } else { // must be contained in the control file int found = 0; foreach (string edgetagname in bndy.Keys) { if (edgetagname.Equals(EdgeTagName, StringComparison.InvariantCultureIgnoreCase)) { found++; } } if (found > 1) { Problems.Add("Boundary condition in control file is specified more than once (" + found + " times) (EdgeTagName = '" + EdgeTagName + "', Edgetag = " + EdgeTag + "."); } if (found == 0) { Problems.Add("EdgeTagName = '" + EdgeTagName + "', Edgetag = " + EdgeTag + " is specified in the grid, but not in control file."); } } } // 2nd: look if all boundary conditions in the control file can be found in the grid. foreach (string edgetagname in bndy.Keys) // loop over all boundary conditions in control file { if (edgetagname == null || edgetagname.Length <= 0) { Problems.Add("found some boundary condition with zero-length name"); } if (!grdDat.EdgeTagNames.Values.Contains(edgetagname, new StringIgnoreCaseEq())) { Problems.Add("some boundary condition for '" + edgetagname + "' is specified in control file, but there is no corresponding EdgeTagName in the grid."); } } // 3rd: test if all boundary conditions can be interpreted foreach (var bc in bndy) { string edgetagname = bc.Key; string _EdgeTagName = edgetagname.ToLowerInvariant(); string ttt = bc.Value.type; int interptret = 0; foreach (string bctype in this.BoundaryCondTypes.Keys) { string _bctype = bctype.ToLowerInvariant(); if (ttt != null && ttt.Equals(bctype, StringComparison.InvariantCultureIgnoreCase)) { interptret++; continue; } if (ttt == null && _EdgeTagName.Contains(_bctype)) { interptret++; continue; } } if (interptret <= 0) { Problems.Add("unable to interpret boundary condition for name '" + edgetagname + "': no fitting boundary condition type found;"); } if (interptret > 1) { Problems.Add("unable to interpret boundary condition for name '" + edgetagname + "': not unique; "); } } // throw an exception, if there are any problems if (Problems.Count > 0) { StringWriter stw = new StringWriter(); stw.WriteLine("Found " + Problems.Count + " problem(s) with boundary condition specification."); foreach (string s in Problems) { stw.WriteLine(s); } stw.Write("(EdgeTagNames in the grid are: "); int cnt = 0; foreach (string s in grdDat.EdgeTagNames.Values) { cnt++; stw.Write("'" + s + "'"); if (cnt < grdDat.EdgeTagNames.Count) { stw.Write(", "); } } stw.Write(")"); throw new ApplicationException(stw.ToString()); } } // test edges // ========== // loop over all edges ... int E = grdDat.iGeomEdges.Count; for (int e = 0; e < E; e++) { //foreach (byte EdgeTag in grdDat.EdgeTags) { byte EdgeTag = grdDat.iGeomEdges.EdgeTags[e]; if (EdgeTag == 0) { if (grdDat.iGeomEdges.CellIndices[e, 1] < 0) { // unspec. EdgeTag on boundary -> error throw new ApplicationException("Error in Grid: found at least one edge without EdgeTag;"); } else { // inner edge: nothing to do; continue; } } if (EdgeTag >= GridCommons.FIRST_PERIODIC_BC_TAG) { continue; // do nothing for periodic edges } } // build the EdgeTag -> BoundaryCondType -- Mapping // ================================================ foreach (byte EdgeTag in grdDat.EdgeTagNames.Keys) { string EdgeTagName = grdDat.EdgeTagNames[EdgeTag]; if (EdgeTag == 0 || EdgeTag >= GridCommons.FIRST_PERIODIC_BC_TAG) { continue; } AppControl.BoundaryValueCollection bc = bndy[EdgeTagName]; { // these problems should have been detected prevoiusly... if (bc == null) { throw new ApplicationException("unable to find definition for boundary in control file; " + "From Gird: EdegTag = " + EdgeTag + ", EdgeTagName = " + EdgeTagName + "; "); } if (EdgeTagName == null || EdgeTagName.Length <= 0) { throw new ApplicationException("EdgeTagName is not defined: must be defined either in grid or within control-file; EdgeTag = " + EdgeTag); } } // set boundary condition // ---------------------- { string _EdgeTagName = EdgeTagName.ToLowerInvariant(); string type = bc.type; if (type == null) { type = ""; } if (type.Length > 0) { // specification of type overrules the name _EdgeTagName = ""; } bool found = false; foreach (string bctype in this.BoundaryCondTypes.Keys) { if (type.Equals(bctype, StringComparison.InvariantCultureIgnoreCase) || _EdgeTagName.Contains(bctype.ToLowerInvariant())) { EdgeTag2Type[EdgeTag] = this.BoundaryCondTypes[bctype]; found = true; break; } } if (!found) { throw new ApplicationException("unable to determine boundary condition type:" + " EdgeTagName: \"" + EdgeTagName + "\": " + "EdgeTagName or type must contain either with \"Wall\", \"Velocity_inlet\", or \"Pressure_Outlet\", or \"Outflow\" (case insensitive) to be identified by this version of the Navier-Stokes solver."); } foreach (var kv in bc.Evaluators) { string DesiredFieldName = kv.Key; Func <double[], double, double> f_bnd = kv.Value; if (!bndFunction.Keys.Contains(DesiredFieldName)) { //string allNmn = ""; //foreach (var ss in bndFunction.Keys) // allNmn += ss + " "; //throw new ApplicationException("boundary function '" + val.DesiredFieldName + "' is not supported by the application (must be one of: " + allNmn+");"); // there may be some other BoundaryConditionMap which uses this name } else { bndFunction[DesiredFieldName][EdgeTag] = f_bnd; } } } } // define which boundary condition types are used in the actual grid !!! // ===================================================================== foreach (BCType bct in this.BoundaryCondTypes.Values) { int cnt = 0; // loop over all edges ... E = grdDat.iGeomEdges.Count; for (int e = 0; e < E; e++) { //foreach (byte EdgeTag in grdDat.EdgeTags) { byte EdgeTag = grdDat.iGeomEdges.EdgeTags[e]; if (EdgeTag == 0) { continue; } if (EdgeTag >= GridCommons.FIRST_PERIODIC_BC_TAG) { continue; // do nothing for periodic edges } if (EdgeTag2Type[EdgeTag].Equals(bct)) { cnt++; } } int GlobCnt = 0; unsafe { csMPI.Raw.Allreduce((IntPtr)(&cnt), (IntPtr)(&GlobCnt), 1, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD); } BCTypeUseCount.Add(bct, GlobCnt); } // additional info // =============== { var _EdgeTag2EdgeTagName = new Dictionary <byte, string>(); var _EdgeTagName2EdgeTag = new Dictionary <string, byte>(); foreach (var kv in grdDat.EdgeTagNames) { _EdgeTag2EdgeTagName.Add(kv.Key, kv.Value); _EdgeTagName2EdgeTag.Add(kv.Value, kv.Key); } EdgeTag2EdgeTagName = _EdgeTag2EdgeTagName; EdgeTagName2EdgeTag = _EdgeTagName2EdgeTag; } }
/// <summary> /// Version of <see cref="GetVelocityBoundaryValueFunction"/> which /// supports optional vector fields. /// </summary> /// <param name="boundaryValues"> /// <see cref="GetBoundaryValueFunction"/> /// </param> /// <returns> /// A list of length /// <see cref="CNSEnvironment.NumberOfDimensions"/> of boundary /// values as returned by <see cref="GetBoundaryValueFunction"/>. /// </returns> private static Func <double[], double, double>[] GetOptionalVelocityBoundaryValueFunction(AppControl.BoundaryValueCollection boundaryValues) { int numberOfDimensions = CNSEnvironment.NumberOfDimensions; // First check x-component only Func <double[], double, double> boundaryValue; bool found = TryGetBoundaryValueFunction(boundaryValues, "u0", out boundaryValue); // If x-component is missing, assume no velocity if (!found) { return(null); } Func <double[], double, double>[] result = new Func <double[], double, double> [numberOfDimensions]; result[0] = boundaryValue; // If x-component is present, _all_ other components have to be // there, too for (int i = 1; i < numberOfDimensions; i++) { result[i] = GetBoundaryValueFunction(boundaryValues, "u" + i); } return(result); }
/// <summary> /// Vector version of <see cref="GetBoundaryValueFunction"/> for the /// velocity components /// </summary> /// <param name="boundaryCondition"> /// <see cref="GetBoundaryValueFunction"/> /// </param> /// <returns> /// A list of length /// <see cref="CNSEnvironment.NumberOfDimensions"/> of boundary /// values as returned by <see cref="GetBoundaryValueFunction"/>. /// </returns> private static Func <double[], double, double>[] GetVelocityBoundaryValueFunction(AppControl.BoundaryValueCollection boundaryCondition) { Func <double[], double, double>[] result = GetOptionalVelocityBoundaryValueFunction(boundaryCondition); if (result == null) { throw new Exception(String.Format( "Missing definition of velocity component for boundary condition")); } return(result); }
/// <summary> /// Finds the boundary evaluator (<see cref="AppControl.BoundaryValues"/>) /// associated with <paramref name="fieldName"/> for the condition /// <paramref name="boundaryValues"/>. /// </summary> /// <param name="boundaryValues"> /// The configured boundary values /// </param> /// <param name="fieldName">The id of the boundary in question</param> /// <param name="result"> /// On exit: The evaluator stored in <see cref="AppControl.BoundaryValues"/> /// for a boundary with id <paramref name="fieldName"/> if it exists /// </param> /// <returns> /// True, if a boundary value has been found; false otherwise /// </returns> private static bool TryGetBoundaryValueFunction(AppControl.BoundaryValueCollection boundaryValues, string fieldName, out Func <double[], double, double> result) { return(boundaryValues.Evaluators.TryGetValue(fieldName, out result)); }