“Philosophical Orientation”

An update on 27 April 2018 06:30 HRS IST, noted at the end:


Here is a beginning of a passage, a section, from a book on QM (now-a-days available through the Dover). The section was the very first one from the very first chapter, and was aptly called “Philosophical Orientation.” It began thus:

\dots For what purpose, dear reader, do you study physics?

To use it technologically? Physics can be put to use; so can art and music. But that’s not why you study them.

It isn’t their social relevance that attracts you. The most precious things in life are the irrelevant ones. It is a meager life, indeed, that is consumed only by the relevant, by the problems of mere survival.

You study physics because you find it fascinating. You find poetry in conceptual structures. You find it romantic to understand the working of nature. You study physics to acquire an intimacy with nature’s way.

Our entire understanding of nature’s way is founded on the subject called quantum mechanics. No fact of nature has ever been discovered that contradicts quantum mechanics. \dots


A good passage to read, that one was. \dots. It was (I guess originally) published as late as in 1987. \dots


An update on 27 April 2018 06:30 HRS IST:

Initially, when I put this post online, I had thought that, sure, people would be able to copy-paste the quote, and thereby get to the book. But looks like they won’t. Hence this update.

The book in question is this:

Chester, Marvin (1987) “Primer of Quantum Mechanics,” Wiley; reproduced as a Dover ed. (2003) from the corrected Krieger ed. (1992).

If you ask for my opinion about the book: It’s a (really) good one, but despite being “philosophical,” like all texts on QM, it still tends to miss the forest for the trees. And it doesn’t even mention entanglement (not in the index, anyway). Entanglement began to appear in the text-books only after the mid-90’s, I gather. Also another thing: It’s not a primer. It’s a summary, meant for the graduate student. But it’s written in a pretty neat way. If you have already had a course on QM, then you should go through it. Several issues (say those related to measurement, and the QM machinery) are explained very neatly here.


A Song I Like:

[Yet another song I liked as a school-boy child; one of those which I still do. \dots Not too sure about the order of the credits though \dots]

(Hindi) “meraa to jo bhi kadam hai…”
Music: Laxmikant-Pyarelal
Singer: Mohammad Rafi
Lyrics: Majrooh Sultanpuri

 

Advertisements

A small utility for blockMesh

The blockMesh is a utility program included in the OpenFOAM distribution. It takes a specification of a domain geometry as the input, and produces a block-structured mesh as the output. The OpenFOAM tutorials illustrate its usage.

However, writing the input file to the blockMesh program (i.e., writing the blockMeshDict file) gets very tedious as soon as you add even just a bit of complexity to the domain geometry.

So, I wrote a small utility in Python. It takes a metadata file as its input, and produces the blockMeshDict file corresponding to the interFoam solver, as its output.

The main hassle the script saves you is that you no longer have to manually list all the vertices, let alone refer to them using the implicit indexing scheme, as demanded by the whimsical file-format of the blockMesh utility. Instead, you directly specify the blocks themselves. Then, when it comes to specifying the BCs, once again, you don’t have to specify the faces or patches using vertices. Instead, you directly identify the faces as the local “left/right/front/etc.” face of a particular block. The script will automatically locate and use the right IDs for the vertices. It will also list the vertices in the right order—you no longer have to worry about the normal to the face possibly going into a direction opposite to what is required. Further, the script also automatically lists all the IDs using inline comments in the generated blockMesh dictionary file, so that the file is more readable to you.

The output was tested using the version of the blockMesh program which comes bundled with the blueCFD-core distribution, on Win7 SP1 (64-bit), but not very extensively. It seems to work, though bugs are possible.

Here is the script. I call it “GBMDF.py” (Generate BlockMesh Dictionary File):

