Tomi Maila
Members-
Posts
849 -
Joined
-
Last visited
-
Days Won
9
Content Type
Profiles
Forums
Downloads
Gallery
Everything posted by Tomi Maila
-
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 30 2007, 02:32 AM) I was unable to replicate what I saw yesterday. I'll post a VI if I can replicate the weird behaviour I saw. QUOTE(Aristos Queue @ Aug 30 2007, 02:32 AM) The subVI doesn't know. The subVI is compiled with its own inplaceness. If it doesn't preserve inplaceness across outputs, then the caller will copy the output back into the original buffer. There aren't any references. If we take a look at your example class method below, I don't actually see how this VI is an in-place VI. The input buffer and the output buffer are clearly different. Or in other words, the output buffer is not a modified version of the input buffer. So how does LabVIEW interpret this VI to preserve inplaceness across outputs? QUOTE(Aristos Queue @ Aug 30 2007, 02:32 AM) Honestly, I'm not sure. But I believe that the natural dataflow expression of LV will kick in and make creating the tree impossible. Dataflow and functional programming are very similar in concepts. Actually dataflow can be considered to be a subset of functional programming. And functional programming has always allowed this kind of data structures and their manipulation in a very efficient and easy way. So I don't see why LabVIEW in principle couldn't do this. As I already said I've used recursive data structures before in LabVIEW in this particular way you used them now but without new memory management nodes and structures. And they appear to work somehow. To proove myself right here, I attach a version of AQ's map where all the in-place tircks are removed. And it appears to work. This is perhaps what has confused me the most in this thread. I've used these kind of memory models for LVOOP for ages (1 year) and they have appeared to work. Now AQ has given a message that actually they may not work or they are not intended to work. This has really confused me. Especially when I don't understand why these shouldn't work. I still don't see what is the catch why these shouldn't work. http://forums.lavag.org/index.php?act=attach&type=post&id=6810 QUOTE(Aristos Queue @ Aug 30 2007, 02:32 AM) Let me be very clear here: If I do not wire the output of the Unbundle node, LV is correct to optimize out the Bundle node. Every rule of dataflow says that the execution of that bundle node should not be necessary -- there's nothing downstream from the Bundle node to need the data. Remember, we're violating dataflow here -- we're saying that we need LV to change the value on a wire even though that wire isn't going anywhere because the memory is actually shared with items that are going on down the wire. I actually meant why did you have those copy always nodes there. You said that you had them there to avoid incorrect optimization. What kind of incorrect optimization could LV do? QUOTE(Aristos Queue @ Aug 30 2007, 02:32 AM) How will this keep working in future LV versions? Don't know. In fact, I'm pretty sure that LV's compiler will eventually be smart enough to optimize this out unless I deliberately put something in to keep this working. I'm not entirely sure that it should keep working. By many arguments, the code I've written for the Map is a bug that should be fixed, probably in 8.5.1. This bit of magick arises as the confluence of multiple features, and I've posted it here to see what everyone thinks. I see a certain elegance to it, but this may be the same romance a moth feels for a flame. So to write future proof code, avoid relying on the memory model or compiler optimizations or in-placeness. -
Just a thought experiment. What happens when you branch a wire that contains a cyclic graph? Wouldn't LabVIEW find itself in an infinite loop of copying the loop. We would need a copy-constructor to avoid this scenario. If you try to avoid this problem and implement a cyclic graph by storing the cyclic reference not by value but as some other sort of reference you end up into another problem. In this case when you branch a wire, LabVIEW doesn't understand that it needs to update the reference to refer to the new tree. To avoid this problem you would also need a copy constructor. One can create cyclic data structures with queues. The simplest example would be to enqueue the queue reference itself. But this is no longer a by value structure and once again, when you branch a wire, you don't get a by-value copy, unless you'd have a copy constructor. So my gut feeling is that you can create some sort of cyclic data structures in LabVIEW, even with LVOOP. But what you cannot do is to get them behave properly when you branch a wire. Unless ofcourse AQ would be so kind that he considers copy constructors an important issue and adds them to the language Tomi
-
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 29 2007, 07:50 PM) Actually I've been using recursive data structures from the day LV 8.20 was introduced with some occasional troubles but I actually never knew there was something wrong with them. One of my most challenging projects that required modifications to a graph constantly failed when I was developing it with 8.20. I though it was due to LV 8.20 bugs, but now it appears to me that it may also have been that I failed to do the things the correct way. But the fact that our team has been extensively using recursive LVOOP data structures means that if you close the syntax from the language, then the programs that we've spends hundreds or even thousands of hours, won't work. I don't think closing this hole is anymore an option. I was rather saying that now that the hole is there you should document how to use it. And make the documentation comprehensive. QUOTE(Aristos Queue @ Aug 29 2007, 07:50 PM) Side note... after today, I may not be posting much for the next week or so. Other stuff going on. I'll try to get a more complete answer to Tomi's questions later today, but no guarantees. I really appreciate if you would. We are just working for a major project that needs to use recursive data structures. I simply need to understand what's going on. -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
In the school we were always told that there is not such thing as too stupid questions. So let me start with the stupid ones. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) I don't even complitely understand what happens here. When I've a cluster constant from which I make two copies using Always Copy primitive and do sequence Unbundle-Swap Values-Bundle for the clusters, LabVIEW makes two buffer copies at the Swap Values node and two buffer copies at the Bundle nodes; one for each bundle. If I do exactly the same thing for LVOOP objects, LabVIEW doesn't do any memory copies. If I use in-place memory structure instead of Unbundle-Bundle sequence LabVIEW does memory copies for the cluster when in-place structure is called but doesn't do memory copies for classes. 1. So my first very simple question is what exactly does Switch Values node and In-Place Memory structure do? Why do they behave differently for different but apparently similar data types. 2. How can I know if an operation really happens in-place or not if it's such a crusial thing when manipulating hierarchical data structures. 3. In-place memory structure is a rather intuitive thing when you look at the examples of its usage in LabVIEW help. However when you make a subVI call inside in-place memory structure the things get more complicated. How does the subVI know that it needs to operate in-place. Is it passed a reference to input-buffer and a reference to output buffer normally. When a VI is called within in-place structure will these two references be the same? What if there are two or more subVIs inside the in-place structure. How does the knowledge of in-placeness propagate trough the VIs? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) We want to do #1 WITHOUT MAKING A COPY OF ANYTHING. Why? Because a single node really is an entire sub-tree. We want to simply connect that subtree into a new place in the graph without duplicating all the pointers. Otherwise all of our efficiency is lost. If we just don't use in-place memory structures and don't mind of making copies, will we be able to use hierarchical data structures such as binary tree without any tricks and risks of interfering parallel wires? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) The node that we're going to delete has the left and right subtrees as member data values. When the deleted node reaches the end of its wire, it will disappear from memory AND WILL TAKE ALL OF ITS MEMBER DATA WITH IT. Haven't we used the Unbundle node to tell LabVIEW that we are going to use two of the data members, Left and Right in this case? Was the problem that if we didn't use Swap Values nodes to write dummy values l and r to the original object X(L,R) private data, LabVIEW would need to make data copies of the Left (L) and Right ® in order to be able to remove original object X(L,R) from memory? And it wouldn't be an in-place operation any more and we would loose the efficiency. Exactly when would X(L,R) disappear from memory? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) So the first thing to do is to give the node about to be deleted some new values for its left and right nodes. We use the Leaf Node constants. The Force Copy primitives (those little small dots for those of you without LV8.5) keeps LabVIEW from trying to be too smart about optimizing copies. How do you know when is LabVIEW going to optimize copies incorrectly either in LV 8.5 or any of the future versions? I guess this is an undocumented issue... How would LabVIEW incorrectly optimize the code in this particular case? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) It guarantees that we have an independent value of a Leaf Node, one for left and one for right. We Swap those two in place of the current subtrees of the node being deleted. So our left and right subtrees are now disconnected from the main tree. So what exatly as happened here. We have had four handles (pointer to pointer) for LabVIEW objects LH,RH,lH and rH. The handles themselves remain in the same addresses but the pointers the handles refer to get exchanged. So LH that has originally referred to a Lp to L. Now refers to another pointer lp to l. Am I right or wrong here? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) Why is the Sequence Structure there? Because if we don't wire the output of the Bundle node, LabVIEW will look at the diagram and say, "Hey! This output is unwired. That means the node is a no-op." And it will optimize out the bundle. How do we know that in a future version of LabVIEW this trick will not be optimized as a no-op? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) That one gets to be put in place of the deleted node because it keeps the maximum number of nodes at the highest possible level of the tree. The shallower subtree is then inserted into the map as if it were a new node. How does LabVIEW know how to write the output of a class in-place on top of the original data. Well this is actually the same as the question I asked above. How does LabVIEW pass the in-placeness to a subVI and back from it in a call chain. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) There are points in this graph where we are modifying a value on one wire which results in a change in value on another parallel wire. Just in case I don't yet see all these occasions, can you explicitly determine which changes to which wires modify the data in which other wires. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) This is a massive no-no for dataflow programming. I complitely agree QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) And yet it works in this situation -- reliably, predictably, and quickly -- without any semaphore or mutex locking. I can't admit I could yet predict this behaviour. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) If you coded it wrong, you could crash LabVIEW.... First of all, you can't do any of this without the memory management primitives. Anyone trying to make this work without the Swap will find themselves coding regular LabVIEW and completely unable to get the map to work the way they'd like it to work. Actually to complitely understand these things, I'd need more examples of what I shouldn't do and what actions are not allowed rather than what actions the correct answers. I need to ask this one more time. If I don't try to do things in-place, will I still have risks of crashing LabVIEW or something similar when I modify hierarchical data structures? QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) Anyone who uses the Swap primitives is definitely on the cutting edge of LabVIEW, because it is so non-intuitive compared with simply crossing the wires. And if you're advanced enough to be playing with these, then I think the full power of options should be open to you. I disagree. LabVIEW has always been a programming language that one can learn without reading books simply by checking the documentation of each node. Now these particula techniques are not documented anywhere. LabVIEW help doesn't tell much anything. Users are tempted to give these new memory management nodes a try. They may soon use them thinking they understand, but they don't. At least if they are as stupid as I'm. There is simply no way a user can learn these techiques if there is not a very comprehensive introduction to these techiques. This is also true for the most advanced users like the ones here at LAVA. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) This hierarchy gives you a Map that is perfect dataflow outside the class --- if you fork the wire, the entire Map duplicates and is thus dataflow safe for all operations, and it can be freely stored in LV2-style globals, global VIs or single-element queues if you decide you need a reference to one. It hides all the "pointer arithmetic" inside its private member VIs, thus guaranteeing the coherency and consistency of the Map and keeping the dangerous dataflow-unsafe functions from being called directly under conditions that might not be safe. What exactly do you mean inside-the-class and outside-the-class. Do you mean that when you use unbundle and bundle nodes, that are only available inside the class, the pointer-like charasteristics appear. Or do you mean that when you use these new memory management functions the pointer like charasteristics appear? As far as I understand, forking a wire inside a class is no different from forking a wire outside a class. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) I'm thinking an essay covering the analysis of this diagram and the related VI hierarchy should be added to the Certified LabVIEW Architect exam. Lucky you who got the exam before this addition -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 29 2007, 01:35 PM) Well, the carbage collection algorithm is not documented. -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
I'm still trying to get hold on this issue. I feel I have a lot of questions but I'll need some time to formulate the questions properly. The questions are not maybe that much related to what AQ says in his answer but rahter what he doesn't say. This example assumes a lot of knowledge on how LabVIEW memory management works and this information is not that well documented. Even though it may be very clear issue for someone working in LV R&D, it is definitely not clear for me as I'm only dependent on the LabVIEW public documentation. For example the documentation of flat sequence doesn't have any information on how the flat sequence affects memory management. To make the discussion on all these subjects easier I suggest the following. I've a little reorganized the layout of the block diagram we are talking about. I've given names to buffers on the block diagram to help follow the program flow and to give joint names to the buffers. Furthermore I've named the Swap Values nodes uniquely. Use these names I've given to refer to different parts of the block diagram we're talking about. http://forums.lavag.org/index.php?act=attach&type=post&id=6791 Branch Node.lvclass:Delete Key.vi, case where the particular node 'X' is deleted. http://forums.lavag.org/index.php?act=attach&type=post&id=6792 Branch Node.lvclass:Delete Key.vi, one of the two symmetric positions on the block diagram where the VI calls itself recursively. -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM) I opened a new thread for this cyclic graph challenge so that we can concentrate in this thread to the binary tree modification operations. I think there is enough challenge in these for most of use for now. -
In another thread Aristos Queue challenged us all to implement a cyclic graph in pure G. I open this new thread for discussing the (close to impossible) challenge. QUOTE(Aristos Queue @ Aug 29 2007, 07:24 AM)
-
Hi, I've just posted a new blog article Using New LabVIEW Merge Tool LVMerge With Tortoise SVN to my blog at ExpressionFlow. Check it out! Tomi
-
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 24 2007, 06:28 AM) I'm like a child eagerly waiting for Christmas... -
One day while sniffing cleaning products....
Tomi Maila replied to LAVA 1.0 Content's topic in LAVA Lounge
QUOTE(eaolson @ Aug 27 2007, 05:27 PM) It's only because you don't belong to the 3% 2% 1% of the people who are not animals gods. -
New Windows 386 supports multitasking, cool
Tomi Maila replied to Michael Aivaliotis's topic in LAVA Lounge
I wonder if Bill himself was the art director for this video -
LabVOOP Usage 1 Year Later
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Justin Goeres @ Aug 25 2007, 12:12 AM) Actually I take a step backwards. I don't think objects should be called private clusters as they are really objects and they should only and always be called objects to avoid confusion. However I don't think LVOOP should actually be called OOP at all. This is the part where I think NI made a wrong choice. The word object holds with LVOOP but the phrase OOP doesn't, at least not complitely. I guess if NI had chosen a different term such as http://expressionflow.com/2007/04/27/object-flow-programming-merging-dataflow-and-object-oriented-programming/' target="_blank">object-flow programming, it would have been easier for LabVIEW users to consider it somewhat different from OOP. There would not have been all those 'where are my by-reference objects' claims. People would have been generally happy that something new was introduced into LabVIEW. But selecting a word that already had a very strong meaning that didn't exactly coincide what LVOOP provided caused and still causes a lot of problems. -
"Get LV Class Default Value.vi" equivalent in 8.5
Tomi Maila replied to Jim Kring's topic in Object-Oriented Programming
QUOTE(Jim Kring @ Aug 24 2007, 09:09 PM) Sure -
How to write SCC Plugin for LabVIEW project
Tomi Maila replied to Abdullah R's topic in Source Code Control
QUOTE(gmart @ Aug 24 2007, 03:06 PM) Actually I think this is a plugin that makes Visual Studio to speak DesignSync protocol. We'd need a plugin that makes DesignSync to speak MS Visual Source Safe protocol. So I guess this plugin is of no help in this situation. Tomi -
LabVOOP Usage 1 Year Later
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Jim Kring @ Aug 24 2007, 07:18 PM) Actually I hate the fact that many things in the context of LabVIEW have names that differs from 'industry standards'. I think it actually slows down the learning process instead of speeding it up as it's harder to tie the new concepts you hear to something you've previously heard of. I actually learned coding LabVIEW quite late compared to many of you, so the learning experiense is still in my fresh memory -
"Get LV Class Default Value.vi" equivalent in 8.5
Tomi Maila replied to Jim Kring's topic in Object-Oriented Programming
Jim, I've used class plugins myself since the times of LV 8.20. The way I do it is that for each plugin, I create a single VI that simply returns the class constant. Then simply dynamically open a reference to this VI. If you use certain naming convention for the VIs (as I do), you can search directory structure for these VIs and open plugins as needed. It's very simple way and doesn't require any special features of LabVIEW 8.5 -
How to write SCC Plugin for LabVIEW project
Tomi Maila replied to Abdullah R's topic in Source Code Control
QUOTE(paracha3 @ Aug 24 2007, 06:05 AM) There is no need to integrate SCC solution to LabVIEW project. May of the LAVA users are using Tortoise SVN for their SCC client. Tortoise SVN is not integrated to LabVIEW project; rather it's integrated to windows explorer. Bottom line is that if you find a SCC client for your SCC server that simply is able to 1) properly synchronize your folders with the SCC server and 2) allows you to use third party diff and merge tools then you should be able to use your SCC server. As most of the SCC servers also have a stand-alone client, I guess you are better off using one of those rather than trying to integrate with LV project. However if you insist integrating with LV project, I guess LV is compatible with MS visual source safe compatible servers. So you can write a wrapper that acts like a MS visual source safe server for LabVIEW direction and as Design Sync client for the server direction. Or maybe there is already a MS Visual Source Safe interface in Design Sync.... Tomi -
LabVOOP Usage 1 Year Later
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
I've been using LVOOP for one whole year now. At the moment all my new projects use LVOOP and I've encapsulated some old libraries to LVOOP as well. With LV 8.20 there were a huge number of issues and the first half year was a nightmare, although an expected nightmare After 8.2.1 was released the life with LVOOP became a lot easier as LVOOP projects became a lot more stable. LVOOP has enormously helped in the architecture of complicated application. The applications can now be much better modularized making building complicated extensible applications possible. I never was against by-value LVOOP and I still find it very suitable for many but not all use cases. The lack of recursive calls was an near show-stopper issue for some projects but now in LV 8.5 it has been fixed. Thanks for the R&D team for this excellent improvement! Over all I'm quite happy with current LVOOP in LV 8.5. This doesn't mean that I think it even close to being complete OOP implementation; there is still a huge amount of work to do. Some improvements I'd like to see in LVOOP in the future: The current development process is simply too slow. Endevo GDS speeds up the development process significatly. However the native development process needs to be speed up a lot by making the process more fluent.Placing class controls and methods is not simple and fast enough. There are two few templates for creating new methods. User should be able to create their own method templates that would integrate to LV Project context menu Editing icons is not fluent and fast enough One should be able copy a method from a sister class so that the icons becomes automatically correct and the class controls are changed One should be able to create override methods from different templates as well, the default scripted override VI is almost never usable by any means [*]The lack of both build in create nodes comparable to new operator in Java as well as lack of build in constructors are an obstacle [*]The support for by-ref classes would still be nice to have [*]I need mixin inheritance everywhere and every day [*]LabVIEW build-in type should really be made classes as well so that they could be passed where LabVIEW Object is expected. For example currently AQ's binary tree map implementation doesn't function for any build-in LabVIEW types. This is a issue that encouter often when I try to make new tools. There is no common parent class for build-in LabVIEW types. There is nothing in principle that would prevent simply calling build-in LabVIEW types classes. [*]Class probes don't work for child classes [*]I'd like to be able to use inner classes (that have access to outer class private data) There may be more issues but I simply need to go now Overall LVOOP is an excellent improvement to LabVIEW. Not having LVOOP would have forced me to move to other programming languages at least part time. Actually I'm still planning to use some other languages as well but at least now I can still use LabVIEW for most of the projects. Great job Aristos Queue & co. And thank you! -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 23 2007, 06:56 AM) My guess: Node Delete Key.vi of Branch Node class calls itself recursively from within in-place memory structure. The in-place memory structure can optimize memory usage only if the buffer that is being edited in-place doesn't get garbage collected. The empty sequence frame is there to keep the edited buffer in memory while the VI is being executed. This somehow affects LabVIEW compilers ability to optimize the execution of the outer in-place memory structure of the calling clone of Node Delete Key.vi. Was it even close? -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 23 2007, 04:38 PM) Ok. I read it. I still don't understand what's going on. I now understand that using LabVIEW in recursive data structures may not be safe. However I've created graphs and trees before and they've functioned if you don't care about occasional crashes. I didn't have any of these in-place memory nodes available in LabVIEW 8.2 or 8.2.1. If I interpret you correctly AQ, you are saying that one can use recrusive memory structures but one needs to use some hocus-pocus non-dataflow programming techniques to do this safely. Did I interpret you completely incorrectly? If not, what are these hocus-pocus tricks one needs to use? -
Map, implemented with classes, for 8.5
Tomi Maila replied to Aristos Queue's topic in Object-Oriented Programming
QUOTE(Aristos Queue @ Aug 23 2007, 06:56 AM) I modified your class to have a little more informative probing system. Now each class in the project has a probe that populates a tree recursively. This way you can actually see what is the structure of the binary tree used in this implementation. http://forums.lavag.org/index.php?act=attach&type=post&id=6727 http://forums.lavag.org/index.php?act=attach&type=post&id=6728 QUOTE(Aristos Queue @ Aug 23 2007, 06:56 AM) You'll find some *fascinating* code that definitely only works in LV8.5 (uses the new inplaceness nodes) on the block diagram of Map.lvlib:Branch Node.lvclass:Node Delete Key.vi. 20 points and a bowl of gruel to the first person who can explain why the *empty* Sequence Structure is labeled "Do not delete". ;-) This particular VI is actually quite weird. Would you like to shed light on what's happing in the method and why all those switch nodes are needed and why do you have always copy nodes and why do you have that 'do not remove' sequence. EDIT: I spend some time trying to figure out what the heck is going on in this particular VI. I can understand from dataflow point of view what's going on but I've no freaking idea of why AQ is using swap values and always copy nodes as well as this empty structure. I tried to profile the VI with LV memory profiler. The memory consumption was not always the same, which is weird. Removing the wire between the sequence frame and the bundle node seem to decrease the memory usage according to the profiler. I tried to use show buffer allocations tool. It seems that this tool is not very informative with LVOOP as there were dots everywhere. Champion or not, I still don't understand LabVIEW memory management and the functionality of the in-placeness algorithm at the depth I'd like to. If only there was some material to read but I guess I've read all there is. p.s. Can you refer to some location such as Wikipedia where they describe this binary tree map algorithm you are using. Tomi -
"Get LV Class Default Value.vi" equivalent in 8.5
Tomi Maila replied to Jim Kring's topic in Object-Oriented Programming
QUOTE(Jim Kring @ Aug 23 2007, 01:19 AM) Not to my knowledge, no. What's your use case, there may be a work around. -
QUOTE(Ale914 @ Aug 22 2007, 12:13 PM) Teststand may be expensive but I doubt it's too complicated for unit testing.
-
QUOTE(alfa @ Aug 21 2007, 07:38 PM) I still have my Nakahara Geometry, Topology and Physics at my book shelf. An excellent book, as far as I still recall. I must admit I've forgotten almost everything I knew of manifolds and differential forms. Enjoy the seminar. Please tell us what are the hot topics in differential geometry this year after your visit.