- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello. In MSC.Marc with the Intel XE 2015 Fortran compiler there is the demonstration example e8x94c.dat on deformation of a plate. Without use of file u8x94c.f on Fortran with the method usplit_mesh, shown below, deformation of a plate is run without a splitting of faces of the hexagon finite elements. After adding file u8x94c.f, deformation of a plate is run with a splitting of faces (written above in code in the method usplit_mesh) of hexagon finite elements.
In file u8x94c.f is declared the method usplit_mesh with ten parameters, stated below. From the theory of programming it is known, that the method usplit_mesh is not run, until it is called with a task of certain values for all ten parameters, for example with the value “1” for the variable “icall”. At running of the demonstration example e8x94c.dat on deformation of a plate with use of file u8x94c.f with method usplit_mesh, somewhere is called the method usplit_mesh with the certain values for all ten parameters, but where is called, it is unknown.
What code should be written in the method usplit_mesh, shown below, to learn, where the method usplit_mesh is called? Thanks.
subroutine usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist,
$ ifacelist,nfacelist,inc,time,timeinc)
#ifdef _IMPLICITNONE
implicit none
#else
implicit logical (a-z)
#endif
integer nodelist,nlist,iedgelist,nedgelist,ifacelist,nfacelist
integer icall,inc
real*8 time,timeinc
dimension nodelist(*),iedgelist(2,*),ifacelist(4,*)
integer num,i,alt
if (icall.eq.1) then
alt=3
c alternative 1: specify a sequence of nodes
if (alt.eq.1) then
nlist=7
num=0
do i=57,63
num=num+1
nodelist(num)=i
enddo
elseif (alt.eq.2) then
c alternative 2: specify a list of edges in any order
nedgelist=6
iedgelist(1,1)=57
iedgelist(2,1)=58
iedgelist(1,2)=62
iedgelist(2,2)=63
iedgelist(1,3)=59
iedgelist(2,3)=60
iedgelist(1,4)=58
iedgelist(2,4)=59
iedgelist(1,5)=60
iedgelist(2,5)=61
iedgelist(1,6)=61
iedgelist(2,6)=62
elseif (alt.eq.3) then
c 3d: give a list of faces
nfacelist=4
ifacelist(1,1)=819
ifacelist(2,1)=817
ifacelist(3,1)=822
ifacelist(4,1)=824
c
ifacelist(1,2)=817
ifacelist(2,2)=57
ifacelist(3,2)=58
ifacelist(4,2)=822
c
ifacelist(1,3)=829
ifacelist(2,3)=827
ifacelist(3,3)=822
ifacelist(4,3)=824
c
ifacelist(1,4)=822
ifacelist(2,4)=827
ifacelist(3,4)=58
ifacelist(4,4)=59
endif
endif
return
end
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you read that, it was incorrect. Visual Studio Express Edition has never supported anything other than Microsoft languages (and it came into existence long after Microsoft left the Fortran market.) (One could do command-line builds of Fortran, but not debugging, with Visual Studio Express Editions.)
However, Microsoft now offers Visual Studio Community Edition for free, if you qualify, and it does support Intel Fortran. You will need the latest version of Intel Parallel Studio XE 2017 (Update 4) to support Visual Studio 2017 Community Edition.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can add a USE IFPORT statement in the subroutine that you want and CALL TRACEBACKQQ() at a selected location in the subroutine. You may also pass optional arguments to that routine if you wish, especially if you want the program to print a traceback and continue execution; see the TRACEBACKQQ documentation for details. You should compile with the /traceback option if you use this approach and you want line numbers in the traceback.
Note that if you build a DLL with such a call to TRACEBACKQQ and that DLL is called by a package such as MARC, Fluent, etc., you may not find the traceback information to be of much use since there are no debug symbols in the caller chain.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for your recommendations.
On this subject on the USE IFPORT statement, I have seen the corresponding links:
https://software.intel.com/en-us/node/694591
https://software.intel.com/en-us/node/680209
https://software.intel.com/en-us/node/535322
https://software.intel.com/en-us/node/693726
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/533975
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/537434
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/270346
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/268049
https://software.intel.com/en-us/comment/1904093
https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/515131
In MSC.Marc with the Intel XE 2015 Fortran compiler in the usplit_mesh method, given above, after the line
#endif
I wrote the statement
USE IFPORT
and in the *.log file I received the following error message:
u8x94c.f(104): error #6278: This USE statement is not positioned correctly within the scoping unit.
USE IFPORT
Write, please, how it is correct to write USE IFPORT and CALL TRACEBACKQQ() in the usplit_mesh method, given above? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
See the Fortran documentation; specifically, see https://software.intel.com/en-us/node/678493 regarding the rules on the placement of USE statements.
In general, unqualified Web searches often yield too many "results" to be useful. This is especially true of searches related to the syntax rules of a programming language.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Following the page:
https://software.intel.com/en-us/node/694109
in the usplit_mesh method, given above, after the line:
subroutine usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist,
$ ifacelist,nfacelist,inc,time,timeinc)
I wrote the line:
USE IFCORE
and after the line:
if (icall.eq.1) then
alt=3
I wrote a line:
CALL TRACEBACKQQ()
After start on running of a demonstration example of e8x94c.dat with u8x94c.f, Marc with the Intel XE 2015 Fortran compiler solved this task, however a traceback report is absent.
How to define, where the method usplit_mesh is called by specific parameters? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
That seems to be an ill-considered location for a call to TRACEBACKQQ. What do you expect the value of ICALL to be? If that is anything different from 1, there will be no traceback printed.
It would probably be better to make the call to TRACEBACKQQ the very first executable statement in the subroutine.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I wrote the line CALL TRACEBACKQQ() in different places, but there is no answer to a question.
The question remains open: Where in Marc, to the usplit_mesh method, the concrete parameters are set? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The tracebackqq report is probably sent to one of the Marc output files or alternatively into a blackhole. The environment variable FOR_DIAGNOSTIC_LOG_FILE=c:\mylog.txt can be set to direct the output to a named file.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
but do you even know if usplit_mesh is even called my marc in your tests? Write some output to a file to prove that.....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for answers.
We carry out: Marc, File, Import, Marc Input, and we import the Marc demonstration file e8x94c.dat. In a graphic window, the plate appears. We add the file u8x94c.f to the Run Job panel, and we click the Submit button. In several seconds, the solution of a task comes to an end. After the choice of commands File, Results, Open Default, Monitor results file, the plate begins to be deformed with the splitting of the faces, set above in the usplit_mesh method for alt=3.
To two files e8x94c.dat, u8x94c.f are added more the 6 files: *_job1.dat, *_job1.log, *_job1.out, *_job1.sts, *_job1.t16, *_job1.t16.mud.
What of these files to show me for you? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Valery, please realize that most of us do not have Marc or any other FEA, so your reporting details on running such packages is not of much use. As Andrew remarked, at this point you should focus on finding out whether or not the subroutine usplit_mesh() is called. If it is not called, the questions of where it was called from and with what arguments are pointless.
It is only after you have succeeded in getting Marc to call the subroutine that you can look at the details regarding the calling sequence and argument values. I for one, and most users in this forum probably, will not be able to help you regarding those details. You really should look for a different, Marc related, forum.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for answers.
In the subroutine usplit_mesh, provided above, I wrote
write(*,*) '"icall" is:'
write(6,*) icall
but after a task solution in Marc with the Intel XE 2015 Fortran compiler, in three files *_job1.log, *_job1.out, * _job1.sts, which can be opened in Nodepad, there is no value for “icall”?
How to me to display the value “icall”? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is possible that Marc captures outputs to STDOUT. If it does, the output of WRITE(*,... statements would not appear on the console. What you can try to overcome this problem is to (i) OPEN a text file with a name such as ICALL.TXT, a unit number such as, say, 51, that is not already associated, (ii) write a message such as "ICALL - ..." to it, and close the file. If, after the Marc run, the file ICALL.TXT does not exist, that would be an indication that the subroutine was never called.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for answers.
Excuse me, please, but I understood nothing. Write, please, in more detail, how to answer a question:
How to me to display the value “icall”? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Add these lines of code to the subroutine, after any existing declaration statements, and run as before. Look for the file icall.log after the run.
C integer lun C lun=0 open(file='icall.log',newunit=lun,status='replace') if (lun .lt. 0) then write(lun,'(1x,I6,2x,A,2x,i12)')lun,'ICALL = ',icall close(lun) end if
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the lines of code.
In MSC.Marc with the Intel XE 2015 Fortran compiler, in file u8x94c.f, I wrote the code, which you kindly provided, in the subroutine usplit_mesh (shown above), I executed this demonstration example e8x94c.dat of Marc, in the folder C, Users, Valery, I opened the file icall.log in Notepad, and I received the record:
-150 ICALL = 3
In this subroutine usplit_mesh from lines:
if (icall.eq.1) then
alt=3
follows, that the parameter icall should be equal to 1. For value icall=3, the code, given in this subroutine, will not be run, but it is run.
Why the parameter icall is equal 3 in the file icall.log instead of 1? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your findings in #16 establish that
- the subroutine usplit_mesh() is, indeed, called by Marc,
- The value of ICALL is not 1, as you may have expected, but 3,
- The subroutine has no provision for handling the case ICALL = 3
The question of why ICALL=3 is one that I cannot answer, not being a Marc user. You should, however, be able to call TRACEBACKQQ as the first statement in the subroutine and obtain a traceback listing that you can use in a Marc forum.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for answers.
Following the page:
https://software.intel.com/en-us/node/694109
in the subroutine usplit_mesh, given above, after the line:
subroutine usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist,
$ ifacelist,nfacelist,inc,time,timeinc)
I wrote the line:
USE IFCORE
and after the line:
if (icall.eq.1) then
alt=3
I wrote the line:
CALL TRACEBACKQQ("My application message string")
After start on running of a demonstration example of e8x94c.dat with u8x94c.f, Marc with the Intel XE 2015 Fortran compiler stopped a solution of this task.
In the folder C, Windows, Temp appeared the file MpCmdRun.log of the following contents:
MpCmdRun: Command Line: "c:\program files\windows defender\MpCmdRun.exe" SpyNetService -RestrictPrivileges -AccessKey D9367E57-FA6C-E32D-1801-71013217DD95
Start Time: 11:41:20
MpCmdRun: End Time: 11:41:20
Write, please, where it is correct to write the lines:
USE IFCORE
CALL TRACEBACKQQ("My application message string")
to receive the useful messages? Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1] Firstly your Fortran code is only very small, attaching your code is MUCH better than using words to describe what you did
2] Please please use the {code} Fortran option (like below) to add code, it makes it readable
3] If you call TRACEBACKQQ without user_exit_code=-1 it will assume user_exit_code=0 and terminate the program.
4] With MARC user Fortran make a "test" main program so you can use the debugger to step through the code to make sure it does what you want it to before trying ruin run MARC.
4] I have added some source that should help you (and tested it)
subroutine usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist, $ ifacelist,nfacelist,inc,time,timeinc) use ifport, only: setenvqq use ifcore, only: TRACEBACKQQ implicit none integer nodelist,nlist,iedgelist,nedgelist,ifacelist,nfacelist integer icall,inc real*8 time,timeinc dimension nodelist(*),iedgelist(2,*),ifacelist(4,*) integer num,i,alt integer lun logical lret C lun = 0 open( file='icall.log', newunit=lun, status='unknown', + access='append' ) if (lun /= 0) then write(lun,'(1x,I6,2x,A,2x,i12)') lun,'ICALL = ',icall close(lun) lret = setenvqq("FOR_DIAGNOSTIC_LOG_FILE=icall.log") CALL TRACEBACKQQ("My application message string", + user_exit_code=-1) end if c if (icall.eq.1) then alt=3 c alternative 1: specify a sequence of nodes if (alt.eq.1) then nlist=7 num=0 do i=57,63 num=num+1 nodelist(num)=i enddo elseif (alt.eq.2) then c alternative 2: specify a list of edges in any order nedgelist=6 iedgelist(1,1)=57 iedgelist(2,1)=58 iedgelist(1,2)=62 iedgelist(2,2)=63 iedgelist(1,3)=59 iedgelist(2,3)=60 iedgelist(1,4)=58 iedgelist(2,4)=59 iedgelist(1,5)=60 iedgelist(2,5)=61 iedgelist(1,6)=61 iedgelist(2,6)=62 elseif (alt.eq.3) then c 3d: give a list of faces nfacelist=4 ifacelist(:,1) = [819,817,822,824] ifacelist(:,2) = [817,57,58,822] ifacelist(:,3) = [829,827,822,824] ifacelist(:,4) = [822,827,58,59] endif endif return end
program main implicit none integer :: nlist, nedgelist, nfacelist integer :: nodelist(7), iedgelist(2,6), ifacelist(4,6) integer :: icall, inc real(8) :: time, timeinc do ICALL = 1, 3 call usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist,ifacelist,nfacelist,inc,time,timeinc) enddo end program main
-129 ICALL = 1 My application message string Image PC Routine Line Source libifcoremdd.dll 5C295B1B Unknown Unknown Unknown functest.exe 008C12AA _USPLIT_MESH 22 Source2.for functest.exe 008C1081 _MAIN__ 8 Source1.f90 functest.exe 008C18AF Unknown Unknown Unknown functest.exe 008C4209 Unknown Unknown Unknown functest.exe 008C434D Unknown Unknown Unknown KERNEL32.DLL 76F062C4 Unknown Unknown Unknown ntdll.dll 77A50FD9 Unknown Unknown Unknown ntdll.dll 77A50FA4 Unknown Unknown Unknown -130 ICALL = 2 My application message string Image PC Routine Line Source libifcoremdd.dll 5C295B1B Unknown Unknown Unknown functest.exe 008C12AA _USPLIT_MESH 22 Source2.for functest.exe 008C1081 _MAIN__ 8 Source1.f90 functest.exe 008C18AF Unknown Unknown Unknown functest.exe 008C4209 Unknown Unknown Unknown functest.exe 008C434D Unknown Unknown Unknown KERNEL32.DLL 76F062C4 Unknown Unknown Unknown ntdll.dll 77A50FD9 Unknown Unknown Unknown ntdll.dll 77A50FA4 Unknown Unknown Unknown -131 ICALL = 3 My application message string Image PC Routine Line Source libifcoremdd.dll 5C295B1B Unknown Unknown Unknown functest.exe 008C12AA _USPLIT_MESH 22 Source2.for functest.exe 008C1081 _MAIN__ 8 Source1.f90 functest.exe 008C18AF Unknown Unknown Unknown functest.exe 008C4209 Unknown Unknown Unknown functest.exe 008C434D Unknown Unknown Unknown KERNEL32.DLL 76F062C4 Unknown Unknown Unknown ntdll.dll 77A50FD9 Unknown Unknown Unknown ntdll.dll 77A50FA4 Unknown Unknown Unknown
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the code.
I inserted in Notepad the code, which you kindly provided, into the file u8x94c.f instead of the previous subroutine usplit_mesh, shown above.
After start on running of a demonstration example of e8x94c.dat with u8x94c.f, Marc with the Intel XE 2015 Fortran compiler displayed the following errors:
…
Default bin directory: C:\MSC.Software\Marc\2016.0.0\marc2016\bin\win64i8
Material database : C:\MSC.Software\Marc\2016.0.0\marc2016\AF_flowmat\
ifort /fpp /c /DWIN32_intel -D_IMPLICITNONE /nologo /integer_size:64 -DI64 -DMKL -DOPENMP -DOMP_COMPAT -D_MSCMARC -DWIN64 /I"C:\MSC.Software\Marc\2016.0.0\marc2016\common" /I"C:\MSC.Software\Marc\2016.0.0\marc2016\bcsgpusolver\common" /I"C:\MSC.Software\Marc\2016.0.0\marc2016\mumpssolver\include" /I"C:\MSC.Software\Marc\2016.0.0\marc2016\intelmpi\win64\include" /O2 /Qip /Qvec- /Qsafe-cray-ptr /switch:fe_old_modvar /W0 /Qopenmp /Qopenmp-threadprivate:compat -DCASI -DPARDISO -DMUMPS -DBCSGPU -DCUDA /MD -DDDM /object:"C:\Users\Valerij\u8x94c.obj" "C:\temp\e8x94c_var26\u8x94c.f"
C:\temp\e8x94c_var26\u8x94c.f(14): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ( % [ : . = =>
C
---------^
C:\temp\e8x94c_var26\u8x94c.f(16): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ( * <IDENTIFIER> <CHAR_CON_KIND_PARAM> <CHAR_NAM_KIND_PARAM> <CHARACTER_CONSTANT> ...
open( file='icall.log', newunit=lun, status='unknown',
--------------------------------------------------------------------^
C:\temp\e8x94c_var26\u8x94c.f(17): error #5276: Unbalanced parentheses
+ access='append' )
------------------------------------^
C:\temp\e8x94c_var26\u8x94c.f(17): error #5082: Syntax error, found '+' when expecting one of: <LABEL> <END-OF-STATEMENT> ; BLOCK PROGRAM BLOCKDATA MODULE INTEGER REAL COMPLEX ...
+ access='append' )
-------------^
C:\temp\e8x94c_var26\u8x94c.f(22): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ( * ) :: , <IDENTIFIER> <CHAR_CON_KIND_PARAM> <CHAR_NAM_KIND_PARAM> <CHARACTER_CONSTANT> ...
CALL TRACEBACKQQ("My application message string",
------------------------------------------------------------------^
C:\temp\e8x94c_var26\u8x94c.f(23): error #5276: Unbalanced parentheses
+ user_exit_code=-1)
----------------------------------------------------^
C:\temp\e8x94c_var26\u8x94c.f(23): error #5082: Syntax error, found '+' when expecting one of: <LABEL> <END-OF-STATEMENT> ; BLOCK PROGRAM BLOCKDATA MODULE INTEGER REAL COMPLEX ...
+ user_exit_code=-1)
-------------^
C:\temp\e8x94c_var26\u8x94c.f(25): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ( % [ : . = =>
c
---------------^
C:\temp\e8x94c_var26\u8x94c.f(28): error #5082: Syntax error, found IDENTIFIER 'SPECIFYASEQUENCEOFNODES' when expecting one of: BLOCK DO FORALL SELECT SELECTCASE SELECTTYPE WHERE ASSOCIATE CRITICAL IF
c alternative 1: specify a sequence of nodes
--------------------------^
C:\temp\e8x94c_var26\u8x94c.f(37): error #5082: Syntax error, found IDENTIFIER 'SPECIFYALISTOFEDGESINANYORDER' when expecting one of: BLOCK DO FORALL SELECT SELECTCASE SELECTTYPE WHERE ASSOCIATE CRITICAL IF
c alternative 2: specify a list of edges in any order
-------------------------^
C:\temp\e8x94c_var26\u8x94c.f(52): error #5082: Syntax error, found IDENTIFIER 'GIVEALISTOFFACES' when expecting one of: BLOCK DO FORALL SELECT SELECTCASE SELECTTYPE WHERE ASSOCIATE CRITICAL IF
c 3d: give a list of faces
---------------^
C:\temp\e8x94c_var26\u8x94c.f(69): error #5082: Syntax error, found END-OF-STATEMENT when expecting one of: ( * ) :: , . % + - [ : . ** / // .LT. < .LE. <= .EQ. == ...
call usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist,iface
-------------------------------------------------------------------------------^
C:\temp\e8x94c_var26\u8x94c.f(69): error #6404: This name does not have a type, and must have an explicit type. [IFACE]
call usplit_mesh(icall,nodelist,nlist,iedgelist,nedgelist,iface
--------------------------------------------------------------------------^
compilation aborted for C:\temp\e8x94c_var26\u8x94c.f (code 1)
compile failed for C:\Users\Valerij\u8x94c.f
Marc Exit number 3
I tried to correct independently errors, but I do not have enough knowledge of Fortran.
Help to correct errors, please. Thanks.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In an old style FIXED format source file columns 1-6 are usually are usually blank and the Fortran starts in col 7. In the #19 source the $ on line 2 and the + on line 17 and 23 is in col 6 indicating a continuation line. If it is not col 6 then errors will result...
i think your source file formatting is a bit screwed. If you hover your mouse over the source in #19 a menu appears at the top right and if you click the <> icon you get a plain text popup window that you can just select all then copy paste into a Fortran file....
I also suggest it would help you if you get a primer on Fortran and do a little reading to understand basics.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page