'''
Reads a simple metadata file and generates the blockMeshDict file for 
OpenFOAM simulations

Format of the metadata file:
Comments lines begin with # and are ignored
Data are comma separated values, line by line, in the following sequence:
The float value of the "Convert to Meters" factor
Number of Blocks
BlockID, xOrig, yOrig, zOrig, xLen, yLen, zLen, entire string for number of cells and grading (reproduced as is)
Number of different sets (patches) of faces to list for BCs
PatchID, Name, OF type, no. of faces in the patch
block (hex) ID, face ID (0 through 5)
List of faces in this patch: block (hex) ID, face ID (one of 0 through 5)

The face ID is local to the block. The convention is that of OpenFOAM, taken from:
https://github.com/OpenFOAM/OpenFOAM-dev/blob/master/applications/utilities/mesh/generation/blockMesh/blockMesh.C
Accessed on 05 Feb 2018 18:21 HRS IST. 

Here is the copy-paste of the relevant portion from blockMesh.C 
argList::addNote
    (
        "Block description\n"
        "\n"
        "  For a given block, the correspondence between the ordering of\n"
        "  vertex labels and face labels is shown below.\n"
        "  For vertex numbering in the sequence 0 to 7 (block, centre):\n"
        "    faces 0 (f0) and 1 are left and right, respectively;\n"
        "    faces 2 and 3 are front and back; \n"
        "    and faces 4 and 5 are bottom and top::\n"
        "\n"
        "                 7 ---- 6\n"
        "            f5   |\\     |\\   f3\n"
        "            |    | 4 ---- 5   \\\n"
        "            |    3 |--- 2 |    \\\n"
        "            |     \\|     \\|    f2\n"
        "            f4     0 ---- 1\n"
        "\n"
        "       Z         f0 ----- f1\n"
        "       |  Y\n"
        "       | /\n"
        "       O --- X\n"
    );

Excerpt from blockMesh.C is over.

So, what the OpenFOAM convention means is this:
Orient the block such that x runs to the right, 
y to the far (through the page), and z upwards. 
Then,
face 0 is Left (-ve x-face):    (0 4 7 3)
face 1 is Right (+ve x-face):   (1 2 6 5)
face 2 is Front (-ve y-face):   (0 1 5 4)
face 3 is Back (+ve y-face):    (2 3 7 6)
face 4 is Bottom (-ve z-face):  (0 3 2 1)
face 5 is Top (+ve z-face):     (4 5 6 7)

Here is an example MetaData file. Its content begins from the next line:

# This metadata file describes a cube
# Number of Blocks
1
# BlockID, xOrig, yOrig, zOrig, xLen, yLen, zLen, string for number of cells and grading (reproduced as is)
0, 0.0, 0.0, 0.0, 10.0, 5.0 , 3.0, (10 5 3) simplegrading (1 1 1)
# Number of different sets (patches) of faces to list for BCs
2
# PatchID, Name, OF type, no. of faces in the patch
1, sides, wall, 5
# List of faces in this patch: block (hex) ID, face ID (0 through 5)
0, 0
0, 1
0, 4
0, 5
0, 2
# PatchID, Name, OF type, no. of faces in the patch
1, topInlet, patch, 1
# List of faces in this patch: block (hex) ID, face ID (0 through 5)
0, 3

Example File Got Over at the Above Line

Usage: Open a command line terminal and type:
python GBMDF.py InputMetaDataFileName OutputFileName
'''

import sys

#########################################
# String constants

str0 = '''/*--------------------------------*- C++ -*----------------------------------*\\
| =========                 |                                                 |
| \\\\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
|  \\\\    /   O peration     | Version:  5                                     |
|   \\\\  /    A nd           | Web:      www.OpenFOAM.org                      |
|    \\\\/     M anipulation  |                                                 |
\*---------------------------------------------------------------------------*/
FoamFile
{
    version     2.0;
    format      ascii;
    class       dictionary;
    object      blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

convertToMeters\t'''

str1 = "vertices\n(\n"

str2 = ");\n\nblocks\n(\n"

str3 = ");\n\nedges\n(\n);\n\nboundary\n(\n"

str4 = "\n);\n\nmergePatchPairs\n(\n);\n\n// ************************************************************************* //\n"

#################################################
# Global Data

# Basically, these are maps of vertex coordinates to IDs, and vice-versa.
# These maps are stored as Python dictionaries.
# We create the key for the floating point vertex coordinates 
# (fx, fy, fz) by printing them to a consistently formatted 
# string ("fx fy fz"). The vertex ID is an int
mapVtxToNum = {}
mapNumToVtx = {}
# Precision to use in formatting vertex key strings and in writing 
# floating point numbers in the output file
gnPrec = 6

# This is a list of blocks. Each block is a list of vertex IDs (int's), 
# in the OpenFOAM order (see the doc comment above)
aBlocks = []


#################################################
# Helper functions

def readNextDataLine(theFile):
    sLine = ""
    while True:
        sLine = theFile.readline().strip()
        # ignore empty lines
        if len(sLine) == 0:
            continue
        # ignore comment lines
        nIndex = sLine.find("#")
        if 0 == nIndex:
            continue
        if -1 == nIndex:
            break
    return sLine

def tokenize(sLine):
    toks = sLine.split(",")
    for t in range(len(toks)):
        toks[t] = toks[t].strip()
    return toks

#########################################################
# Vertices-related functions

# Input is floating point numbers. Returns the key string 
# to be used in the vertex (coordinates) -> vertex ID map.
def createVertexKeyString( fx, fy, fz, nPrec =gnPrec):
    fx = round(fx, nPrec)
    fy = round(fy, nPrec)
    fz = round(fz, nPrec)
    sFormat = "%%0.%dlf %%0.%dlf %%0.%dlf" % (nPrec, nPrec, nPrec)
    sKey = sFormat % (fx, fy, fz)
    return sKey

def checkAddVertex(fx, fy, fz):
    vtxKeyStr = createVertexKeyString( fx, fy, fz )
    if mapVtxToNum.has_key(vtxKeyStr):
        nVtx = mapVtxToNum[vtxKeyStr]
        return nVtx, vtxKeyStr
    else:
        nNewVtx = len(mapVtxToNum)
        mapVtxToNum[vtxKeyStr] = nNewVtx
        mapNumToVtx[nNewVtx] = vtxKeyStr
        return nNewVtx, vtxKeyStr

# Get the set of vertex IDs for a given local face ID 
# of a given block (hex)
def getFace(blk,nFaceCode):
    f = []
    if 0 == nFaceCode:
        f = [blk[0],blk[4],blk[7],blk[3]]
    elif 1 == nFaceCode:
        f = [blk[1],blk[2],blk[6],blk[5]]
    elif 2 == nFaceCode:
        f = [blk[0],blk[1],blk[5],blk[4]]
    elif 3 == nFaceCode:
        f = [blk[2],blk[3],blk[7],blk[6]]
    elif 4 == nFaceCode:
        f = [blk[0],blk[3],blk[2],blk[1]]
    elif 5 == nFaceCode:
        f = [blk[4],blk[5],blk[6],blk[7]]
    else:
        f = None
    return f


############################## MAIN #################

if __name__ == "__main__":

    sInFile = sys.argv[1]
    sOutFile = sys.argv[2]

    inFile = open(sInFile, "r")
    outFile = open(sOutFile, "w+")

    sConvertToMeters = readNextDataLine(inFile)
    outFile.write(str0)
    outFile.write("%s;\n\n" % sConvertToMeters)
    outFile.write(str1)

    nBlocks = int(readNextDataLine(inFile))
    for b in range(nBlocks):
        str = readNextDataLine(inFile)
        toks = tokenize(str)

        nBlockID = int(toks[0])
        x0 = float(toks[1])
        y0 = float(toks[2])
        z0 = float(toks[3])
        x1 = x0 + float(toks[4])
        y1 = y0 + float(toks[5])
        z1 = z0 + float(toks[6])

        n0, vtx0 = checkAddVertex(x0, y0, z0)
        n1, vtx1 = checkAddVertex(x1, y0, z0)
        n2, vtx2 = checkAddVertex(x1, y1, z0)
        n3, vtx3 = checkAddVertex(x0, y1, z0)

        n4, vtx4 = checkAddVertex(x0, y0, z1)
        n5, vtx5 = checkAddVertex(x1, y0, z1)
        n6, vtx6 = checkAddVertex(x1, y1, z1)
        n7, vtx7 = checkAddVertex(x0, y1, z1)

        blk = [n0, n1, n2, n3, n4, n5, n6, n7, toks[7], nBlockID]
        aBlocks.append( blk )

    nVertices = len(mapNumToVtx)
    for n in range(nVertices):
        vtxKeyStr = mapNumToVtx[n]
        strVtx = "\t( %s ) \t// vertex ID: %d\n" % (vtxKeyStr, n)
        outFile.write(strVtx)
    outFile.write(str2)
    for b in range(nBlocks):
        blk = aBlocks[b]
        str = "\thex (%2d %2d %2d %2d %2d %2d %2d %2d) %s\t// Block ID: %d\n" \
			%(blk[0],blk[1],blk[2],blk[3],blk[4],blk[5],blk[6],blk[7],blk[8],blk[9])
        outFile.write(str)
    outFile.write(str3)

    nPatchListings = int(readNextDataLine(inFile))
    for p in range(nPatchListings):
        sLine = readNextDataLine(inFile)
        toks = tokenize(sLine)
        nPatchNumber = int(toks[0])
        sPatchName = toks[1]
        sOFType = toks[2]
        nFaces = int(toks[3])

        outFile.write("\t%s\t// Patch Number: %d\n\t{\n" % (sPatchName, nPatchNumber) )
        outFile.write("\t\ttype\t%s;\n\t\tfaces\n\t\t(\n" % sOFType )

        asFaceCodes = ["Left", "Right", "Front", "Back", "Bottom", "Top"]

        for f in range(nFaces):
            sLine = readNextDataLine(inFile)
            toks = tokenize(sLine)
            nBlockID = int(toks[0])
            nFaceCode = int(toks[1])
            blk = aBlocks[nBlockID]
            face = getFace(blk,nFaceCode)
            outFile.write("\t\t\t(%2d %2d %2d %2d) // BlockID: %d Face: %s\n" \
                           % (face[0],face[1],face[2],face[3], nBlockID, asFaceCodes[nFaceCode] ))
        outFile.write("\t\t);\n\t}\n\n")
    outFile.write(str4)
    print( "Done! See the file: %s" % sOutFile)

# EOF

<hr />

And, here is an example meta data file, the one for the damBreak case of interFoam. Go through it once. A small explanatory note appears in the next section.

# This metadata file describes the geometry used for the interFoam 
# solver of OpenFOAM. Use this file as an input to the Python
# GBMDF.py script, to produce the blockMeshDict file.
# Written by and copyright (c) Ajit R. Jadhav. All rights reserved.
# This is a freeware. Use it at your own risk.
# Version: 13 April 2018.
#####################################################################

# The case given here is that of the damBreak tutorial of OpenFOAM.
# Note, the tutorial assumes that the gravity acts along the -ve
# y-axis, whereas the blockMesh source code shows that top and bottom
# are taken, in the local coordinate system for each block, along the
# +ve and -ve z-axis, respectively. Thus, this tutorial is a bit 
# confusing as far as the blockMesh part is concerned.


# ConvertToMeters
0.146

# Number of Blocks
5

# BlockID, xOrig, yOrig, zOrig, xLen, yLen, zLen, string for number of cells and grading (reproduced as is)
0, 0, 0, 0, 2, 0.32876, 0.1, (23 8 1) simpleGrading (1 1 1)
1, 2.16438, 0, 0, 1.83562, 0.32876,  0.1, (19 8 1) simpleGrading (1 1 1)
2, 0, 0.32876, 0, 2, 3.67124, 0.1, (23 42 1) simpleGrading (1 1 1)
3, 2, 0.32876, 0, 0.16438, 3.67124, 0.1, (4 42 1) simpleGrading (1 1 1)
4, 2.16438, 0.32876, 0, 1.83562, 3.67124, 0.1, (19 42 1) simpleGrading (1 1 1)

# Number of different sets (patches) of faces to list for BCs
4

# PatchID, Name, OF type, no. of faces in the patch
0, leftWall, wall, 2
# List of faces in this patch: block (hex) ID, local face ID (0 through 5)
0, 0
2, 0

# PatchID, Name, OF type, no. of faces in the patch
1, rightWall, wall, 2
# List of faces in this patch: block (hex) ID, local face ID (0 through 5)
1, 1
4, 1

# PatchID, Name, OF type, no. of faces in the patch
# Note, for the damBreak case as presented in the OpenFOAM tutorials,
# the "bottom" is the -ve y-axis, not the -ve z-axis
2, lowerWall, wall, 5
# List of faces in this patch: block (hex) ID, local face ID (0 through 5)
0, 2
0, 1
3, 2
1, 0
1, 2

# PatchID, Name, OF type, no. of faces in the patch
3, atmosphere, patch, 3
# List of faces in this patch: block (hex) ID, local face ID (0 through 5)
# Note, for the damBreak case as presented in the OpenFOAM tutorials,
# the "top" is the +ve y-axis, not the +ve z-axis. 
2,3
3,3
4,3

In creating the metadata file, follow these steps:

  1. First, draw the global coordinate system using the OpenFOAM convention (given in its source code, here [^]).
  2. Then, prepare a sketch of the domain geometry. Remember, with every protrusion or dent you add, you have to add a number of blocks. That’s the way blockMesh works.
  3. Number all these blocks suitably, starting from 0.
  4. Make a table of blocks, having the following columns: blockID, the three coordinates of its origin, the three lengths along the three coordinate axes.
  5. Mark the faces on which you will be applying boundary conditions. Number them suitably, starting with 0.
  6. Make a table of faces carrying BCs, having the following columns: face ID, the block ID of which this is a face, and the local face code for this face, according to the OpenFOAM convention
  7. Now you are set. You can write the metadata file.

One reason I didn’t write any ReadMe.txt file is because I wanted to upgrade the format of the input (metadata) file from the current ad-hoc format to a more descriptive, XML-based one. However, I didn’t get the time to do that. (I wrote this script some time in February.) Also, the last time I thought about it, I was not sure whether I should continue with the current way of specifying the block or not. The current way is to specify the coordinates of its origin and the three lengths. But, may be, there are easier ways to specify blocks. For instance, you could specify the first block by giving its origin and three lengths (as is the case now), and then, for the next block, specify it as being adjacent to the first block, touching it on the left/right/front/etc. … I will see if such simplifications can be easily added or not.

Once I extend the script and XML-ize the input data format, I may publish the final version of this script via a journal paper or so. (Yes, I need to enhance my resume!)

In the meanwhile, try it out. I would appreciate receiving any feedback, including suggestions for improvements.

Bye for now…


A Song I Like:

[It was a song I liked when I was a school-boy. I still do.]

(Hindi) “chaahe raho door, chaahe raho paas…”
Music: R. D. Burman
Singers: Kishore Kumar, Lata Mangeshkar
Lyrics: Majrooh Sultanpuri

 

Also, a boy…

“I don’t care about your political compulsions, the ideology of your party, your attachment to a religion and your political loyalties. If you don’t crack down hard and do so publicly on those who hurt an 8-yr old girl, you don’t deserve to be an Indian leader.” –Chetan Bhagat (via Twitter)

Also, a boy.

 

May the person from Oakland, CA, USA, please stand up and be counted?

May the person from Oakland, CA, USA, please stand up and be counted?

I mean the one who has been hitting my blog, in the rather more recent times, a bit too far often to be otherwise statistically justifiable?

Hmmm….?

[The predecessor to him, during the Obama years, was someone similar from “Mississauga, Canada.”

But nearly not as noticeable, robotic, and therefore, not so readily noticeable. At least to me, back then.]


And once again: If you are/want to be fake, leave this blog alone. I don’t need your support.

For one simple reason: I know you can’t give me that.

Another reason, viz. the fact that I have been a programmer, and so know: Robots are controlled by people.


No songs section for this post.